Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duktape-1.5.2/src-noline/duktape.c
Go to the documentation of this file.
1/*
2 * Single source autogenerated distributable for Duktape 1.5.2.
3 *
4 * Git commit cad34ae155acb0846545ca6bf2d29f9463b22bbb (v1.5.2).
5 * Git branch HEAD.
6 *
7 * See Duktape AUTHORS.rst and LICENSE.txt for copyright and
8 * licensing information.
9 */
10
11/* LICENSE.txt */
12/*
13* ===============
14* Duktape license
15* ===============
16*
17* (http://opensource.org/licenses/MIT)
18*
19* Copyright (c) 2013-2016 by Duktape authors (see AUTHORS.rst)
20*
21* Permission is hereby granted, free of charge, to any person obtaining a copy
22* of this software and associated documentation files (the "Software"), to deal
23* in the Software without restriction, including without limitation the rights
24* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25* copies of the Software, and to permit persons to whom the Software is
26* furnished to do so, subject to the following conditions:
27*
28* The above copyright notice and this permission notice shall be included in
29* all copies or substantial portions of the Software.
30*
31* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37* THE SOFTWARE.
38*/
39/* AUTHORS.rst */
40/*
41* ===============
42* Duktape authors
43* ===============
44*
45* Copyright
46* =========
47*
48* Duktape copyrights are held by its authors. Each author has a copyright
49* to their contribution, and agrees to irrevocably license the contribution
50* under the Duktape ``LICENSE.txt``.
51*
52* Authors
53* =======
54*
55* Please include an e-mail address, a link to your GitHub profile, or something
56* similar to allow your contribution to be identified accurately.
57*
58* The following people have contributed code, website contents, or Wiki contents,
59* and agreed to irrevocably license their contributions under the Duktape
60* ``LICENSE.txt`` (in order of appearance):
61*
62* * Sami Vaarala <sami.vaarala@iki.fi>
63* * Niki Dobrev
64* * Andreas \u00d6man <andreas@lonelycoder.com>
65* * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
66* * Legimet <legimet.calc@gmail.com>
67* * Karl Skomski <karl@skomski.com>
68* * Bruce Pascoe <fatcerberus1@gmail.com>
69* * Ren\u00e9 Hollander <rene@rene8888.at>
70* * Julien Hamaide (https://github.com/crazyjul)
71* * Sebastian G\u00f6tte (https://github.com/jaseg)
72*
73* Other contributions
74* ===================
75*
76* The following people have contributed something other than code (e.g. reported
77* bugs, provided ideas, etc; roughly in order of appearance):
78*
79* * Greg Burns
80* * Anthony Rabine
81* * Carlos Costa
82* * Aur\u00e9lien Bouilland
83* * Preet Desai (Pris Matic)
84* * judofyr (http://www.reddit.com/user/judofyr)
85* * Jason Woofenden
86* * Micha\u0142 Przyby\u015b
87* * Anthony Howe
88* * Conrad Pankoff
89* * Jim Schimpf
90* * Rajaran Gaunker (https://github.com/zimbabao)
91* * Andreas \u00d6man
92* * Doug Sanden
93* * Josh Engebretson (https://github.com/JoshEngebretson)
94* * Remo Eichenberger (https://github.com/remoe)
95* * Mamod Mehyar (https://github.com/mamod)
96* * David Demelier (https://github.com/markand)
97* * Tim Caswell (https://github.com/creationix)
98* * Mitchell Blank Jr (https://github.com/mitchblank)
99* * https://github.com/yushli
100* * Seo Sanghyeon (https://github.com/sanxiyn)
101* * Han ChoongWoo (https://github.com/tunz)
102* * Joshua Peek (https://github.com/josh)
103* * Bruce E. Pascoe (https://github.com/fatcerberus)
104* * https://github.com/Kelledin
105* * https://github.com/sstruchtrup
106* * Michael Drake (https://github.com/tlsa)
107* * https://github.com/chris-y
108* * Laurent Zubiaur (https://github.com/lzubiaur)
109* * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
110*
111* If you are accidentally missing from this list, send me an e-mail
112* (``sami.vaarala@iki.fi``) and I'll fix the omission.
113*/
114/*
115 * Top-level include file to be used for all (internal) source files.
116 *
117 * Source files should not include individual header files, as they
118 * have not been designed to be individually included.
119 */
120
121#ifndef DUK_INTERNAL_H_INCLUDED
122#define DUK_INTERNAL_H_INCLUDED
123
124/*
125 * The 'duktape.h' header provides the public API, but also handles all
126 * compiler and platform specific feature detection, Duktape feature
127 * resolution, inclusion of system headers, etc. These have been merged
128 * because the public API is also dependent on e.g. detecting appropriate
129 * C types which is quite platform/compiler specific especially for a non-C99
130 * build. The public API is also dependent on the resolved feature set.
131 *
132 * Some actions taken by the merged header (such as including system headers)
133 * are not appropriate for building a user application. The define
134 * DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
135 * sections depending on what is being built.
136 */
137
138#define DUK_COMPILING_DUKTAPE
139#include "duktape.h"
140
141/*
142 * User declarations, e.g. prototypes for user functions used by Duktape
143 * macros. Concretely, if DUK_USE_PANIC_HANDLER is used and the macro
144 * value calls a user function, it needs to be declared for Duktape
145 * compilation to avoid warnings.
146 */
147
149
150/*
151 * Duktape includes (other than duk_features.h)
152 *
153 * The header files expect to be included in an order which satisfies header
154 * dependencies correctly (the headers themselves don't include any other
155 * includes). Forward declarations are used to break circular struct/typedef
156 * dependencies.
157 */
158
159#ifndef DUK_REPLACEMENTS_H_INCLUDED
160#define DUK_REPLACEMENTS_H_INCLUDED
161
162#if !defined(DUK_SINGLE_FILE)
163#if defined(DUK_USE_COMPUTED_INFINITY)
164DUK_INTERNAL_DECL double duk_computed_infinity;
165#endif
166#if defined(DUK_USE_COMPUTED_NAN)
167DUK_INTERNAL_DECL double duk_computed_nan;
168#endif
169#if defined(DUK_USE_REPL_FPCLASSIFY)
171#endif
172#if defined(DUK_USE_REPL_SIGNBIT)
174#endif
175#if defined(DUK_USE_REPL_ISFINITE)
177#endif
178#if defined(DUK_USE_REPL_ISNAN)
180#endif
181#if defined(DUK_USE_REPL_ISINF)
183#endif
184#endif /* !DUK_SINGLE_FILE */
185
186#endif /* DUK_REPLACEMENTS_H_INCLUDED */
187/*
188 * Wrapper for jmp_buf.
189 *
190 * This is used because jmp_buf is an array type for backward compatibility.
191 * Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
192 * behave more intuitively.
193 *
194 * http://en.wikipedia.org/wiki/Setjmp.h#Member_types
195 */
196
197#ifndef DUK_JMPBUF_H_INCLUDED
198#define DUK_JMPBUF_H_INCLUDED
199
200#if defined(DUK_USE_CPP_EXCEPTIONS)
201struct duk_jmpbuf {
202 duk_small_int_t dummy; /* unused */
203};
204#else
208#endif
209
210#endif /* DUK_JMPBUF_H_INCLUDED */
211/*
212 * Exception for Duktape internal throws when C++ exceptions are used
213 * for long control transfers.
214 *
215 * Doesn't inherit from any exception base class to minimize the chance
216 * that user code would accidentally catch this exception.
217 */
218
219#ifndef DUK_EXCEPTION_H_INCLUDED
220#define DUK_EXCEPTION_H_INCLUDED
221
222#if defined(DUK_USE_CPP_EXCEPTIONS)
223class duk_internal_exception {
224 /* intentionally empty */
225};
226#endif
227
228#endif /* DUK_EXCEPTION_H_INCLUDED */
229/*
230 * Forward declarations for all Duktape structures.
231 */
232
233#ifndef DUK_FORWDECL_H_INCLUDED
234#define DUK_FORWDECL_H_INCLUDED
235
236/*
237 * Forward declarations
238 */
239
240#if defined(DUK_USE_CPP_EXCEPTIONS)
241class duk_internal_exception;
242#else
243struct duk_jmpbuf;
244#endif
245
246/* duk_tval intentionally skipped */
247struct duk_heaphdr;
248struct duk_heaphdr_string;
249struct duk_hstring;
251struct duk_hobject;
254struct duk_hthread;
255struct duk_hbufferobject;
256struct duk_hbuffer;
257struct duk_hbuffer_fixed;
260
261struct duk_propaccessor;
262union duk_propvalue;
263struct duk_propdesc;
264
265struct duk_heap;
266struct duk_breakpoint;
267
268struct duk_activation;
269struct duk_catcher;
270struct duk_strcache;
271struct duk_ljstate;
272struct duk_strtab_entry;
273
274#ifdef DUK_USE_DEBUG
275struct duk_fixedbuffer;
276#endif
277
278struct duk_bitdecoder_ctx;
279struct duk_bitencoder_ctx;
280struct duk_bufwriter_ctx;
281
282struct duk_token;
283struct duk_re_token;
284struct duk_lexer_point;
285struct duk_lexer_ctx;
287
288struct duk_compiler_instr;
289struct duk_compiler_func;
290struct duk_compiler_ctx;
291
292struct duk_re_matcher_ctx;
294
295#if defined(DUK_USE_CPP_EXCEPTIONS)
296/* no typedef */
297#else
298typedef struct duk_jmpbuf duk_jmpbuf;
299#endif
300
301/* duk_tval intentionally skipped */
315
319
320typedef struct duk_heap duk_heap;
322
328
329#ifdef DUK_USE_DEBUG
330typedef struct duk_fixedbuffer duk_fixedbuffer;
331#endif
332
336
337typedef struct duk_token duk_token;
342
346
349
350#endif /* DUK_FORWDECL_H_INCLUDED */
351/*
352 * Tagged type definition (duk_tval) and accessor macros.
353 *
354 * Access all fields through the accessor macros, as the representation
355 * is quite tricky.
356 *
357 * There are two packed type alternatives: an 8-byte representation
358 * based on an IEEE double (preferred for compactness), and a 12-byte
359 * representation (portability). The latter is needed also in e.g.
360 * 64-bit environments (it usually pads to 16 bytes per value).
361 *
362 * Selecting the tagged type format involves many trade-offs (memory
363 * use, size and performance of generated code, portability, etc),
364 * see doc/types.rst for a detailed discussion (especially of how the
365 * IEEE double format is used to pack tagged values).
366 *
367 * NB: because macro arguments are often expressions, macros should
368 * avoid evaluating their argument more than once.
369 */
370
371#ifndef DUK_TVAL_H_INCLUDED
372#define DUK_TVAL_H_INCLUDED
373
374/* sanity */
375#if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
376#error unsupported: cannot determine byte order variant
377#endif
378
379#if defined(DUK_USE_PACKED_TVAL)
380/* ======================================================================== */
381
382/*
383 * Packed 8-byte representation
384 */
385
386/* use duk_double_union as duk_tval directly */
387typedef union duk_double_union duk_tval;
388
389/* tags */
390#define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
391/* avoid tag 0xfff0, no risk of confusion with negative infinity */
392#if defined(DUK_USE_FASTINT)
393#define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
394#endif
395#define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */
396#define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */
397#define DUK_TAG_NULL 0xfff4UL /* embed: nothing */
398#define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */
399/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
400#define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */
401#define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */
402#define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */
403#define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */
404#define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */
405
406/* for convenience */
407#define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL
408#define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL
409
410/* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
411#if defined(DUK_USE_64BIT_OPS)
412#if defined(DUK_USE_DOUBLE_ME)
413#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
414 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
415 } while (0)
416#else
417#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
418 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
419 } while (0)
420#endif
421#else /* DUK_USE_64BIT_OPS */
422#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
423 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
424 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
425 } while (0)
426#endif /* DUK_USE_64BIT_OPS */
427
428#if defined(DUK_USE_64BIT_OPS)
429/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
430#if defined(DUK_USE_DOUBLE_ME)
431#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
432 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
433 ((duk_uint64_t) (flags)) | \
434 (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
435 } while (0)
436#else
437#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
438 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
439 (((duk_uint64_t) (flags)) << 32) | \
440 ((duk_uint64_t) (duk_uint32_t) (fp)); \
441 } while (0)
442#endif
443#else /* DUK_USE_64BIT_OPS */
444#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
445 (v)->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
446 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
447 } while (0)
448#endif /* DUK_USE_64BIT_OPS */
449
450#if defined(DUK_USE_FASTINT)
451/* Note: masking is done for 'i' to deal with negative numbers correctly */
452#if defined(DUK_USE_DOUBLE_ME)
453#define DUK__TVAL_SET_FASTINT(v,i) do { \
454 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
455 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
456 } while (0)
457#define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
458 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
459 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
460 } while (0)
461#else
462#define DUK__TVAL_SET_FASTINT(v,i) do { \
463 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & 0x0000ffffffffffffULL); \
464 } while (0)
465#define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
466 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
467 } while (0)
468#endif
469
470#define DUK__TVAL_SET_FASTINT_I32(v,i) do { \
471 duk_int64_t duk__tmp = (duk_int64_t) (i); \
472 DUK_TVAL_SET_FASTINT((v), duk__tmp); \
473 } while (0)
474
475/* XXX: clumsy sign extend and masking of 16 topmost bits */
476#if defined(DUK_USE_DOUBLE_ME)
477#define DUK__TVAL_GET_FASTINT(v) (((duk_int64_t) ((((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
478#else
479#define DUK__TVAL_GET_FASTINT(v) ((((duk_int64_t) (v)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
480#endif
481#define DUK__TVAL_GET_FASTINT_U32(v) ((v)->ui[DUK_DBL_IDX_UI1])
482#define DUK__TVAL_GET_FASTINT_I32(v) ((duk_int32_t) (v)->ui[DUK_DBL_IDX_UI1])
483#endif /* DUK_USE_FASTINT */
484
485#define DUK_TVAL_SET_UNDEFINED(v) do { \
486 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
487 } while (0)
488#define DUK_TVAL_SET_UNUSED(v) do { \
489 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
490 } while (0)
491#define DUK_TVAL_SET_NULL(v) do { \
492 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
493 } while (0)
494
495#define DUK_TVAL_SET_BOOLEAN(v,val) DUK_DBLUNION_SET_HIGH32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
496
497#define DUK_TVAL_SET_NAN(v) DUK_DBLUNION_SET_NAN_FULL((v))
498
499/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
500#if defined(DUK_USE_FASTINT)
501#define DUK_TVAL_SET_DOUBLE(v,d) do { \
502 duk_double_t duk__dblval; \
503 duk__dblval = (d); \
504 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
505 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
506 } while (0)
507#define DUK_TVAL_SET_FASTINT(v,i) DUK__TVAL_SET_FASTINT((v), (i))
508#define DUK_TVAL_SET_FASTINT_I32(v,i) DUK__TVAL_SET_FASTINT_I32((v), (i))
509#define DUK_TVAL_SET_FASTINT_U32(v,i) DUK__TVAL_SET_FASTINT_U32((v), (i))
510#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) duk_tval_set_number_chkfast((v), (d))
511#define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
512#define DUK_TVAL_CHKFAST_INPLACE(v) do { \
513 duk_tval *duk__tv; \
514 duk_double_t duk__d; \
515 duk__tv = (v); \
516 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
517 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
518 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
519 } \
520 } while (0)
521#else
522#define DUK_TVAL_SET_DOUBLE(v,d) do { \
523 duk_double_t duk__dblval; \
524 duk__dblval = (d); \
525 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
526 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
527 } while (0)
528#define DUK_TVAL_SET_FASTINT(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i)) /* XXX: fast int-to-double */
529#define DUK_TVAL_SET_FASTINT_I32(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
530#define DUK_TVAL_SET_FASTINT_U32(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
531#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
532#define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
533#define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
534#endif
535
536#define DUK_TVAL_SET_LIGHTFUNC(v,fp,flags) DUK__TVAL_SET_LIGHTFUNC((v), (fp), (flags))
537#define DUK_TVAL_SET_STRING(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_STRING)
538#define DUK_TVAL_SET_OBJECT(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_OBJECT)
539#define DUK_TVAL_SET_BUFFER(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_BUFFER)
540#define DUK_TVAL_SET_POINTER(v,p) DUK__TVAL_SET_TAGGEDPOINTER((v), (p), DUK_TAG_POINTER)
541
542#define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
543
544/* getters */
545#define DUK_TVAL_GET_BOOLEAN(v) ((int) (v)->us[DUK_DBL_IDX_US1])
546#if defined(DUK_USE_FASTINT)
547#define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
548#define DUK_TVAL_GET_FASTINT(v) DUK__TVAL_GET_FASTINT((v))
549#define DUK_TVAL_GET_FASTINT_U32(v) DUK__TVAL_GET_FASTINT_U32((v))
550#define DUK_TVAL_GET_FASTINT_I32(v) DUK__TVAL_GET_FASTINT_I32((v))
551#define DUK_TVAL_GET_NUMBER(v) duk_tval_get_number_packed((v))
552#else
553#define DUK_TVAL_GET_NUMBER(v) ((v)->d)
554#define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
555#endif
556#define DUK_TVAL_GET_LIGHTFUNC(v,out_fp,out_flags) do { \
557 (out_flags) = (v)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
558 (out_fp) = (duk_c_function) (v)->ui[DUK_DBL_IDX_UI1]; \
559 } while (0)
560#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(v) ((duk_c_function) ((v)->ui[DUK_DBL_IDX_UI1]))
561#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(v) (((int) (v)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
562#define DUK_TVAL_GET_STRING(v) ((duk_hstring *) (v)->vp[DUK_DBL_IDX_VP1])
563#define DUK_TVAL_GET_OBJECT(v) ((duk_hobject *) (v)->vp[DUK_DBL_IDX_VP1])
564#define DUK_TVAL_GET_BUFFER(v) ((duk_hbuffer *) (v)->vp[DUK_DBL_IDX_VP1])
565#define DUK_TVAL_GET_POINTER(v) ((void *) (v)->vp[DUK_DBL_IDX_VP1])
566#define DUK_TVAL_GET_HEAPHDR(v) ((duk_heaphdr *) (v)->vp[DUK_DBL_IDX_VP1])
567
568/* decoding */
569#define DUK_TVAL_GET_TAG(v) ((duk_small_uint_t) (v)->us[DUK_DBL_IDX_US0])
570
571#define DUK_TVAL_IS_UNDEFINED(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNDEFINED)
572#define DUK_TVAL_IS_UNUSED(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNUSED)
573#define DUK_TVAL_IS_NULL(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_NULL)
574#define DUK_TVAL_IS_BOOLEAN(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BOOLEAN)
575#define DUK_TVAL_IS_BOOLEAN_TRUE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
576#define DUK_TVAL_IS_BOOLEAN_FALSE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
577#define DUK_TVAL_IS_LIGHTFUNC(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_LIGHTFUNC)
578#define DUK_TVAL_IS_STRING(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_STRING)
579#define DUK_TVAL_IS_OBJECT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_OBJECT)
580#define DUK_TVAL_IS_BUFFER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BUFFER)
581#define DUK_TVAL_IS_POINTER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_POINTER)
582#if defined(DUK_USE_FASTINT)
583/* 0xfff0 is -Infinity */
584#define DUK_TVAL_IS_DOUBLE(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
585#define DUK_TVAL_IS_FASTINT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_FASTINT)
586#define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff1UL)
587#else
588#define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
589#define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
590#endif
591
592/* This is performance critical because it appears in every DECREF. */
593#define DUK_TVAL_IS_HEAP_ALLOCATED(v) (DUK_TVAL_GET_TAG((v)) >= DUK_TAG_STRING)
594
595#if defined(DUK_USE_FASTINT)
596DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
597#endif
598
599#else /* DUK_USE_PACKED_TVAL */
600/* ======================================================================== */
601
602/*
603 * Portable 12-byte representation
604 */
605
606/* Note: not initializing all bytes is normally not an issue: Duktape won't
607 * read or use the uninitialized bytes so valgrind won't issue warnings.
608 * In some special cases a harmless valgrind warning may be issued though.
609 * For example, the DumpHeap debugger command writes out a compiled function's
610 * 'data' area as is, including any uninitialized bytes, which causes a
611 * valgrind warning.
612 */
613
615
636
637#define DUK__TAG_NUMBER 0 /* not exposed */
638#if defined(DUK_USE_FASTINT)
639#define DUK_TAG_FASTINT 1
640#endif
641#define DUK_TAG_UNDEFINED 2
642#define DUK_TAG_NULL 3
643#define DUK_TAG_BOOLEAN 4
644#define DUK_TAG_POINTER 5
645#define DUK_TAG_LIGHTFUNC 6
646#define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */
647#define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */
648#define DUK_TAG_OBJECT 9
649#define DUK_TAG_BUFFER 10
650
651/* DUK__TAG_NUMBER is intentionally first, as it is the default clause in code
652 * to support the 8-byte representation. Further, it is a non-heap-allocated
653 * type so it should come before DUK_TAG_STRING. Finally, it should not break
654 * the tag value ranges covered by case-clauses in a switch-case.
655 */
656
657/* setters */
658#define DUK_TVAL_SET_UNDEFINED(tv) do { \
659 (tv)->t = DUK_TAG_UNDEFINED; \
660 } while (0)
661
662#define DUK_TVAL_SET_UNUSED(tv) do { \
663 (tv)->t = DUK_TAG_UNUSED; \
664 } while (0)
665
666#define DUK_TVAL_SET_NULL(tv) do { \
667 (tv)->t = DUK_TAG_NULL; \
668 } while (0)
669
670#define DUK_TVAL_SET_BOOLEAN(tv,val) do { \
671 (tv)->t = DUK_TAG_BOOLEAN; \
672 (tv)->v.i = (val); \
673 } while (0)
674
675#if defined(DUK_USE_FASTINT)
676#define DUK_TVAL_SET_DOUBLE(tv,val) do { \
677 (tv)->t = DUK__TAG_NUMBER; \
678 (tv)->v.d = (val); \
679 } while (0)
680#define DUK_TVAL_SET_FASTINT(tv,val) do { \
681 (tv)->t = DUK_TAG_FASTINT; \
682 (tv)->v.fi = (val); \
683 } while (0)
684#define DUK_TVAL_SET_FASTINT_U32(tv,val) do { \
685 (tv)->t = DUK_TAG_FASTINT; \
686 (tv)->v.fi = (duk_int64_t) (val); \
687 } while (0)
688#define DUK_TVAL_SET_FASTINT_I32(tv,val) do { \
689 (tv)->t = DUK_TAG_FASTINT; \
690 (tv)->v.fi = (duk_int64_t) (val); \
691 } while (0)
692#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
693 duk_tval_set_number_chkfast((tv), (d))
694#define DUK_TVAL_SET_NUMBER(tv,val) \
695 DUK_TVAL_SET_DOUBLE((tv), (val))
696#define DUK_TVAL_CHKFAST_INPLACE(v) do { \
697 duk_tval *duk__tv; \
698 duk_double_t duk__d; \
699 duk__tv = (v); \
700 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
701 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
702 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
703 } \
704 } while (0)
705#else
706#define DUK_TVAL_SET_DOUBLE(tv,d) \
707 DUK_TVAL_SET_NUMBER((tv), (d))
708#define DUK_TVAL_SET_FASTINT(tv,val) \
709 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */
710#define DUK_TVAL_SET_FASTINT_U32(tv,val) \
711 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
712#define DUK_TVAL_SET_FASTINT_I32(tv,val) \
713 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
714#define DUK_TVAL_SET_NUMBER(tv,val) do { \
715 (tv)->t = DUK__TAG_NUMBER; \
716 (tv)->v.d = (val); \
717 } while (0)
718#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
719 DUK_TVAL_SET_NUMBER((tv), (d))
720#define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
721#endif /* DUK_USE_FASTINT */
722
723#define DUK_TVAL_SET_POINTER(tv,hptr) do { \
724 (tv)->t = DUK_TAG_POINTER; \
725 (tv)->v.voidptr = (hptr); \
726 } while (0)
727
728#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
729 (tv)->t = DUK_TAG_LIGHTFUNC; \
730 (tv)->v_extra = (flags); \
731 (tv)->v.lightfunc = (duk_c_function) (fp); \
732 } while (0)
733
734#define DUK_TVAL_SET_STRING(tv,hptr) do { \
735 (tv)->t = DUK_TAG_STRING; \
736 (tv)->v.hstring = (hptr); \
737 } while (0)
738
739#define DUK_TVAL_SET_OBJECT(tv,hptr) do { \
740 (tv)->t = DUK_TAG_OBJECT; \
741 (tv)->v.hobject = (hptr); \
742 } while (0)
743
744#define DUK_TVAL_SET_BUFFER(tv,hptr) do { \
745 (tv)->t = DUK_TAG_BUFFER; \
746 (tv)->v.hbuffer = (hptr); \
747 } while (0)
748
749#define DUK_TVAL_SET_NAN(tv) do { \
750 /* in non-packed representation we don't care about which NaN is used */ \
751 (tv)->t = DUK__TAG_NUMBER; \
752 (tv)->v.d = DUK_DOUBLE_NAN; \
753 } while (0)
754
755#define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
756
757/* getters */
758#define DUK_TVAL_GET_BOOLEAN(tv) ((tv)->v.i)
759#if defined(DUK_USE_FASTINT)
760#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
761#define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
762#define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
763#define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
764#if 0
765#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
766 (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
767 DUK_TVAL_GET_DOUBLE((tv)))
768#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
769#else
770/* This seems reasonable overall. */
771#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
772 duk_tval_get_number_unpacked_fastint((tv)) : \
773 DUK_TVAL_GET_DOUBLE((tv)))
774#endif
775#else
776#define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
777#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
778#endif /* DUK_USE_FASTINT */
779#define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
780#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
781 (out_flags) = (duk_uint32_t) (tv)->v_extra; \
782 (out_fp) = (tv)->v.lightfunc; \
783 } while (0)
784#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
785#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) ((duk_uint32_t) ((tv)->v_extra))
786#define DUK_TVAL_GET_STRING(tv) ((tv)->v.hstring)
787#define DUK_TVAL_GET_OBJECT(tv) ((tv)->v.hobject)
788#define DUK_TVAL_GET_BUFFER(tv) ((tv)->v.hbuffer)
789#define DUK_TVAL_GET_HEAPHDR(tv) ((tv)->v.heaphdr)
790
791/* decoding */
792#define DUK_TVAL_GET_TAG(tv) ((tv)->t)
793#define DUK_TVAL_IS_UNDEFINED(tv) ((tv)->t == DUK_TAG_UNDEFINED)
794#define DUK_TVAL_IS_UNUSED(tv) ((tv)->t == DUK_TAG_UNUSED)
795#define DUK_TVAL_IS_NULL(tv) ((tv)->t == DUK_TAG_NULL)
796#define DUK_TVAL_IS_BOOLEAN(tv) ((tv)->t == DUK_TAG_BOOLEAN)
797#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
798#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
799#if defined(DUK_USE_FASTINT)
800#define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK__TAG_NUMBER)
801#define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
802#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER || \
803 (tv)->t == DUK_TAG_FASTINT)
804#else
805#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER)
806#define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
807#endif /* DUK_USE_FASTINT */
808#define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
809#define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
810#define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
811#define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
812#define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
813
814/* This is performance critical because it's needed for every DECREF.
815 * Take advantage of the fact that the first heap allocated tag is 8,
816 * so that bit 3 is set for all heap allocated tags (and never set for
817 * non-heap-allocated tags).
818 */
819#if 0
820#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
821#endif
822#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08)
823
824#if defined(DUK_USE_FASTINT)
825#if 0
826DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
827#endif
828DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
829#endif
830
831#endif /* DUK_USE_PACKED_TVAL */
832
833/*
834 * Convenience (independent of representation)
835 */
836
837#define DUK_TVAL_SET_BOOLEAN_TRUE(v) DUK_TVAL_SET_BOOLEAN(v, 1)
838#define DUK_TVAL_SET_BOOLEAN_FALSE(v) DUK_TVAL_SET_BOOLEAN(v, 0)
839
840/* Lightfunc flags packing and unpacking. */
841/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss## */
842#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
843 ((((duk_int32_t) (lf_flags)) << 16) >> 24)
844#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
845 (((lf_flags) >> 4) & 0x0f)
846#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
847 ((lf_flags) & 0x0f)
848#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
849 (((magic) & 0xff) << 8) | ((length) << 4) | (nargs)
850
851#define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
852#define DUK_LFUNC_NARGS_MIN 0x00
853#define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
854#define DUK_LFUNC_LENGTH_MIN 0x00
855#define DUK_LFUNC_LENGTH_MAX 0x0f
856#define DUK_LFUNC_MAGIC_MIN (-0x80)
857#define DUK_LFUNC_MAGIC_MAX 0x7f
858
859/* fastint constants etc */
860#if defined(DUK_USE_FASTINT)
861#define DUK_FASTINT_MIN (-0x800000000000LL)
862#define DUK_FASTINT_MAX 0x7fffffffffffLL
863#define DUK_FASTINT_BITS 48
864
865DUK_INTERNAL_DECL void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x);
866#endif
867
868#endif /* DUK_TVAL_H_INCLUDED */
869/*
870 * Automatically generated by genbuiltins.py, do not edit!
871 */
872
873#ifndef DUK_BUILTINS_H_INCLUDED
874#define DUK_BUILTINS_H_INCLUDED
875
876#if defined(DUK_USE_ROM_STRINGS)
877#error ROM support not enabled, rerun make_dist.py with --rom-support
878#else /* DUK_USE_ROM_STRINGS */
879#define DUK_STRIDX_UC_UNDEFINED 0 /* 'Undefined' */
880#define DUK_HEAP_STRING_UC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
881#define DUK_HTHREAD_STRING_UC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
882#define DUK_STRIDX_UC_NULL 1 /* 'Null' */
883#define DUK_HEAP_STRING_UC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
884#define DUK_HTHREAD_STRING_UC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
885#define DUK_STRIDX_UC_ARGUMENTS 2 /* 'Arguments' */
886#define DUK_HEAP_STRING_UC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
887#define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
888#define DUK_STRIDX_UC_OBJECT 3 /* 'Object' */
889#define DUK_HEAP_STRING_UC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
890#define DUK_HTHREAD_STRING_UC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
891#define DUK_STRIDX_UC_FUNCTION 4 /* 'Function' */
892#define DUK_HEAP_STRING_UC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
893#define DUK_HTHREAD_STRING_UC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
894#define DUK_STRIDX_ARRAY 5 /* 'Array' */
895#define DUK_HEAP_STRING_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
896#define DUK_HTHREAD_STRING_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
897#define DUK_STRIDX_UC_STRING 6 /* 'String' */
898#define DUK_HEAP_STRING_UC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
899#define DUK_HTHREAD_STRING_UC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
900#define DUK_STRIDX_UC_BOOLEAN 7 /* 'Boolean' */
901#define DUK_HEAP_STRING_UC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
902#define DUK_HTHREAD_STRING_UC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
903#define DUK_STRIDX_UC_NUMBER 8 /* 'Number' */
904#define DUK_HEAP_STRING_UC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
905#define DUK_HTHREAD_STRING_UC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
906#define DUK_STRIDX_DATE 9 /* 'Date' */
907#define DUK_HEAP_STRING_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
908#define DUK_HTHREAD_STRING_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
909#define DUK_STRIDX_REG_EXP 10 /* 'RegExp' */
910#define DUK_HEAP_STRING_REG_EXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
911#define DUK_HTHREAD_STRING_REG_EXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
912#define DUK_STRIDX_UC_ERROR 11 /* 'Error' */
913#define DUK_HEAP_STRING_UC_ERROR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
914#define DUK_HTHREAD_STRING_UC_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
915#define DUK_STRIDX_MATH 12 /* 'Math' */
916#define DUK_HEAP_STRING_MATH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
917#define DUK_HTHREAD_STRING_MATH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
918#define DUK_STRIDX_JSON 13 /* 'JSON' */
919#define DUK_HEAP_STRING_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
920#define DUK_HTHREAD_STRING_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
921#define DUK_STRIDX_EMPTY_STRING 14 /* '' */
922#define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
923#define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
924#define DUK_STRIDX_ARRAY_BUFFER 15 /* 'ArrayBuffer' */
925#define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
926#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
927#define DUK_STRIDX_DATA_VIEW 16 /* 'DataView' */
928#define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
929#define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
930#define DUK_STRIDX_INT8_ARRAY 17 /* 'Int8Array' */
931#define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
932#define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
933#define DUK_STRIDX_UINT8_ARRAY 18 /* 'Uint8Array' */
934#define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
935#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
936#define DUK_STRIDX_UINT8_CLAMPED_ARRAY 19 /* 'Uint8ClampedArray' */
937#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
938#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
939#define DUK_STRIDX_INT16_ARRAY 20 /* 'Int16Array' */
940#define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
941#define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
942#define DUK_STRIDX_UINT16_ARRAY 21 /* 'Uint16Array' */
943#define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
944#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
945#define DUK_STRIDX_INT32_ARRAY 22 /* 'Int32Array' */
946#define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
947#define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
948#define DUK_STRIDX_UINT32_ARRAY 23 /* 'Uint32Array' */
949#define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
950#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
951#define DUK_STRIDX_FLOAT32_ARRAY 24 /* 'Float32Array' */
952#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
953#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
954#define DUK_STRIDX_FLOAT64_ARRAY 25 /* 'Float64Array' */
955#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
956#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
957#define DUK_STRIDX_GLOBAL 26 /* 'global' */
958#define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
959#define DUK_HTHREAD_STRING_GLOBAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
960#define DUK_STRIDX_OBJ_ENV 27 /* 'ObjEnv' */
961#define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
962#define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
963#define DUK_STRIDX_DEC_ENV 28 /* 'DecEnv' */
964#define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
965#define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
966#define DUK_STRIDX_UC_BUFFER 29 /* 'Buffer' */
967#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
968#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
969#define DUK_STRIDX_UC_POINTER 30 /* 'Pointer' */
970#define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
971#define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
972#define DUK_STRIDX_UC_THREAD 31 /* 'Thread' */
973#define DUK_HEAP_STRING_UC_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
974#define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
975#define DUK_STRIDX_EVAL 32 /* 'eval' */
976#define DUK_HEAP_STRING_EVAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
977#define DUK_HTHREAD_STRING_EVAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
978#define DUK_STRIDX_DEFINE_PROPERTY 33 /* 'defineProperty' */
979#define DUK_HEAP_STRING_DEFINE_PROPERTY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFINE_PROPERTY)
980#define DUK_HTHREAD_STRING_DEFINE_PROPERTY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFINE_PROPERTY)
981#define DUK_STRIDX_VALUE 34 /* 'value' */
982#define DUK_HEAP_STRING_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
983#define DUK_HTHREAD_STRING_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
984#define DUK_STRIDX_WRITABLE 35 /* 'writable' */
985#define DUK_HEAP_STRING_WRITABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
986#define DUK_HTHREAD_STRING_WRITABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
987#define DUK_STRIDX_CONFIGURABLE 36 /* 'configurable' */
988#define DUK_HEAP_STRING_CONFIGURABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
989#define DUK_HTHREAD_STRING_CONFIGURABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
990#define DUK_STRIDX_ENUMERABLE 37 /* 'enumerable' */
991#define DUK_HEAP_STRING_ENUMERABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
992#define DUK_HTHREAD_STRING_ENUMERABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
993#define DUK_STRIDX_JOIN 38 /* 'join' */
994#define DUK_HEAP_STRING_JOIN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
995#define DUK_HTHREAD_STRING_JOIN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
996#define DUK_STRIDX_TO_LOCALE_STRING 39 /* 'toLocaleString' */
997#define DUK_HEAP_STRING_TO_LOCALE_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
998#define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
999#define DUK_STRIDX_VALUE_OF 40 /* 'valueOf' */
1000#define DUK_HEAP_STRING_VALUE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1001#define DUK_HTHREAD_STRING_VALUE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1002#define DUK_STRIDX_TO_UTC_STRING 41 /* 'toUTCString' */
1003#define DUK_HEAP_STRING_TO_UTC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1004#define DUK_HTHREAD_STRING_TO_UTC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1005#define DUK_STRIDX_TO_ISO_STRING 42 /* 'toISOString' */
1006#define DUK_HEAP_STRING_TO_ISO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1007#define DUK_HTHREAD_STRING_TO_ISO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1008#define DUK_STRIDX_TO_GMT_STRING 43 /* 'toGMTString' */
1009#define DUK_HEAP_STRING_TO_GMT_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1010#define DUK_HTHREAD_STRING_TO_GMT_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1011#define DUK_STRIDX_SOURCE 44 /* 'source' */
1012#define DUK_HEAP_STRING_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1013#define DUK_HTHREAD_STRING_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1014#define DUK_STRIDX_IGNORE_CASE 45 /* 'ignoreCase' */
1015#define DUK_HEAP_STRING_IGNORE_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1016#define DUK_HTHREAD_STRING_IGNORE_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1017#define DUK_STRIDX_MULTILINE 46 /* 'multiline' */
1018#define DUK_HEAP_STRING_MULTILINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1019#define DUK_HTHREAD_STRING_MULTILINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1020#define DUK_STRIDX_LAST_INDEX 47 /* 'lastIndex' */
1021#define DUK_HEAP_STRING_LAST_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1022#define DUK_HTHREAD_STRING_LAST_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1023#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 48 /* '(?:)' */
1024#define DUK_HEAP_STRING_ESCAPED_EMPTY_REGEXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ESCAPED_EMPTY_REGEXP)
1025#define DUK_HTHREAD_STRING_ESCAPED_EMPTY_REGEXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ESCAPED_EMPTY_REGEXP)
1026#define DUK_STRIDX_INDEX 49 /* 'index' */
1027#define DUK_HEAP_STRING_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1028#define DUK_HTHREAD_STRING_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1029#define DUK_STRIDX_PROTOTYPE 50 /* 'prototype' */
1030#define DUK_HEAP_STRING_PROTOTYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1031#define DUK_HTHREAD_STRING_PROTOTYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1032#define DUK_STRIDX_CONSTRUCTOR 51 /* 'constructor' */
1033#define DUK_HEAP_STRING_CONSTRUCTOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1034#define DUK_HTHREAD_STRING_CONSTRUCTOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1035#define DUK_STRIDX_MESSAGE 52 /* 'message' */
1036#define DUK_HEAP_STRING_MESSAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1037#define DUK_HTHREAD_STRING_MESSAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1038#define DUK_STRIDX_LC_BOOLEAN 53 /* 'boolean' */
1039#define DUK_HEAP_STRING_LC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1040#define DUK_HTHREAD_STRING_LC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1041#define DUK_STRIDX_LC_NUMBER 54 /* 'number' */
1042#define DUK_HEAP_STRING_LC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1043#define DUK_HTHREAD_STRING_LC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1044#define DUK_STRIDX_LC_STRING 55 /* 'string' */
1045#define DUK_HEAP_STRING_LC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1046#define DUK_HTHREAD_STRING_LC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1047#define DUK_STRIDX_LC_OBJECT 56 /* 'object' */
1048#define DUK_HEAP_STRING_LC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1049#define DUK_HTHREAD_STRING_LC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1050#define DUK_STRIDX_LC_UNDEFINED 57 /* 'undefined' */
1051#define DUK_HEAP_STRING_LC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1052#define DUK_HTHREAD_STRING_LC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1053#define DUK_STRIDX_NAN 58 /* 'NaN' */
1054#define DUK_HEAP_STRING_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1055#define DUK_HTHREAD_STRING_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1056#define DUK_STRIDX_INFINITY 59 /* 'Infinity' */
1057#define DUK_HEAP_STRING_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1058#define DUK_HTHREAD_STRING_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1059#define DUK_STRIDX_MINUS_INFINITY 60 /* '-Infinity' */
1060#define DUK_HEAP_STRING_MINUS_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1061#define DUK_HTHREAD_STRING_MINUS_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1062#define DUK_STRIDX_MINUS_ZERO 61 /* '-0' */
1063#define DUK_HEAP_STRING_MINUS_ZERO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1064#define DUK_HTHREAD_STRING_MINUS_ZERO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1065#define DUK_STRIDX_COMMA 62 /* ',' */
1066#define DUK_HEAP_STRING_COMMA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1067#define DUK_HTHREAD_STRING_COMMA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1068#define DUK_STRIDX_SPACE 63 /* ' ' */
1069#define DUK_HEAP_STRING_SPACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SPACE)
1070#define DUK_HTHREAD_STRING_SPACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SPACE)
1071#define DUK_STRIDX_NEWLINE_4SPACE 64 /* '\n ' */
1072#define DUK_HEAP_STRING_NEWLINE_4SPACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1073#define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1074#define DUK_STRIDX_BRACKETED_ELLIPSIS 65 /* '[...]' */
1075#define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1076#define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1077#define DUK_STRIDX_INVALID_DATE 66 /* 'Invalid Date' */
1078#define DUK_HEAP_STRING_INVALID_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1079#define DUK_HTHREAD_STRING_INVALID_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1080#define DUK_STRIDX_LC_ARGUMENTS 67 /* 'arguments' */
1081#define DUK_HEAP_STRING_LC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1082#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1083#define DUK_STRIDX_CALLEE 68 /* 'callee' */
1084#define DUK_HEAP_STRING_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1085#define DUK_HTHREAD_STRING_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1086#define DUK_STRIDX_CALLER 69 /* 'caller' */
1087#define DUK_HEAP_STRING_CALLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1088#define DUK_HTHREAD_STRING_CALLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1089#define DUK_STRIDX_HAS 70 /* 'has' */
1090#define DUK_HEAP_STRING_HAS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1091#define DUK_HTHREAD_STRING_HAS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1092#define DUK_STRIDX_GET 71 /* 'get' */
1093#define DUK_HEAP_STRING_GET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1094#define DUK_HTHREAD_STRING_GET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1095#define DUK_STRIDX_DELETE_PROPERTY 72 /* 'deleteProperty' */
1096#define DUK_HEAP_STRING_DELETE_PROPERTY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1097#define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1098#define DUK_STRIDX_ENUMERATE 73 /* 'enumerate' */
1099#define DUK_HEAP_STRING_ENUMERATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERATE)
1100#define DUK_HTHREAD_STRING_ENUMERATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERATE)
1101#define DUK_STRIDX_OWN_KEYS 74 /* 'ownKeys' */
1102#define DUK_HEAP_STRING_OWN_KEYS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1103#define DUK_HTHREAD_STRING_OWN_KEYS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1104#define DUK_STRIDX_SET_PROTOTYPE_OF 75 /* 'setPrototypeOf' */
1105#define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1106#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1107#define DUK_STRIDX___PROTO__ 76 /* '__proto__' */
1108#define DUK_HEAP_STRING___PROTO__(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1109#define DUK_HTHREAD_STRING___PROTO__(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1110#define DUK_STRIDX_REQUIRE 77 /* 'require' */
1111#define DUK_HEAP_STRING_REQUIRE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE)
1112#define DUK_HTHREAD_STRING_REQUIRE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REQUIRE)
1113#define DUK_STRIDX_ID 78 /* 'id' */
1114#define DUK_HEAP_STRING_ID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID)
1115#define DUK_HTHREAD_STRING_ID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID)
1116#define DUK_STRIDX_EXPORTS 79 /* 'exports' */
1117#define DUK_HEAP_STRING_EXPORTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS)
1118#define DUK_HTHREAD_STRING_EXPORTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS)
1119#define DUK_STRIDX_FILENAME 80 /* 'filename' */
1120#define DUK_HEAP_STRING_FILENAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILENAME)
1121#define DUK_HTHREAD_STRING_FILENAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILENAME)
1122#define DUK_STRIDX_TO_STRING 81 /* 'toString' */
1123#define DUK_HEAP_STRING_TO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1124#define DUK_HTHREAD_STRING_TO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1125#define DUK_STRIDX_TO_JSON 82 /* 'toJSON' */
1126#define DUK_HEAP_STRING_TO_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1127#define DUK_HTHREAD_STRING_TO_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1128#define DUK_STRIDX_TYPE 83 /* 'type' */
1129#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1130#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1131#define DUK_STRIDX_DATA 84 /* 'data' */
1132#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1133#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1134#define DUK_STRIDX_LENGTH 85 /* 'length' */
1135#define DUK_HEAP_STRING_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1136#define DUK_HTHREAD_STRING_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1137#define DUK_STRIDX_BYTE_LENGTH 86 /* 'byteLength' */
1138#define DUK_HEAP_STRING_BYTE_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH)
1139#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH)
1140#define DUK_STRIDX_BYTE_OFFSET 87 /* 'byteOffset' */
1141#define DUK_HEAP_STRING_BYTE_OFFSET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET)
1142#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET)
1143#define DUK_STRIDX_BYTES_PER_ELEMENT 88 /* 'BYTES_PER_ELEMENT' */
1144#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT)
1145#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT)
1146#define DUK_STRIDX_SET 89 /* 'set' */
1147#define DUK_HEAP_STRING_SET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1148#define DUK_HTHREAD_STRING_SET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1149#define DUK_STRIDX_STACK 90 /* 'stack' */
1150#define DUK_HEAP_STRING_STACK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1151#define DUK_HTHREAD_STRING_STACK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1152#define DUK_STRIDX_PC 91 /* 'pc' */
1153#define DUK_HEAP_STRING_PC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1154#define DUK_HTHREAD_STRING_PC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1155#define DUK_STRIDX_LINE_NUMBER 92 /* 'lineNumber' */
1156#define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1157#define DUK_HTHREAD_STRING_LINE_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1158#define DUK_STRIDX_INT_TRACEDATA 93 /* '\xffTracedata' */
1159#define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1160#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1161#define DUK_STRIDX_NAME 94 /* 'name' */
1162#define DUK_HEAP_STRING_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1163#define DUK_HTHREAD_STRING_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1164#define DUK_STRIDX_FILE_NAME 95 /* 'fileName' */
1165#define DUK_HEAP_STRING_FILE_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1166#define DUK_HTHREAD_STRING_FILE_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1167#define DUK_STRIDX_LC_BUFFER 96 /* 'buffer' */
1168#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
1169#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
1170#define DUK_STRIDX_LC_POINTER 97 /* 'pointer' */
1171#define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1172#define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1173#define DUK_STRIDX_INT_VALUE 98 /* '\xffValue' */
1174#define DUK_HEAP_STRING_INT_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1175#define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1176#define DUK_STRIDX_INT_NEXT 99 /* '\xffNext' */
1177#define DUK_HEAP_STRING_INT_NEXT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1178#define DUK_HTHREAD_STRING_INT_NEXT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1179#define DUK_STRIDX_INT_BYTECODE 100 /* '\xffBytecode' */
1180#define DUK_HEAP_STRING_INT_BYTECODE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1181#define DUK_HTHREAD_STRING_INT_BYTECODE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1182#define DUK_STRIDX_INT_FORMALS 101 /* '\xffFormals' */
1183#define DUK_HEAP_STRING_INT_FORMALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1184#define DUK_HTHREAD_STRING_INT_FORMALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1185#define DUK_STRIDX_INT_VARMAP 102 /* '\xffVarmap' */
1186#define DUK_HEAP_STRING_INT_VARMAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1187#define DUK_HTHREAD_STRING_INT_VARMAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1188#define DUK_STRIDX_INT_LEXENV 103 /* '\xffLexenv' */
1189#define DUK_HEAP_STRING_INT_LEXENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_LEXENV)
1190#define DUK_HTHREAD_STRING_INT_LEXENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_LEXENV)
1191#define DUK_STRIDX_INT_VARENV 104 /* '\xffVarenv' */
1192#define DUK_HEAP_STRING_INT_VARENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1193#define DUK_HTHREAD_STRING_INT_VARENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1194#define DUK_STRIDX_INT_SOURCE 105 /* '\xffSource' */
1195#define DUK_HEAP_STRING_INT_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1196#define DUK_HTHREAD_STRING_INT_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1197#define DUK_STRIDX_INT_PC2LINE 106 /* '\xffPc2line' */
1198#define DUK_HEAP_STRING_INT_PC2LINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1199#define DUK_HTHREAD_STRING_INT_PC2LINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1200#define DUK_STRIDX_INT_ARGS 107 /* '\xffArgs' */
1201#define DUK_HEAP_STRING_INT_ARGS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_ARGS)
1202#define DUK_HTHREAD_STRING_INT_ARGS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_ARGS)
1203#define DUK_STRIDX_INT_MAP 108 /* '\xffMap' */
1204#define DUK_HEAP_STRING_INT_MAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1205#define DUK_HTHREAD_STRING_INT_MAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1206#define DUK_STRIDX_INT_FINALIZER 109 /* '\xffFinalizer' */
1207#define DUK_HEAP_STRING_INT_FINALIZER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1208#define DUK_HTHREAD_STRING_INT_FINALIZER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1209#define DUK_STRIDX_INT_HANDLER 110 /* '\xffHandler' */
1210#define DUK_HEAP_STRING_INT_HANDLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_HANDLER)
1211#define DUK_HTHREAD_STRING_INT_HANDLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_HANDLER)
1212#define DUK_STRIDX_INT_CALLEE 111 /* '\xffCallee' */
1213#define DUK_HEAP_STRING_INT_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_CALLEE)
1214#define DUK_HTHREAD_STRING_INT_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_CALLEE)
1215#define DUK_STRIDX_INT_THREAD 112 /* '\xffThread' */
1216#define DUK_HEAP_STRING_INT_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THREAD)
1217#define DUK_HTHREAD_STRING_INT_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THREAD)
1218#define DUK_STRIDX_INT_REGBASE 113 /* '\xffRegbase' */
1219#define DUK_HEAP_STRING_INT_REGBASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_REGBASE)
1220#define DUK_HTHREAD_STRING_INT_REGBASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_REGBASE)
1221#define DUK_STRIDX_INT_TARGET 114 /* '\xffTarget' */
1222#define DUK_HEAP_STRING_INT_TARGET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1223#define DUK_HTHREAD_STRING_INT_TARGET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1224#define DUK_STRIDX_INT_THIS 115 /* '\xffThis' */
1225#define DUK_HEAP_STRING_INT_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THIS)
1226#define DUK_HTHREAD_STRING_INT_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THIS)
1227#define DUK_STRIDX_COMPILE 116 /* 'compile' */
1228#define DUK_HEAP_STRING_COMPILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1229#define DUK_HTHREAD_STRING_COMPILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1230#define DUK_STRIDX_INPUT 117 /* 'input' */
1231#define DUK_HEAP_STRING_INPUT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1232#define DUK_HTHREAD_STRING_INPUT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1233#define DUK_STRIDX_ERR_CREATE 118 /* 'errCreate' */
1234#define DUK_HEAP_STRING_ERR_CREATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1235#define DUK_HTHREAD_STRING_ERR_CREATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1236#define DUK_STRIDX_ERR_THROW 119 /* 'errThrow' */
1237#define DUK_HEAP_STRING_ERR_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1238#define DUK_HTHREAD_STRING_ERR_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1239#define DUK_STRIDX_MOD_SEARCH 120 /* 'modSearch' */
1240#define DUK_HEAP_STRING_MOD_SEARCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MOD_SEARCH)
1241#define DUK_HTHREAD_STRING_MOD_SEARCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MOD_SEARCH)
1242#define DUK_STRIDX_MOD_LOADED 121 /* 'modLoaded' */
1243#define DUK_HEAP_STRING_MOD_LOADED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MOD_LOADED)
1244#define DUK_HTHREAD_STRING_MOD_LOADED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MOD_LOADED)
1245#define DUK_STRIDX_ENV 122 /* 'env' */
1246#define DUK_HEAP_STRING_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1247#define DUK_HTHREAD_STRING_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1248#define DUK_STRIDX_HEX 123 /* 'hex' */
1249#define DUK_HEAP_STRING_HEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1250#define DUK_HTHREAD_STRING_HEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1251#define DUK_STRIDX_BASE64 124 /* 'base64' */
1252#define DUK_HEAP_STRING_BASE64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1253#define DUK_HTHREAD_STRING_BASE64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1254#define DUK_STRIDX_JX 125 /* 'jx' */
1255#define DUK_HEAP_STRING_JX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1256#define DUK_HTHREAD_STRING_JX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1257#define DUK_STRIDX_JC 126 /* 'jc' */
1258#define DUK_HEAP_STRING_JC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1259#define DUK_HTHREAD_STRING_JC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1260#define DUK_STRIDX_RESUME 127 /* 'resume' */
1261#define DUK_HEAP_STRING_RESUME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RESUME)
1262#define DUK_HTHREAD_STRING_RESUME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RESUME)
1263#define DUK_STRIDX_FMT 128 /* 'fmt' */
1264#define DUK_HEAP_STRING_FMT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FMT)
1265#define DUK_HTHREAD_STRING_FMT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FMT)
1266#define DUK_STRIDX_RAW 129 /* 'raw' */
1267#define DUK_HEAP_STRING_RAW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RAW)
1268#define DUK_HTHREAD_STRING_RAW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RAW)
1269#define DUK_STRIDX_LC_TRACE 130 /* 'trace' */
1270#define DUK_HEAP_STRING_LC_TRACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_TRACE)
1271#define DUK_HTHREAD_STRING_LC_TRACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_TRACE)
1272#define DUK_STRIDX_LC_DEBUG 131 /* 'debug' */
1273#define DUK_HEAP_STRING_LC_DEBUG(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_DEBUG)
1274#define DUK_HTHREAD_STRING_LC_DEBUG(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_DEBUG)
1275#define DUK_STRIDX_LC_INFO 132 /* 'info' */
1276#define DUK_HEAP_STRING_LC_INFO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_INFO)
1277#define DUK_HTHREAD_STRING_LC_INFO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_INFO)
1278#define DUK_STRIDX_LC_WARN 133 /* 'warn' */
1279#define DUK_HEAP_STRING_LC_WARN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_WARN)
1280#define DUK_HTHREAD_STRING_LC_WARN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_WARN)
1281#define DUK_STRIDX_LC_ERROR 134 /* 'error' */
1282#define DUK_HEAP_STRING_LC_ERROR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ERROR)
1283#define DUK_HTHREAD_STRING_LC_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ERROR)
1284#define DUK_STRIDX_LC_FATAL 135 /* 'fatal' */
1285#define DUK_HEAP_STRING_LC_FATAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FATAL)
1286#define DUK_HTHREAD_STRING_LC_FATAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FATAL)
1287#define DUK_STRIDX_LC_N 136 /* 'n' */
1288#define DUK_HEAP_STRING_LC_N(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_N)
1289#define DUK_HTHREAD_STRING_LC_N(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_N)
1290#define DUK_STRIDX_LC_L 137 /* 'l' */
1291#define DUK_HEAP_STRING_LC_L(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_L)
1292#define DUK_HTHREAD_STRING_LC_L(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_L)
1293#define DUK_STRIDX_CLOG 138 /* 'clog' */
1294#define DUK_HEAP_STRING_CLOG(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLOG)
1295#define DUK_HTHREAD_STRING_CLOG(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLOG)
1296#define DUK_STRIDX_TO_LOG_STRING 139 /* 'toLogString' */
1297#define DUK_HEAP_STRING_TO_LOG_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOG_STRING)
1298#define DUK_HTHREAD_STRING_TO_LOG_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOG_STRING)
1299#define DUK_STRIDX_JSON_EXT_UNDEFINED 140 /* '{"_undef":true}' */
1300#define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1301#define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1302#define DUK_STRIDX_JSON_EXT_NAN 141 /* '{"_nan":true}' */
1303#define DUK_HEAP_STRING_JSON_EXT_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1304#define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1305#define DUK_STRIDX_JSON_EXT_POSINF 142 /* '{"_inf":true}' */
1306#define DUK_HEAP_STRING_JSON_EXT_POSINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1307#define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1308#define DUK_STRIDX_JSON_EXT_NEGINF 143 /* '{"_ninf":true}' */
1309#define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1310#define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1311#define DUK_STRIDX_JSON_EXT_FUNCTION1 144 /* '{"_func":true}' */
1312#define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1313#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1314#define DUK_STRIDX_JSON_EXT_FUNCTION2 145 /* '{_func:true}' */
1315#define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1316#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1317#define DUK_STRIDX_BREAK 146 /* 'break' */
1318#define DUK_HEAP_STRING_BREAK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1319#define DUK_HTHREAD_STRING_BREAK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1320#define DUK_STRIDX_CASE 147 /* 'case' */
1321#define DUK_HEAP_STRING_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1322#define DUK_HTHREAD_STRING_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1323#define DUK_STRIDX_CATCH 148 /* 'catch' */
1324#define DUK_HEAP_STRING_CATCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1325#define DUK_HTHREAD_STRING_CATCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1326#define DUK_STRIDX_CONTINUE 149 /* 'continue' */
1327#define DUK_HEAP_STRING_CONTINUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1328#define DUK_HTHREAD_STRING_CONTINUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1329#define DUK_STRIDX_DEBUGGER 150 /* 'debugger' */
1330#define DUK_HEAP_STRING_DEBUGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1331#define DUK_HTHREAD_STRING_DEBUGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1332#define DUK_STRIDX_DEFAULT 151 /* 'default' */
1333#define DUK_HEAP_STRING_DEFAULT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1334#define DUK_HTHREAD_STRING_DEFAULT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1335#define DUK_STRIDX_DELETE 152 /* 'delete' */
1336#define DUK_HEAP_STRING_DELETE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1337#define DUK_HTHREAD_STRING_DELETE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1338#define DUK_STRIDX_DO 153 /* 'do' */
1339#define DUK_HEAP_STRING_DO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1340#define DUK_HTHREAD_STRING_DO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1341#define DUK_STRIDX_ELSE 154 /* 'else' */
1342#define DUK_HEAP_STRING_ELSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1343#define DUK_HTHREAD_STRING_ELSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1344#define DUK_STRIDX_FINALLY 155 /* 'finally' */
1345#define DUK_HEAP_STRING_FINALLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1346#define DUK_HTHREAD_STRING_FINALLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1347#define DUK_STRIDX_FOR 156 /* 'for' */
1348#define DUK_HEAP_STRING_FOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1349#define DUK_HTHREAD_STRING_FOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1350#define DUK_STRIDX_LC_FUNCTION 157 /* 'function' */
1351#define DUK_HEAP_STRING_LC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1352#define DUK_HTHREAD_STRING_LC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1353#define DUK_STRIDX_IF 158 /* 'if' */
1354#define DUK_HEAP_STRING_IF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1355#define DUK_HTHREAD_STRING_IF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1356#define DUK_STRIDX_IN 159 /* 'in' */
1357#define DUK_HEAP_STRING_IN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1358#define DUK_HTHREAD_STRING_IN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1359#define DUK_STRIDX_INSTANCEOF 160 /* 'instanceof' */
1360#define DUK_HEAP_STRING_INSTANCEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1361#define DUK_HTHREAD_STRING_INSTANCEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1362#define DUK_STRIDX_NEW 161 /* 'new' */
1363#define DUK_HEAP_STRING_NEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1364#define DUK_HTHREAD_STRING_NEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1365#define DUK_STRIDX_RETURN 162 /* 'return' */
1366#define DUK_HEAP_STRING_RETURN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1367#define DUK_HTHREAD_STRING_RETURN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1368#define DUK_STRIDX_SWITCH 163 /* 'switch' */
1369#define DUK_HEAP_STRING_SWITCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1370#define DUK_HTHREAD_STRING_SWITCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1371#define DUK_STRIDX_THIS 164 /* 'this' */
1372#define DUK_HEAP_STRING_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1373#define DUK_HTHREAD_STRING_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1374#define DUK_STRIDX_THROW 165 /* 'throw' */
1375#define DUK_HEAP_STRING_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1376#define DUK_HTHREAD_STRING_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1377#define DUK_STRIDX_TRY 166 /* 'try' */
1378#define DUK_HEAP_STRING_TRY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1379#define DUK_HTHREAD_STRING_TRY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1380#define DUK_STRIDX_TYPEOF 167 /* 'typeof' */
1381#define DUK_HEAP_STRING_TYPEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1382#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1383#define DUK_STRIDX_VAR 168 /* 'var' */
1384#define DUK_HEAP_STRING_VAR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1385#define DUK_HTHREAD_STRING_VAR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1386#define DUK_STRIDX_CONST 169 /* 'const' */
1387#define DUK_HEAP_STRING_CONST(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1388#define DUK_HTHREAD_STRING_CONST(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1389#define DUK_STRIDX_VOID 170 /* 'void' */
1390#define DUK_HEAP_STRING_VOID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1391#define DUK_HTHREAD_STRING_VOID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1392#define DUK_STRIDX_WHILE 171 /* 'while' */
1393#define DUK_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1394#define DUK_HTHREAD_STRING_WHILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1395#define DUK_STRIDX_WITH 172 /* 'with' */
1396#define DUK_HEAP_STRING_WITH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1397#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1398#define DUK_STRIDX_CLASS 173 /* 'class' */
1399#define DUK_HEAP_STRING_CLASS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1400#define DUK_HTHREAD_STRING_CLASS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1401#define DUK_STRIDX_ENUM 174 /* 'enum' */
1402#define DUK_HEAP_STRING_ENUM(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1403#define DUK_HTHREAD_STRING_ENUM(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1404#define DUK_STRIDX_EXPORT 175 /* 'export' */
1405#define DUK_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1406#define DUK_HTHREAD_STRING_EXPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1407#define DUK_STRIDX_EXTENDS 176 /* 'extends' */
1408#define DUK_HEAP_STRING_EXTENDS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1409#define DUK_HTHREAD_STRING_EXTENDS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1410#define DUK_STRIDX_IMPORT 177 /* 'import' */
1411#define DUK_HEAP_STRING_IMPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1412#define DUK_HTHREAD_STRING_IMPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1413#define DUK_STRIDX_SUPER 178 /* 'super' */
1414#define DUK_HEAP_STRING_SUPER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
1415#define DUK_HTHREAD_STRING_SUPER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
1416#define DUK_STRIDX_LC_NULL 179 /* 'null' */
1417#define DUK_HEAP_STRING_LC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
1418#define DUK_HTHREAD_STRING_LC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
1419#define DUK_STRIDX_TRUE 180 /* 'true' */
1420#define DUK_HEAP_STRING_TRUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
1421#define DUK_HTHREAD_STRING_TRUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
1422#define DUK_STRIDX_FALSE 181 /* 'false' */
1423#define DUK_HEAP_STRING_FALSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
1424#define DUK_HTHREAD_STRING_FALSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
1425#define DUK_STRIDX_IMPLEMENTS 182 /* 'implements' */
1426#define DUK_HEAP_STRING_IMPLEMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
1427#define DUK_HTHREAD_STRING_IMPLEMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
1428#define DUK_STRIDX_INTERFACE 183 /* 'interface' */
1429#define DUK_HEAP_STRING_INTERFACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
1430#define DUK_HTHREAD_STRING_INTERFACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
1431#define DUK_STRIDX_LET 184 /* 'let' */
1432#define DUK_HEAP_STRING_LET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
1433#define DUK_HTHREAD_STRING_LET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
1434#define DUK_STRIDX_PACKAGE 185 /* 'package' */
1435#define DUK_HEAP_STRING_PACKAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
1436#define DUK_HTHREAD_STRING_PACKAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
1437#define DUK_STRIDX_PRIVATE 186 /* 'private' */
1438#define DUK_HEAP_STRING_PRIVATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
1439#define DUK_HTHREAD_STRING_PRIVATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
1440#define DUK_STRIDX_PROTECTED 187 /* 'protected' */
1441#define DUK_HEAP_STRING_PROTECTED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
1442#define DUK_HTHREAD_STRING_PROTECTED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
1443#define DUK_STRIDX_PUBLIC 188 /* 'public' */
1444#define DUK_HEAP_STRING_PUBLIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
1445#define DUK_HTHREAD_STRING_PUBLIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
1446#define DUK_STRIDX_STATIC 189 /* 'static' */
1447#define DUK_HEAP_STRING_STATIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
1448#define DUK_HTHREAD_STRING_STATIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
1449#define DUK_STRIDX_YIELD 190 /* 'yield' */
1450#define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
1451#define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
1452
1453#define DUK_HEAP_NUM_STRINGS 191
1454#define DUK_STRIDX_START_RESERVED 146
1455#define DUK_STRIDX_START_STRICT_RESERVED 182
1456#define DUK_STRIDX_END_RESERVED 191 /* exclusive endpoint */
1457
1458/* To convert a heap stridx to a token number, subtract
1459 * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
1460 */
1461#if !defined(DUK_SINGLE_FILE)
1462DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1049];
1463#endif /* !DUK_SINGLE_FILE */
1464#define DUK_STRDATA_MAX_STRLEN 17
1465#define DUK_STRDATA_DATA_LENGTH 1049
1466#endif /* DUK_USE_ROM_STRINGS */
1467
1468#if defined(DUK_USE_ROM_OBJECTS)
1469#error ROM support not enabled, rerun make_dist.py with --rom-support
1470#else
1620#if !defined(DUK_SINGLE_FILE)
1622#endif /* !DUK_SINGLE_FILE */
1623#if defined(DUK_USE_BUILTIN_INITJS)
1624#if !defined(DUK_SINGLE_FILE)
1625DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[204];
1626#endif /* !DUK_SINGLE_FILE */
1627#define DUK_BUILTIN_INITJS_DATA_LENGTH 204
1628#endif /* DUK_USE_BUILTIN_INITJS */
1629#define DUK_BIDX_GLOBAL 0
1630#define DUK_BIDX_GLOBAL_ENV 1
1631#define DUK_BIDX_OBJECT_CONSTRUCTOR 2
1632#define DUK_BIDX_OBJECT_PROTOTYPE 3
1633#define DUK_BIDX_FUNCTION_CONSTRUCTOR 4
1634#define DUK_BIDX_FUNCTION_PROTOTYPE 5
1635#define DUK_BIDX_ARRAY_CONSTRUCTOR 6
1636#define DUK_BIDX_ARRAY_PROTOTYPE 7
1637#define DUK_BIDX_STRING_CONSTRUCTOR 8
1638#define DUK_BIDX_STRING_PROTOTYPE 9
1639#define DUK_BIDX_BOOLEAN_CONSTRUCTOR 10
1640#define DUK_BIDX_BOOLEAN_PROTOTYPE 11
1641#define DUK_BIDX_NUMBER_CONSTRUCTOR 12
1642#define DUK_BIDX_NUMBER_PROTOTYPE 13
1643#define DUK_BIDX_DATE_CONSTRUCTOR 14
1644#define DUK_BIDX_DATE_PROTOTYPE 15
1645#define DUK_BIDX_REGEXP_CONSTRUCTOR 16
1646#define DUK_BIDX_REGEXP_PROTOTYPE 17
1647#define DUK_BIDX_ERROR_CONSTRUCTOR 18
1648#define DUK_BIDX_ERROR_PROTOTYPE 19
1649#define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR 20
1650#define DUK_BIDX_EVAL_ERROR_PROTOTYPE 21
1651#define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR 22
1652#define DUK_BIDX_RANGE_ERROR_PROTOTYPE 23
1653#define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR 24
1654#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE 25
1655#define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR 26
1656#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE 27
1657#define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR 28
1658#define DUK_BIDX_TYPE_ERROR_PROTOTYPE 29
1659#define DUK_BIDX_URI_ERROR_CONSTRUCTOR 30
1660#define DUK_BIDX_URI_ERROR_PROTOTYPE 31
1661#define DUK_BIDX_MATH 32
1662#define DUK_BIDX_JSON 33
1663#define DUK_BIDX_TYPE_ERROR_THROWER 34
1664#define DUK_BIDX_PROXY_CONSTRUCTOR 35
1665#define DUK_BIDX_DUKTAPE 36
1666#define DUK_BIDX_THREAD_CONSTRUCTOR 37
1667#define DUK_BIDX_THREAD_PROTOTYPE 38
1668#define DUK_BIDX_BUFFER_CONSTRUCTOR 39
1669#define DUK_BIDX_BUFFER_PROTOTYPE 40
1670#define DUK_BIDX_POINTER_CONSTRUCTOR 41
1671#define DUK_BIDX_POINTER_PROTOTYPE 42
1672#define DUK_BIDX_LOGGER_CONSTRUCTOR 43
1673#define DUK_BIDX_LOGGER_PROTOTYPE 44
1674#define DUK_BIDX_DOUBLE_ERROR 45
1675#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR 46
1676#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 47
1677#define DUK_BIDX_DATAVIEW_CONSTRUCTOR 48
1678#define DUK_BIDX_DATAVIEW_PROTOTYPE 49
1679#define DUK_BIDX_TYPEDARRAY_PROTOTYPE 50
1680#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR 51
1681#define DUK_BIDX_INT8ARRAY_PROTOTYPE 52
1682#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR 53
1683#define DUK_BIDX_UINT8ARRAY_PROTOTYPE 54
1684#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR 55
1685#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 56
1686#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR 57
1687#define DUK_BIDX_INT16ARRAY_PROTOTYPE 58
1688#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR 59
1689#define DUK_BIDX_UINT16ARRAY_PROTOTYPE 60
1690#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR 61
1691#define DUK_BIDX_INT32ARRAY_PROTOTYPE 62
1692#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR 63
1693#define DUK_BIDX_UINT32ARRAY_PROTOTYPE 64
1694#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR 65
1695#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 66
1696#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR 67
1697#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 68
1698#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR 69
1699#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 70
1700#define DUK_NUM_BUILTINS 71
1701#define DUK_NUM_BIDX_BUILTINS 71
1702#define DUK_NUM_ALL_BUILTINS 71
1703#if defined(DUK_USE_DOUBLE_LE)
1704#if !defined(DUK_SINGLE_FILE)
1705DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1706#endif /* !DUK_SINGLE_FILE */
1707#define DUK_BUILTINS_DATA_LENGTH 3833
1708#elif defined(DUK_USE_DOUBLE_BE)
1709#if !defined(DUK_SINGLE_FILE)
1710DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1711#endif /* !DUK_SINGLE_FILE */
1712#define DUK_BUILTINS_DATA_LENGTH 3833
1713#elif defined(DUK_USE_DOUBLE_ME)
1714#if !defined(DUK_SINGLE_FILE)
1715DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1716#endif /* !DUK_SINGLE_FILE */
1717#define DUK_BUILTINS_DATA_LENGTH 3833
1718#else
1719#error invalid endianness defines
1720#endif
1721#endif /* DUK_USE_ROM_OBJECTS */
1722#endif /* DUK_BUILTINS_H_INCLUDED */
1723
1724/*
1725 * Utilities
1726 */
1727
1728#ifndef DUK_UTIL_H_INCLUDED
1729#define DUK_UTIL_H_INCLUDED
1730
1731#define DUK_UTIL_MIN_HASH_PRIME 17 /* must match genhashsizes.py */
1732
1733#define DUK_UTIL_GET_HASH_PROBE_STEP(hash) (duk_util_probe_steps[(hash) & 0x1f])
1734
1735/*
1736 * Endian conversion
1737 */
1738
1739#if defined(DUK_USE_INTEGER_LE)
1740#define DUK_HTON32(x) DUK_BSWAP32((x))
1741#define DUK_NTOH32(x) DUK_BSWAP32((x))
1742#define DUK_HTON16(x) DUK_BSWAP16((x))
1743#define DUK_NTOH16(x) DUK_BSWAP16((x))
1744#elif defined(DUK_USE_INTEGER_BE)
1745#define DUK_HTON32(x) (x)
1746#define DUK_NTOH32(x) (x)
1747#define DUK_HTON16(x) (x)
1748#define DUK_NTOH16(x) (x)
1749#else
1750#error internal error, endianness defines broken
1751#endif
1752
1753/*
1754 * Bitstream decoder
1755 */
1756
1764
1765/*
1766 * Bitstream encoder
1767 */
1768
1777
1778/*
1779 * Raw write/read macros for big endian, unaligned basic values.
1780 * Caller ensures there's enough space. The macros update the pointer
1781 * argument automatically on resizes. The idiom seems a bit odd, but
1782 * leads to compact code.
1783 */
1784
1785#define DUK_RAW_WRITE_U8(ptr,val) do { \
1786 *(ptr)++ = (duk_uint8_t) (val); \
1787 } while (0)
1788#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
1789#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
1790#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
1791#define DUK_RAW_WRITE_XUTF8(ptr,val) do { \
1792 /* 'ptr' is evaluated both as LHS and RHS. */ \
1793 duk_uint8_t *duk__ptr; \
1794 duk_small_int_t duk__len; \
1795 duk__ptr = (duk_uint8_t *) (ptr); \
1796 duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
1797 duk__ptr += duk__len; \
1798 (ptr) = duk__ptr; \
1799 } while (0)
1800#define DUK_RAW_WRITE_CESU8(ptr,val) do { \
1801 /* 'ptr' is evaluated both as LHS and RHS. */ \
1802 duk_uint8_t *duk__ptr; \
1803 duk_small_int_t duk__len; \
1804 duk__ptr = (duk_uint8_t *) (ptr); \
1805 duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
1806 duk__ptr += duk__len; \
1807 (ptr) = duk__ptr; \
1808 } while (0)
1809
1810#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
1811#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
1812#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
1813#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
1814
1815/*
1816 * Buffer writer (dynamic buffer only)
1817 *
1818 * Helper for writing to a dynamic buffer with a concept of a "spare" area
1819 * to reduce resizes. You can ensure there is enough space beforehand and
1820 * then write for a while without further checks, relying on a stable data
1821 * pointer. Spare handling is automatic so call sites only indicate how
1822 * much data they need right now.
1823 *
1824 * There are several ways to write using bufwriter. The best approach
1825 * depends mainly on how much performance matters over code footprint.
1826 * The key issues are (1) ensuring there is space and (2) keeping the
1827 * pointers consistent. Fast code should ensure space for multiple writes
1828 * with one ensure call. Fastest inner loop code can temporarily borrow
1829 * the 'p' pointer but must write it back eventually.
1830 *
1831 * Be careful to ensure all macro arguments (other than static pointers like
1832 * 'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
1833 * necessary (if that's not possible, there should be a note near the macro).
1834 * Buffer write arguments often contain arithmetic etc so this is
1835 * particularly important here.
1836 */
1837
1838/* XXX: Migrate bufwriter and other read/write helpers to its own header? */
1839
1841 duk_uint8_t *p;
1842 duk_uint8_t *p_base;
1843 duk_uint8_t *p_limit;
1845};
1846
1847#define DUK_BW_SPARE_ADD 64
1848#define DUK_BW_SPARE_SHIFT 4 /* 2^4 -> 1/16 = 6.25% spare */
1849
1850/* Initialization and finalization (compaction), converting to other types. */
1851
1852#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
1853 duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
1854 } while (0)
1855#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
1856 duk_bw_init((thr), (bw_ctx), (buf)); \
1857 } while (0)
1858#define DUK_BW_COMPACT(thr,bw_ctx) do { \
1859 /* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
1860 duk_bw_compact((thr), (bw_ctx)); \
1861 } while (0)
1862#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
1863 duk_push_lstring((duk_context *) (thr), \
1864 (const char *) (bw_ctx)->p_base, \
1865 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
1866 } while (0)
1867/* Pointers may be NULL for a while when 'buf' size is zero and before any
1868 * ENSURE calls have been made. Once an ENSURE has been made, the pointers
1869 * are required to be non-NULL so that it's always valid to use memcpy() and
1870 * memmove(), even for zero size.
1871 */
1872#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
1873 DUK_ASSERT_EXPR((bw_ctx) != NULL && \
1874 (bw_ctx)->buf != NULL && \
1875 ((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
1876 ((bw_ctx)->p != NULL && \
1877 (bw_ctx)->p_base != NULL && \
1878 (bw_ctx)->p_limit != NULL && \
1879 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
1880 (bw_ctx)->p >= (bw_ctx)->p_base && \
1881 (bw_ctx)->p <= (bw_ctx)->p_limit)))
1882#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
1883 DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
1884 } while (0)
1885
1886/* Working with the pointer and current size. */
1887
1888#define DUK_BW_GET_PTR(thr,bw_ctx) \
1889 ((bw_ctx)->p)
1890#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
1891 (bw_ctx)->p = (ptr); \
1892 } while (0)
1893#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
1894 (bw_ctx)->p += (delta); \
1895 } while (0)
1896#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
1897 ((bw_ctx)->p_base)
1898#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
1899 ((bw_ctx)->p_limit)
1900#define DUK_BW_GET_SIZE(thr,bw_ctx) \
1901 ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
1902#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
1903 DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
1904 (bw_ctx)->p = (bw_ctx)->p_base + (sz); \
1905 } while (0)
1906#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
1907 /* Reset to zero size, keep current limit. */ \
1908 (bw_ctx)->p = (bw_ctx)->p_base; \
1909 } while (0)
1910#define DUK_BW_GET_BUFFER(thr,bw_ctx) \
1911 ((bw_ctx)->buf)
1912
1913/* Ensuring (reserving) space. */
1914
1915#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
1916 duk_size_t duk__sz, duk__space; \
1917 DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
1918 duk__sz = (sz); \
1919 duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
1920 if (duk__space < duk__sz) { \
1921 (void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
1922 } \
1923 } while (0)
1924/* NOTE: Multiple evaluation of 'ptr' in this macro. */
1925/* XXX: Rework to use an always-inline function? */
1926#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
1927 (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
1928 (ptr) : \
1929 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
1930#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
1931 DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
1932#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
1933 (DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
1934 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
1935#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
1936 DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
1937 } while (0)
1938
1939/* Miscellaneous. */
1940
1941#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
1942 (bw_ctx)->p = (ptr); \
1943 duk_bw_compact((thr), (bw_ctx)); \
1944 } while (0)
1945
1946/* Fast write calls which assume you control the spare beforehand.
1947 * Multibyte write variants exist and use a temporary write pointer
1948 * because byte writes alias with anything: with a stored pointer
1949 * explicit pointer load/stores get generated (e.g. gcc -Os).
1950 */
1951
1952#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
1953 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
1954 *(bw_ctx)->p++ = (duk_uint8_t) (val); \
1955 } while (0)
1956#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
1957 duk_uint8_t *duk__p; \
1958 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
1959 duk__p = (bw_ctx)->p; \
1960 *duk__p++ = (duk_uint8_t) (val1); \
1961 *duk__p++ = (duk_uint8_t) (val2); \
1962 (bw_ctx)->p = duk__p; \
1963 } while (0)
1964#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
1965 duk_uint8_t *duk__p; \
1966 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
1967 duk__p = (bw_ctx)->p; \
1968 *duk__p++ = (duk_uint8_t) (val1); \
1969 *duk__p++ = (duk_uint8_t) (val2); \
1970 *duk__p++ = (duk_uint8_t) (val3); \
1971 (bw_ctx)->p = duk__p; \
1972 } while (0)
1973#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
1974 duk_uint8_t *duk__p; \
1975 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
1976 duk__p = (bw_ctx)->p; \
1977 *duk__p++ = (duk_uint8_t) (val1); \
1978 *duk__p++ = (duk_uint8_t) (val2); \
1979 *duk__p++ = (duk_uint8_t) (val3); \
1980 *duk__p++ = (duk_uint8_t) (val4); \
1981 (bw_ctx)->p = duk__p; \
1982 } while (0)
1983#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
1984 duk_uint8_t *duk__p; \
1985 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
1986 duk__p = (bw_ctx)->p; \
1987 *duk__p++ = (duk_uint8_t) (val1); \
1988 *duk__p++ = (duk_uint8_t) (val2); \
1989 *duk__p++ = (duk_uint8_t) (val3); \
1990 *duk__p++ = (duk_uint8_t) (val4); \
1991 *duk__p++ = (duk_uint8_t) (val5); \
1992 (bw_ctx)->p = duk__p; \
1993 } while (0)
1994#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
1995 duk_uint8_t *duk__p; \
1996 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
1997 duk__p = (bw_ctx)->p; \
1998 *duk__p++ = (duk_uint8_t) (val1); \
1999 *duk__p++ = (duk_uint8_t) (val2); \
2000 *duk__p++ = (duk_uint8_t) (val3); \
2001 *duk__p++ = (duk_uint8_t) (val4); \
2002 *duk__p++ = (duk_uint8_t) (val5); \
2003 *duk__p++ = (duk_uint8_t) (val6); \
2004 (bw_ctx)->p = duk__p; \
2005 } while (0)
2006#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2007 duk_ucodepoint_t duk__cp; \
2008 duk_small_int_t duk__enc_len; \
2009 duk__cp = (cp); \
2010 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2011 duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2012 (bw_ctx)->p += duk__enc_len; \
2013 } while (0)
2014#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2015 duk_ucodepoint_t duk__cp; \
2016 duk_small_int_t duk__enc_len; \
2017 duk__cp = (duk_ucodepoint_t) (cp); \
2018 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2019 duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2020 (bw_ctx)->p += duk__enc_len; \
2021 } while (0)
2022/* XXX: add temporary duk__p pointer here too; sharing */
2023#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2024 const void *duk__valptr; \
2025 duk_size_t duk__valsz; \
2026 duk__valptr = (const void *) (valptr); \
2027 duk__valsz = (duk_size_t) (valsz); \
2028 DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2029 (bw_ctx)->p += duk__valsz; \
2030 } while (0)
2031#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2032 const duk_uint8_t *duk__val; \
2033 duk_size_t duk__val_len; \
2034 duk__val = (const duk_uint8_t *) (val); \
2035 duk__val_len = DUK_STRLEN((const char *) duk__val); \
2036 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2037 (bw_ctx)->p += duk__val_len; \
2038 } while (0)
2039#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2040 duk_size_t duk__val_len; \
2041 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2042 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2043 (bw_ctx)->p += duk__val_len; \
2044 } while (0)
2045#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2046 duk_size_t duk__val_len; \
2047 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2048 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2049 (bw_ctx)->p += duk__val_len; \
2050 } while (0)
2051#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2052 duk_size_t duk__val_len; \
2053 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2054 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2055 (bw_ctx)->p += duk__val_len; \
2056 } while (0)
2057#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2058 duk_size_t duk__val_len; \
2059 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2060 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2061 (bw_ctx)->p += duk__val_len; \
2062 } while (0)
2063
2064/* Append bytes from a slice already in the buffer. */
2065#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2066 duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2067
2068/* Insert bytes in the middle of the buffer from an external buffer. */
2069#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2070 duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2071
2072/* Insert bytes in the middle of the buffer from a slice already
2073 * in the buffer. Source offset is interpreted "before" the operation.
2074 */
2075#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2076 duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2077
2078/* Insert a reserved area somewhere in the buffer; caller fills it.
2079 * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2080 * area for convenience.
2081 */
2082#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2083 duk_bw_insert_raw_area((thr), (bw), (off), (len))
2084
2085/* Remove a slice from inside buffer. */
2086#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2087 duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2088
2089/* Safe write calls which will ensure space first. */
2090
2091#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2092 DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2093 DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2094 } while (0)
2095#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2096 DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2097 DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2098 } while (0)
2099#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2100 DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2101 DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2102 } while (0)
2103#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2104 DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2105 DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2106 } while (0)
2107#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2108 DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2109 DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2110 } while (0)
2111#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2112 DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2113 DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2114 } while (0)
2115#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2116 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2117 DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2118 } while (0)
2119#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2120 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2121 DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2122 } while (0)
2123/* XXX: add temporary duk__p pointer here too; sharing */
2124#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2125 const void *duk__valptr; \
2126 duk_size_t duk__valsz; \
2127 duk__valptr = (const void *) (valptr); \
2128 duk__valsz = (duk_size_t) (valsz); \
2129 DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2130 DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2131 (bw_ctx)->p += duk__valsz; \
2132 } while (0)
2133#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2134 const duk_uint8_t *duk__val; \
2135 duk_size_t duk__val_len; \
2136 duk__val = (const duk_uint8_t *) (val); \
2137 duk__val_len = DUK_STRLEN((const char *) duk__val); \
2138 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2139 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2140 (bw_ctx)->p += duk__val_len; \
2141 } while (0)
2142#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2143 duk_size_t duk__val_len; \
2144 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2145 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2146 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2147 (bw_ctx)->p += duk__val_len; \
2148 } while (0)
2149#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2150 duk_size_t duk__val_len; \
2151 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2152 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2153 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2154 (bw_ctx)->p += duk__val_len; \
2155 } while (0)
2156#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2157 duk_size_t duk__val_len; \
2158 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2159 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2160 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2161 (bw_ctx)->p += duk__val_len; \
2162 } while (0)
2163#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2164 duk_size_t duk__val_len; \
2165 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2166 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2167 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2168 (bw_ctx)->p += duk__val_len; \
2169 } while (0)
2170
2171#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2172 duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2173#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2174 duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2175#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2176 duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2177#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2178 /* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2179 duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2180#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2181 /* No difference between raw/ensure because the buffer shrinks. */ \
2182 DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2183
2184/*
2185 * Externs and prototypes
2186 */
2187
2188#if !defined(DUK_SINGLE_FILE)
2189DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2190DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2191DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2192#if defined(DUK_USE_HEX_FASTPATH)
2193DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2194DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2195#endif
2196#if defined(DUK_USE_BASE64_FASTPATH)
2197DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];
2198DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];
2199#endif
2200#endif /* !DUK_SINGLE_FILE */
2201
2202/* Note: assumes that duk_util_probe_steps size is 32 */
2203#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2204#if !defined(DUK_SINGLE_FILE)
2206#endif /* !DUK_SINGLE_FILE */
2207#endif
2208
2209#if defined(DUK_USE_STRHASH_DENSE)
2210DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2211#endif
2212
2213#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2214DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size);
2215#endif
2216
2219DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
2220
2221DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2223
2226
2233DUK_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);
2234DUK_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);
2240/* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2241
2242DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
2243DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
2245DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
2246DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
2247DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
2248
2249#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
2250DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2251#endif
2252
2253#endif /* DUK_UTIL_H_INCLUDED */
2254/*
2255 * Shared error messages: declarations and macros
2256 *
2257 * Error messages are accessed through macros with fine-grained, explicit
2258 * error message distinctions. Concrete error messages are selected by the
2259 * macros and multiple macros can map to the same concrete string to save
2260 * on code footprint. This allows flexible footprint/verbosity tuning with
2261 * minimal code impact. There are a few limitations to this approach:
2262 * (1) switching between plain messages and format strings doesn't work
2263 * conveniently, and (2) conditional strings are a bit awkward to handle.
2264 *
2265 * Because format strings behave differently in the call site (they need to
2266 * be followed by format arguments), they have a special prefix (DUK_STR_FMT_
2267 * and duk_str_fmt_).
2268 *
2269 * On some compilers using explicit shared strings is preferable; on others
2270 * it may be better to use straight literals because the compiler will combine
2271 * them anyway, and such strings won't end up unnecessarily in a symbol table.
2272 */
2273
2274#ifndef DUK_ERRMSG_H_INCLUDED
2275#define DUK_ERRMSG_H_INCLUDED
2276
2277#define DUK_STR_INTERNAL_ERROR duk_str_internal_error
2278#define DUK_STR_INVALID_COUNT duk_str_invalid_count
2279#define DUK_STR_INVALID_CALL_ARGS duk_str_invalid_call_args
2280#define DUK_STR_NOT_CONSTRUCTABLE duk_str_not_constructable
2281#define DUK_STR_NOT_CALLABLE duk_str_not_callable
2282#define DUK_STR_NOT_EXTENSIBLE duk_str_not_extensible
2283#define DUK_STR_NOT_WRITABLE duk_str_not_writable
2284#define DUK_STR_NOT_CONFIGURABLE duk_str_not_configurable
2285
2286#if !defined(DUK_SINGLE_FILE)
2295#endif /* !DUK_SINGLE_FILE */
2296
2297#define DUK_STR_INVALID_CONTEXT duk_str_invalid_context
2298#define DUK_STR_INVALID_INDEX duk_str_invalid_call_args
2299#define DUK_STR_PUSH_BEYOND_ALLOC_STACK duk_str_push_beyond_alloc_stack
2300#define DUK_STR_NOT_UNDEFINED duk_str_unexpected_type
2301#define DUK_STR_NOT_NULL duk_str_unexpected_type
2302#define DUK_STR_NOT_BOOLEAN duk_str_unexpected_type
2303#define DUK_STR_NOT_NUMBER duk_str_unexpected_type
2304#define DUK_STR_NOT_STRING duk_str_unexpected_type
2305#define DUK_STR_NOT_OBJECT duk_str_unexpected_type
2306#define DUK_STR_NOT_POINTER duk_str_unexpected_type
2307#define DUK_STR_NOT_BUFFER duk_str_not_buffer /* still in use with verbose messages */
2308#define DUK_STR_UNEXPECTED_TYPE duk_str_unexpected_type
2309#define DUK_STR_NOT_THREAD duk_str_unexpected_type
2310#define DUK_STR_NOT_COMPILEDFUNCTION duk_str_unexpected_type
2311#define DUK_STR_NOT_NATIVEFUNCTION duk_str_unexpected_type
2312#define DUK_STR_NOT_C_FUNCTION duk_str_unexpected_type
2313#define DUK_STR_NOT_FUNCTION duk_str_unexpected_type
2314#define DUK_STR_NOT_REGEXP duk_str_unexpected_type
2315#define DUK_STR_DEFAULTVALUE_COERCE_FAILED duk_str_defaultvalue_coerce_failed
2316#define DUK_STR_NUMBER_OUTSIDE_RANGE duk_str_number_outside_range
2317#define DUK_STR_NOT_OBJECT_COERCIBLE duk_str_not_object_coercible
2318#define DUK_STR_STRING_TOO_LONG duk_str_string_too_long
2319#define DUK_STR_BUFFER_TOO_LONG duk_str_buffer_too_long
2320#define DUK_STR_SPRINTF_TOO_LONG duk_str_sprintf_too_long
2321#define DUK_STR_ALLOC_FAILED duk_str_alloc_failed
2322#define DUK_STR_POP_TOO_MANY duk_str_pop_too_many
2323#define DUK_STR_WRONG_BUFFER_TYPE duk_str_wrong_buffer_type
2324#define DUK_STR_ENCODE_FAILED duk_str_encode_failed
2325#define DUK_STR_DECODE_FAILED duk_str_decode_failed
2326#define DUK_STR_NO_SOURCECODE duk_str_no_sourcecode
2327#define DUK_STR_CONCAT_RESULT_TOO_LONG duk_str_concat_result_too_long
2328#define DUK_STR_UNIMPLEMENTED duk_str_unimplemented
2329#define DUK_STR_UNSUPPORTED duk_str_unsupported
2330#define DUK_STR_ARRAY_LENGTH_OVER_2G duk_str_array_length_over_2g
2331
2332#if !defined(DUK_SINGLE_FILE)
2353#endif /* !DUK_SINGLE_FILE */
2354
2355#define DUK_STR_FMT_PTR duk_str_fmt_ptr
2356#define DUK_STR_FMT_INVALID_JSON duk_str_fmt_invalid_json
2357#define DUK_STR_JSONDEC_RECLIMIT duk_str_jsondec_reclimit
2358#define DUK_STR_JSONENC_RECLIMIT duk_str_jsonenc_reclimit
2359#define DUK_STR_CYCLIC_INPUT duk_str_cyclic_input
2360
2361#if !defined(DUK_SINGLE_FILE)
2367#endif /* !DUK_SINGLE_FILE */
2368
2369#define DUK_STR_PROXY_REVOKED duk_str_proxy_revoked
2370#define DUK_STR_INVALID_BASE duk_str_invalid_base
2371#define DUK_STR_STRICT_CALLER_READ duk_str_strict_caller_read
2372#define DUK_STR_PROXY_REJECTED duk_str_proxy_rejected
2373#define DUK_STR_INVALID_ARRAY_LENGTH duk_str_invalid_array_length
2374#define DUK_STR_ARRAY_LENGTH_WRITE_FAILED duk_str_array_length_write_failed
2375#define DUK_STR_ARRAY_LENGTH_NOT_WRITABLE duk_str_array_length_not_writable
2376#define DUK_STR_SETTER_UNDEFINED duk_str_setter_undefined
2377#define DUK_STR_REDEFINE_VIRT_PROP duk_str_redefine_virt_prop
2378#define DUK_STR_INVALID_DESCRIPTOR duk_str_invalid_descriptor
2379#define DUK_STR_PROPERTY_IS_VIRTUAL duk_str_property_is_virtual
2380
2381#if !defined(DUK_SINGLE_FILE)
2393#endif /* !DUK_SINGLE_FILE */
2394
2395#define DUK_STR_PARSE_ERROR duk_str_parse_error
2396#define DUK_STR_DUPLICATE_LABEL duk_str_duplicate_label
2397#define DUK_STR_INVALID_LABEL duk_str_invalid_label
2398#define DUK_STR_INVALID_ARRAY_LITERAL duk_str_invalid_array_literal
2399#define DUK_STR_INVALID_OBJECT_LITERAL duk_str_invalid_object_literal
2400#define DUK_STR_INVALID_VAR_DECLARATION duk_str_invalid_var_declaration
2401#define DUK_STR_CANNOT_DELETE_IDENTIFIER duk_str_cannot_delete_identifier
2402#define DUK_STR_INVALID_EXPRESSION duk_str_invalid_expression
2403#define DUK_STR_INVALID_LVALUE duk_str_invalid_lvalue
2404#define DUK_STR_EXPECTED_IDENTIFIER duk_str_expected_identifier
2405#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED duk_str_empty_expr_not_allowed
2406#define DUK_STR_INVALID_FOR duk_str_invalid_for
2407#define DUK_STR_INVALID_SWITCH duk_str_invalid_switch
2408#define DUK_STR_INVALID_BREAK_CONT_LABEL duk_str_invalid_break_cont_label
2409#define DUK_STR_INVALID_RETURN duk_str_invalid_return
2410#define DUK_STR_INVALID_TRY duk_str_invalid_try
2411#define DUK_STR_INVALID_THROW duk_str_invalid_throw
2412#define DUK_STR_WITH_IN_STRICT_MODE duk_str_with_in_strict_mode
2413#define DUK_STR_FUNC_STMT_NOT_ALLOWED duk_str_func_stmt_not_allowed
2414#define DUK_STR_UNTERMINATED_STMT duk_str_unterminated_stmt
2415#define DUK_STR_INVALID_ARG_NAME duk_str_invalid_arg_name
2416#define DUK_STR_INVALID_FUNC_NAME duk_str_invalid_func_name
2417#define DUK_STR_INVALID_GETSET_NAME duk_str_invalid_getset_name
2418#define DUK_STR_FUNC_NAME_REQUIRED duk_str_func_name_required
2419
2420#if !defined(DUK_SINGLE_FILE)
2445#endif /* !DUK_SINGLE_FILE */
2446
2447#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM duk_str_invalid_quantifier_no_atom
2448#define DUK_STR_INVALID_QUANTIFIER_VALUES duk_str_invalid_quantifier_values
2449#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES duk_str_quantifier_too_many_copies
2450#define DUK_STR_UNEXPECTED_CLOSING_PAREN duk_str_unexpected_closing_paren
2451#define DUK_STR_UNEXPECTED_END_OF_PATTERN duk_str_unexpected_end_of_pattern
2452#define DUK_STR_UNEXPECTED_REGEXP_TOKEN duk_str_unexpected_regexp_token
2453#define DUK_STR_INVALID_REGEXP_FLAGS duk_str_invalid_regexp_flags
2454#define DUK_STR_INVALID_BACKREFS duk_str_invalid_backrefs
2455
2456#if !defined(DUK_SINGLE_FILE)
2465#endif /* !DUK_SINGLE_FILE */
2466
2467#define DUK_STR_VALSTACK_LIMIT duk_str_valstack_limit
2468#define DUK_STR_CALLSTACK_LIMIT duk_str_callstack_limit
2469#define DUK_STR_CATCHSTACK_LIMIT duk_str_catchstack_limit
2470#define DUK_STR_PROTOTYPE_CHAIN_LIMIT duk_str_prototype_chain_limit
2471#define DUK_STR_BOUND_CHAIN_LIMIT duk_str_bound_chain_limit
2472#define DUK_STR_C_CALLSTACK_LIMIT duk_str_c_callstack_limit
2473#define DUK_STR_COMPILER_RECURSION_LIMIT duk_str_compiler_recursion_limit
2474#define DUK_STR_BYTECODE_LIMIT duk_str_bytecode_limit
2475#define DUK_STR_REG_LIMIT duk_str_reg_limit
2476#define DUK_STR_TEMP_LIMIT duk_str_temp_limit
2477#define DUK_STR_CONST_LIMIT duk_str_const_limit
2478#define DUK_STR_FUNC_LIMIT duk_str_func_limit
2479#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT duk_str_regexp_compiler_recursion_limit
2480#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT duk_str_regexp_executor_recursion_limit
2481#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT duk_str_regexp_executor_step_limit
2482
2483#if !defined(DUK_SINGLE_FILE)
2499#endif /* !DUK_SINGLE_FILE */
2500
2501#if !defined(DUK_SINGLE_FILE)
2503#endif /* !DUK_SINGLE_FILE */
2504
2505#endif /* DUK_ERRMSG_H_INCLUDED */
2506/*
2507 * Ecmascript bytecode
2508 */
2509
2510#ifndef DUK_JS_BYTECODE_H_INCLUDED
2511#define DUK_JS_BYTECODE_H_INCLUDED
2512
2513/*
2514 * Logical instruction layout
2515 * ==========================
2516 *
2517 * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
2518 * !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!
2519 * +---------------------------------------------------+-----------+
2520 * ! C ! B ! A ! OP !
2521 * +---------------------------------------------------+-----------+
2522 *
2523 * OP (6 bits): opcode (DUK_OP_*), access should be fastest
2524 * A (8 bits): typically a target register number
2525 * B (9 bits): typically first source register/constant number
2526 * C (9 bits): typically second source register/constant number
2527 *
2528 * Some instructions combine BC or ABC together for larger parameter values.
2529 * Signed integers (e.g. jump offsets) are encoded as unsigned, with an opcode
2530 * specific bias. B and C may denote a register or a constant, see
2531 * DUK_BC_ISREG() and DUK_BC_ISCONST().
2532 *
2533 * Note: macro naming is a bit misleading, e.g. "ABC" in macro name but
2534 * the field layout is logically "CBA".
2535 */
2536
2537typedef duk_uint32_t duk_instr_t;
2538
2539#define DUK_DEC_OP(x) ((x) & 0x3fUL)
2540#define DUK_DEC_A(x) (((x) >> 6) & 0xffUL)
2541#define DUK_DEC_B(x) (((x) >> 14) & 0x1ffUL)
2542#define DUK_DEC_C(x) (((x) >> 23) & 0x1ffUL)
2543#define DUK_DEC_BC(x) (((x) >> 14) & 0x3ffffUL)
2544#define DUK_DEC_ABC(x) (((x) >> 6) & 0x3ffffffUL)
2545
2546#define DUK_ENC_OP(op) ((duk_instr_t) (op))
2547#define DUK_ENC_OP_ABC(op,abc) ((duk_instr_t) ( \
2548 (((duk_instr_t) (abc)) << 6) | \
2549 ((duk_instr_t) (op)) \
2550 ))
2551#define DUK_ENC_OP_A_BC(op,a,bc) ((duk_instr_t) ( \
2552 (((duk_instr_t) (bc)) << 14) | \
2553 (((duk_instr_t) (a)) << 6) | \
2554 ((duk_instr_t) (op)) \
2555 ))
2556#define DUK_ENC_OP_A_B_C(op,a,b,c) ((duk_instr_t) ( \
2557 (((duk_instr_t) (c)) << 23) | \
2558 (((duk_instr_t) (b)) << 14) | \
2559 (((duk_instr_t) (a)) << 6) | \
2560 ((duk_instr_t) (op)) \
2561 ))
2562#define DUK_ENC_OP_A_B(op,a,b) DUK_ENC_OP_A_B_C(op,a,b,0)
2563#define DUK_ENC_OP_A(op,a) DUK_ENC_OP_A_B_C(op,a,0,0)
2564
2565/* Constants should be signed so that signed arithmetic involving them
2566 * won't cause values to be coerced accidentally to unsigned.
2567 */
2568#define DUK_BC_OP_MIN 0
2569#define DUK_BC_OP_MAX 0x3fL
2570#define DUK_BC_A_MIN 0
2571#define DUK_BC_A_MAX 0xffL
2572#define DUK_BC_B_MIN 0
2573#define DUK_BC_B_MAX 0x1ffL
2574#define DUK_BC_C_MIN 0
2575#define DUK_BC_C_MAX 0x1ffL
2576#define DUK_BC_BC_MIN 0
2577#define DUK_BC_BC_MAX 0x3ffffL
2578#define DUK_BC_ABC_MIN 0
2579#define DUK_BC_ABC_MAX 0x3ffffffL
2580#define DUK_BC_EXTRAOP_MIN DUK_BC_A_MIN
2581#define DUK_BC_EXTRAOP_MAX DUK_BC_A_MAX
2582
2583#define DUK_OP_LDREG 0
2584#define DUK_OP_STREG 1
2585#define DUK_OP_LDCONST 2
2586#define DUK_OP_LDINT 3
2587#define DUK_OP_LDINTX 4
2588#define DUK_OP_MPUTOBJ 5
2589#define DUK_OP_MPUTOBJI 6
2590#define DUK_OP_MPUTARR 7
2591#define DUK_OP_MPUTARRI 8
2592#define DUK_OP_NEW 9
2593#define DUK_OP_NEWI 10
2594#define DUK_OP_REGEXP 11
2595#define DUK_OP_CSREG 12
2596#define DUK_OP_CSREGI 13
2597#define DUK_OP_GETVAR 14
2598#define DUK_OP_PUTVAR 15
2599#define DUK_OP_DECLVAR 16
2600#define DUK_OP_DELVAR 17
2601#define DUK_OP_CSVAR 18
2602#define DUK_OP_CSVARI 19
2603#define DUK_OP_CLOSURE 20
2604#define DUK_OP_GETPROP 21
2605#define DUK_OP_PUTPROP 22
2606#define DUK_OP_DELPROP 23
2607#define DUK_OP_CSPROP 24
2608#define DUK_OP_CSPROPI 25
2609#define DUK_OP_ADD 26
2610#define DUK_OP_SUB 27
2611#define DUK_OP_MUL 28
2612#define DUK_OP_DIV 29
2613#define DUK_OP_MOD 30
2614#define DUK_OP_BAND 31
2615#define DUK_OP_BOR 32
2616#define DUK_OP_BXOR 33
2617#define DUK_OP_BASL 34
2618#define DUK_OP_BLSR 35
2619#define DUK_OP_BASR 36
2620#define DUK_OP_EQ 37
2621#define DUK_OP_NEQ 38
2622#define DUK_OP_SEQ 39
2623#define DUK_OP_SNEQ 40
2624#define DUK_OP_GT 41
2625#define DUK_OP_GE 42
2626#define DUK_OP_LT 43
2627#define DUK_OP_LE 44
2628#define DUK_OP_IF 45
2629#define DUK_OP_JUMP 46
2630#define DUK_OP_RETURN 47
2631#define DUK_OP_CALL 48
2632#define DUK_OP_CALLI 49
2633#define DUK_OP_TRYCATCH 50
2634#define DUK_OP_EXTRA 51
2635#define DUK_OP_PREINCR 52 /* pre/post opcode values have constraints, */
2636#define DUK_OP_PREDECR 53 /* see duk_js_executor.c */
2637#define DUK_OP_POSTINCR 54
2638#define DUK_OP_POSTDECR 55
2639#define DUK_OP_PREINCV 56
2640#define DUK_OP_PREDECV 57
2641#define DUK_OP_POSTINCV 58
2642#define DUK_OP_POSTDECV 59
2643#define DUK_OP_PREINCP 60
2644#define DUK_OP_PREDECP 61
2645#define DUK_OP_POSTINCP 62
2646#define DUK_OP_POSTDECP 63
2647#define DUK_OP_NONE 64 /* dummy value used as marker */
2648
2649/* DUK_OP_EXTRA, sub-operation in A */
2650#define DUK_EXTRAOP_NOP 0
2651#define DUK_EXTRAOP_INVALID 1
2652#define DUK_EXTRAOP_LDTHIS 2
2653#define DUK_EXTRAOP_LDUNDEF 3
2654#define DUK_EXTRAOP_LDNULL 4
2655#define DUK_EXTRAOP_LDTRUE 5
2656#define DUK_EXTRAOP_LDFALSE 6
2657#define DUK_EXTRAOP_NEWOBJ 7
2658#define DUK_EXTRAOP_NEWARR 8
2659#define DUK_EXTRAOP_SETALEN 9
2660#define DUK_EXTRAOP_TYPEOF 10
2661#define DUK_EXTRAOP_TYPEOFID 11
2662#define DUK_EXTRAOP_INITENUM 12
2663#define DUK_EXTRAOP_NEXTENUM 13
2664#define DUK_EXTRAOP_INITSET 14
2665#define DUK_EXTRAOP_INITSETI 15
2666#define DUK_EXTRAOP_INITGET 16
2667#define DUK_EXTRAOP_INITGETI 17
2668#define DUK_EXTRAOP_ENDTRY 18
2669#define DUK_EXTRAOP_ENDCATCH 19
2670#define DUK_EXTRAOP_ENDFIN 20
2671#define DUK_EXTRAOP_THROW 21
2672#define DUK_EXTRAOP_INVLHS 22
2673#define DUK_EXTRAOP_UNM 23
2674#define DUK_EXTRAOP_UNP 24
2675#define DUK_EXTRAOP_DEBUGGER 25
2676#define DUK_EXTRAOP_BREAK 26
2677#define DUK_EXTRAOP_CONTINUE 27
2678#define DUK_EXTRAOP_BNOT 28
2679#define DUK_EXTRAOP_LNOT 29
2680#define DUK_EXTRAOP_INSTOF 30
2681#define DUK_EXTRAOP_IN 31
2682#define DUK_EXTRAOP_LABEL 32
2683#define DUK_EXTRAOP_ENDLABEL 33
2684
2685/* DUK_OP_CALL flags in A */
2686#define DUK_BC_CALL_FLAG_TAILCALL (1 << 0)
2687#define DUK_BC_CALL_FLAG_EVALCALL (1 << 1)
2688
2689/* DUK_OP_TRYCATCH flags in A */
2690#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1 << 0)
2691#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1 << 1)
2692#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1 << 2)
2693#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1 << 3)
2694
2695/* DUK_OP_RETURN flags in A */
2696#define DUK_BC_RETURN_FLAG_HAVE_RETVAL (1 << 0)
2697
2698/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags (DUK_PROPDESC_FLAG_XXX) */
2699#define DUK_BC_DECLVAR_FLAG_UNDEF_VALUE (1 << 4) /* use 'undefined' for value automatically */
2700#define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1 << 5) /* function declaration */
2701
2702/* misc constants and helper macros */
2703#define DUK_BC_REGLIMIT 256 /* if B/C is >= this value, refers to a const */
2704#define DUK_BC_ISREG(x) ((x) < DUK_BC_REGLIMIT)
2705#define DUK_BC_ISCONST(x) ((x) >= DUK_BC_REGLIMIT)
2706#define DUK_BC_LDINT_BIAS (1L << 17)
2707#define DUK_BC_LDINTX_SHIFT 18
2708#define DUK_BC_JUMP_BIAS (1L << 25)
2709
2710#endif /* DUK_JS_BYTECODE_H_INCLUDED */
2711/*
2712 * Lexer defines.
2713 */
2714
2715#ifndef DUK_LEXER_H_INCLUDED
2716#define DUK_LEXER_H_INCLUDED
2717
2718typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
2719
2720/*
2721 * A token is interpreted as any possible production of InputElementDiv
2722 * and InputElementRegExp, see E5 Section 7 in its entirety. Note that
2723 * the E5 "Token" production does not cover all actual tokens of the
2724 * language (which is explicitly stated in the specification, Section 7.5).
2725 * Null and boolean literals are defined as part of both ReservedWord
2726 * (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions. Here,
2727 * null and boolean values have literal tokens, and are not reserved
2728 * words.
2729 *
2730 * Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
2731 * The number tokens always have a non-negative value. The unary minus
2732 * operator in "-1.0" is optimized during compilation to yield a single
2733 * negative constant.
2734 *
2735 * Token numbering is free except that reserved words are required to be
2736 * in a continuous range and in a particular order. See genstrings.py.
2737 */
2738
2739#define DUK_LEXER_INITCTX(ctx) duk_lexer_initctx((ctx))
2740
2741#define DUK_LEXER_SETPOINT(ctx,pt) duk_lexer_setpoint((ctx), (pt))
2742
2743#define DUK_LEXER_GETPOINT(ctx,pt) do { (pt)->offset = (ctx)->window[0].offset; \
2744 (pt)->line = (ctx)->window[0].line; } while (0)
2745
2746/* currently 6 characters of lookup are actually needed (duk_lexer.c) */
2747#define DUK_LEXER_WINDOW_SIZE 6
2748#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
2749#define DUK_LEXER_BUFFER_SIZE 64
2750#endif
2751
2752#define DUK_TOK_MINVAL 0
2753
2754/* returned after EOF (infinite amount) */
2755#define DUK_TOK_EOF 0
2756
2757/* identifier names (E5 Section 7.6) */
2758#define DUK_TOK_IDENTIFIER 1
2759
2760/* reserved words: keywords */
2761#define DUK_TOK_START_RESERVED 2
2762#define DUK_TOK_BREAK 2
2763#define DUK_TOK_CASE 3
2764#define DUK_TOK_CATCH 4
2765#define DUK_TOK_CONTINUE 5
2766#define DUK_TOK_DEBUGGER 6
2767#define DUK_TOK_DEFAULT 7
2768#define DUK_TOK_DELETE 8
2769#define DUK_TOK_DO 9
2770#define DUK_TOK_ELSE 10
2771#define DUK_TOK_FINALLY 11
2772#define DUK_TOK_FOR 12
2773#define DUK_TOK_FUNCTION 13
2774#define DUK_TOK_IF 14
2775#define DUK_TOK_IN 15
2776#define DUK_TOK_INSTANCEOF 16
2777#define DUK_TOK_NEW 17
2778#define DUK_TOK_RETURN 18
2779#define DUK_TOK_SWITCH 19
2780#define DUK_TOK_THIS 20
2781#define DUK_TOK_THROW 21
2782#define DUK_TOK_TRY 22
2783#define DUK_TOK_TYPEOF 23
2784#define DUK_TOK_VAR 24
2785#define DUK_TOK_CONST 25
2786#define DUK_TOK_VOID 26
2787#define DUK_TOK_WHILE 27
2788#define DUK_TOK_WITH 28
2789
2790/* reserved words: future reserved words */
2791#define DUK_TOK_CLASS 29
2792#define DUK_TOK_ENUM 30
2793#define DUK_TOK_EXPORT 31
2794#define DUK_TOK_EXTENDS 32
2795#define DUK_TOK_IMPORT 33
2796#define DUK_TOK_SUPER 34
2797
2798/* "null", "true", and "false" are always reserved words.
2799 * Note that "get" and "set" are not!
2800 */
2801#define DUK_TOK_NULL 35
2802#define DUK_TOK_TRUE 36
2803#define DUK_TOK_FALSE 37
2804
2805/* reserved words: additional future reserved words in strict mode */
2806#define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */
2807#define DUK_TOK_IMPLEMENTS 38
2808#define DUK_TOK_INTERFACE 39
2809#define DUK_TOK_LET 40
2810#define DUK_TOK_PACKAGE 41
2811#define DUK_TOK_PRIVATE 42
2812#define DUK_TOK_PROTECTED 43
2813#define DUK_TOK_PUBLIC 44
2814#define DUK_TOK_STATIC 45
2815#define DUK_TOK_YIELD 46
2816
2817#define DUK_TOK_END_RESERVED 47 /* exclusive */
2818
2819/* "get" and "set" are tokens but NOT ReservedWords. They are currently
2820 * parsed and identifiers and these defines are actually now unused.
2821 */
2822#define DUK_TOK_GET 47
2823#define DUK_TOK_SET 48
2824
2825/* punctuators (unlike the spec, also includes "/" and "/=") */
2826#define DUK_TOK_LCURLY 49
2827#define DUK_TOK_RCURLY 50
2828#define DUK_TOK_LBRACKET 51
2829#define DUK_TOK_RBRACKET 52
2830#define DUK_TOK_LPAREN 53
2831#define DUK_TOK_RPAREN 54
2832#define DUK_TOK_PERIOD 55
2833#define DUK_TOK_SEMICOLON 56
2834#define DUK_TOK_COMMA 57
2835#define DUK_TOK_LT 58
2836#define DUK_TOK_GT 59
2837#define DUK_TOK_LE 60
2838#define DUK_TOK_GE 61
2839#define DUK_TOK_EQ 62
2840#define DUK_TOK_NEQ 63
2841#define DUK_TOK_SEQ 64
2842#define DUK_TOK_SNEQ 65
2843#define DUK_TOK_ADD 66
2844#define DUK_TOK_SUB 67
2845#define DUK_TOK_MUL 68
2846#define DUK_TOK_DIV 69
2847#define DUK_TOK_MOD 70
2848#define DUK_TOK_INCREMENT 71
2849#define DUK_TOK_DECREMENT 72
2850#define DUK_TOK_ALSHIFT 73 /* named "arithmetic" because result is signed */
2851#define DUK_TOK_ARSHIFT 74
2852#define DUK_TOK_RSHIFT 75
2853#define DUK_TOK_BAND 76
2854#define DUK_TOK_BOR 77
2855#define DUK_TOK_BXOR 78
2856#define DUK_TOK_LNOT 79
2857#define DUK_TOK_BNOT 80
2858#define DUK_TOK_LAND 81
2859#define DUK_TOK_LOR 82
2860#define DUK_TOK_QUESTION 83
2861#define DUK_TOK_COLON 84
2862#define DUK_TOK_EQUALSIGN 85
2863#define DUK_TOK_ADD_EQ 86
2864#define DUK_TOK_SUB_EQ 87
2865#define DUK_TOK_MUL_EQ 88
2866#define DUK_TOK_DIV_EQ 89
2867#define DUK_TOK_MOD_EQ 90
2868#define DUK_TOK_ALSHIFT_EQ 91
2869#define DUK_TOK_ARSHIFT_EQ 92
2870#define DUK_TOK_RSHIFT_EQ 93
2871#define DUK_TOK_BAND_EQ 94
2872#define DUK_TOK_BOR_EQ 95
2873#define DUK_TOK_BXOR_EQ 96
2874
2875/* literals (E5 Section 7.8), except null, true, false, which are treated
2876 * like reserved words (above).
2877 */
2878#define DUK_TOK_NUMBER 97
2879#define DUK_TOK_STRING 98
2880#define DUK_TOK_REGEXP 99
2881
2882#define DUK_TOK_MAXVAL 99 /* inclusive */
2883
2884/* Convert heap string index to a token (reserved words) */
2885#define DUK_STRIDX_TO_TOK(x) ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
2886
2887/* Sanity check */
2888#if (DUK_TOK_MAXVAL > 255)
2889#error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
2890#endif
2891
2892/* Sanity checks for string and token defines */
2893#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
2894#error mismatch in token defines
2895#endif
2896#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
2897#error mismatch in token defines
2898#endif
2899#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
2900#error mismatch in token defines
2901#endif
2902#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
2903#error mismatch in token defines
2904#endif
2905#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
2906#error mismatch in token defines
2907#endif
2908#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
2909#error mismatch in token defines
2910#endif
2911#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
2912#error mismatch in token defines
2913#endif
2914#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
2915#error mismatch in token defines
2916#endif
2917#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
2918#error mismatch in token defines
2919#endif
2920#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
2921#error mismatch in token defines
2922#endif
2923#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
2924#error mismatch in token defines
2925#endif
2926#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
2927#error mismatch in token defines
2928#endif
2929#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
2930#error mismatch in token defines
2931#endif
2932#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
2933#error mismatch in token defines
2934#endif
2935#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
2936#error mismatch in token defines
2937#endif
2938#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
2939#error mismatch in token defines
2940#endif
2941#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
2942#error mismatch in token defines
2943#endif
2944#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
2945#error mismatch in token defines
2946#endif
2947#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
2948#error mismatch in token defines
2949#endif
2950#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
2951#error mismatch in token defines
2952#endif
2953#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
2954#error mismatch in token defines
2955#endif
2956#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
2957#error mismatch in token defines
2958#endif
2959#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
2960#error mismatch in token defines
2961#endif
2962#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
2963#error mismatch in token defines
2964#endif
2965#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
2966#error mismatch in token defines
2967#endif
2968#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
2969#error mismatch in token defines
2970#endif
2971#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
2972#error mismatch in token defines
2973#endif
2974#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
2975#error mismatch in token defines
2976#endif
2977#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
2978#error mismatch in token defines
2979#endif
2980#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
2981#error mismatch in token defines
2982#endif
2983#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
2984#error mismatch in token defines
2985#endif
2986#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
2987#error mismatch in token defines
2988#endif
2989#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
2990#error mismatch in token defines
2991#endif
2992#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
2993#error mismatch in token defines
2994#endif
2995#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
2996#error mismatch in token defines
2997#endif
2998#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
2999#error mismatch in token defines
3000#endif
3001#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3002#error mismatch in token defines
3003#endif
3004#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
3005#error mismatch in token defines
3006#endif
3007#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
3008#error mismatch in token defines
3009#endif
3010#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
3011#error mismatch in token defines
3012#endif
3013#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
3014#error mismatch in token defines
3015#endif
3016#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
3017#error mismatch in token defines
3018#endif
3019#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
3020#error mismatch in token defines
3021#endif
3022#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
3023#error mismatch in token defines
3024#endif
3025#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
3026#error mismatch in token defines
3027#endif
3028
3029/* Regexp tokens */
3030#define DUK_RETOK_EOF 0
3031#define DUK_RETOK_DISJUNCTION 1
3032#define DUK_RETOK_QUANTIFIER 2
3033#define DUK_RETOK_ASSERT_START 3
3034#define DUK_RETOK_ASSERT_END 4
3035#define DUK_RETOK_ASSERT_WORD_BOUNDARY 5
3036#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY 6
3037#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD 7
3038#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD 8
3039#define DUK_RETOK_ATOM_PERIOD 9
3040#define DUK_RETOK_ATOM_CHAR 10
3041#define DUK_RETOK_ATOM_DIGIT 11
3042#define DUK_RETOK_ATOM_NOT_DIGIT 12
3043#define DUK_RETOK_ATOM_WHITE 13
3044#define DUK_RETOK_ATOM_NOT_WHITE 14
3045#define DUK_RETOK_ATOM_WORD_CHAR 15
3046#define DUK_RETOK_ATOM_NOT_WORD_CHAR 16
3047#define DUK_RETOK_ATOM_BACKREFERENCE 17
3048#define DUK_RETOK_ATOM_START_CAPTURE_GROUP 18
3049#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP 19
3050#define DUK_RETOK_ATOM_START_CHARCLASS 20
3051#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21
3052#define DUK_RETOK_ATOM_END_GROUP 22
3053
3054/* Constants for duk_lexer_ctx.buf. */
3055#define DUK_LEXER_TEMP_BUF_LIMIT 256
3056
3057/* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
3058 * Some fields (like num, str1, str2) are only valid for specific token types and may have
3059 * stale values otherwise.
3060 */
3062 duk_small_int_t t; /* token type (with reserved word identification) */
3063 duk_small_int_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */
3064 duk_double_t num; /* numeric value of token */
3065 duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
3066 duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
3067 duk_size_t start_offset; /* start byte offset of token in lexer input */
3068 duk_int_t start_line; /* start line of token (first char) */
3069 duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */
3070 duk_bool_t lineterm; /* token was preceded by a lineterm */
3071 duk_bool_t allow_auto_semi; /* token allows automatic semicolon insertion (eof or preceded by newline) */
3072};
3073
3074#define DUK_RE_QUANTIFIER_INFINITE ((duk_uint32_t) 0xffffffffUL)
3075
3076/* A regexp token value. */
3084
3085/* A structure for 'snapshotting' a point for rewinding */
3090
3091/* Lexer codepoint with additional info like offset/line number */
3097
3098/* Lexer context. Same context is used for Ecmascript and Regexp parsing. */
3100#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3101 duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
3103#else
3104 duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
3105#endif
3106
3107 duk_hthread *thr; /* thread; minimizes argument passing */
3108
3109 const duk_uint8_t *input; /* input string (may be a user pointer) */
3110 duk_size_t input_length; /* input byte length */
3111 duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */
3112 duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */
3113
3114 duk_idx_t slot1_idx; /* valstack slot for 1st token value */
3115 duk_idx_t slot2_idx; /* valstack slot for 2nd token value */
3116 duk_idx_t buf_idx; /* valstack slot for temp buffer */
3117 duk_hbuffer_dynamic *buf; /* temp accumulation buffer */
3118 duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */
3119
3120 duk_int_t token_count; /* number of tokens parsed */
3121 duk_int_t token_limit; /* maximum token count before error (sanity backstop) */
3122};
3123
3124/*
3125 * Prototypes
3126 */
3127
3129
3131
3134 duk_token *out_token,
3135 duk_bool_t strict_mode,
3136 duk_bool_t regexp_mode);
3137#ifdef DUK_USE_REGEXP_SUPPORT
3139DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
3140#endif /* DUK_USE_REGEXP_SUPPORT */
3141
3142#endif /* DUK_LEXER_H_INCLUDED */
3143/*
3144 * Ecmascript compiler.
3145 */
3146
3147#ifndef DUK_JS_COMPILER_H_INCLUDED
3148#define DUK_JS_COMPILER_H_INCLUDED
3149
3150/* ecmascript compiler limits */
3151#define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */
3152
3153/* maximum loopcount for peephole optimization */
3154#define DUK_COMPILER_PEEPHOLE_MAXITER 3
3155
3156/* maximum bytecode length in instructions */
3157#define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */
3158
3159/*
3160 * Compiler intermediate values
3161 *
3162 * Intermediate values describe either plain values (e.g. strings or
3163 * numbers) or binary operations which have not yet been coerced into
3164 * either a left-hand-side or right-hand-side role (e.g. object property).
3165 */
3166
3167#define DUK_IVAL_NONE 0 /* no value */
3168#define DUK_IVAL_PLAIN 1 /* register, constant, or value */
3169#define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
3170#define DUK_IVAL_ARITH_EXTRAOP 3 /* binary arithmetic using extraops; DUK_EXTRAOP_INSTOF etc */
3171#define DUK_IVAL_PROP 4 /* property access */
3172#define DUK_IVAL_VAR 5 /* variable access */
3173
3174#define DUK_ISPEC_NONE 0 /* no value */
3175#define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */
3176#define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */
3177
3178/* bit mask which indicates that a regconst is a constant instead of a register */
3179#define DUK_JS_CONST_MARKER 0x80000000UL
3180
3181/* type to represent a reg/const reference during compilation */
3182typedef duk_uint32_t duk_regconst_t;
3183
3184/* type to represent a straight register reference, with <0 indicating none */
3185typedef duk_int32_t duk_reg_t;
3186
3187typedef struct {
3188 duk_small_uint_t t; /* DUK_ISPEC_XXX */
3190 duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */
3191} duk_ispec;
3192
3193typedef struct {
3194 /*
3195 * PLAIN: x1
3196 * ARITH: x1 <op> x2
3197 * PROP: x1.x2
3198 * VAR: x1 (name)
3199 */
3200
3201 /* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
3202 duk_small_uint_t t; /* DUK_IVAL_XXX */
3203 duk_small_uint_t op; /* bytecode opcode (or extraop) for binary ops */
3206} duk_ivalue;
3207
3208/*
3209 * Bytecode instruction representation during compilation
3210 *
3211 * Contains the actual instruction and (optionally) debug info.
3212 */
3213
3216#if defined(DUK_USE_PC2LINE)
3217 duk_uint32_t line;
3218#endif
3219};
3220
3221/*
3222 * Compiler state
3223 */
3224
3225#define DUK_LABEL_FLAG_ALLOW_BREAK (1 << 0)
3226#define DUK_LABEL_FLAG_ALLOW_CONTINUE (1 << 1)
3227
3228#define DUK_DECL_TYPE_VAR 0
3229#define DUK_DECL_TYPE_FUNC 1
3230
3231/* XXX: optimize to 16 bytes */
3232typedef struct {
3234 duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */
3235 duk_hstring *h_label; /* borrowed label name */
3236 duk_int_t catch_depth; /* catch depth at point of definition */
3237 duk_int_t pc_label; /* pc of label statement:
3238 * pc+1: break jump site
3239 * pc+2: continue jump site
3240 */
3241
3242 /* Fast jumps (which avoid longjmp) jump directly to the jump sites
3243 * which are always known even while the iteration/switch statement
3244 * is still being parsed. A final peephole pass "straightens out"
3245 * the jumps.
3246 */
3248
3249/* Compiling state of one function, eventually converted to duk_hcompiledfunction */
3251 /* These pointers are at the start of the struct so that they pack
3252 * nicely. Mixing pointers and integer values is bad on some
3253 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
3254 */
3255
3256 duk_bufwriter_ctx bw_code; /* bufwriter for code */
3257
3258 duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */
3259 /* h_code: held in bw_code */
3260 duk_hobject *h_consts; /* array */
3261 duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
3262 * offset/line points to closing brace to allow skipping on pass 2
3263 */
3264 duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ]
3265 * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
3266 * record function and variable declarations in pass 1
3267 */
3268 duk_hobject *h_labelnames; /* array of active label names */
3269 duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */
3270 duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */
3271 duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
3272
3273 /* value stack indices for tracking objects */
3274 /* code_idx: not needed */
3282
3283 /* temp reg handling */
3284 duk_reg_t temp_first; /* first register that is a temporary (below: variables) */
3285 duk_reg_t temp_next; /* next temporary register to allocate */
3286 duk_reg_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */
3287
3288 /* shuffle registers if large number of regs/consts */
3292
3293 /* stats for current expression being parsed */
3296 duk_int_t paren_level; /* parenthesis count, 0 = top level */
3297 duk_bool_t expr_lhs; /* expression is left-hand-side compatible */
3298 duk_bool_t allow_in; /* current paren level allows 'in' token */
3299
3300 /* misc */
3301 duk_int_t stmt_next; /* statement id allocation (running counter) */
3302 duk_int_t label_next; /* label id allocation (running counter) */
3303 duk_int_t catch_depth; /* catch stack depth */
3304 duk_int_t with_depth; /* with stack depth (affects identifier lookups) */
3305 duk_int_t fnum_next; /* inner function numbering */
3306 duk_int_t num_formals; /* number of formal arguments */
3307 duk_reg_t reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
3308#if defined(DUK_USE_DEBUGGER_SUPPORT)
3309 duk_int_t min_line; /* XXX: typing (duk_hcompiledfunction has duk_uint32_t) */
3310 duk_int_t max_line;
3311#endif
3312
3313 /* status booleans */
3314 duk_bool_t is_function; /* is an actual function (not global/eval code) */
3315 duk_bool_t is_eval; /* is eval code */
3316 duk_bool_t is_global; /* is global code */
3317 duk_bool_t is_setget; /* is a setter/getter */
3318 duk_bool_t is_decl; /* is a function declaration (as opposed to function expression) */
3319 duk_bool_t is_strict; /* function is strict */
3320 duk_bool_t is_notail; /* function must not be tail called */
3321 duk_bool_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */
3322 duk_bool_t in_scanning; /* parsing in "scanning" phase (first pass) */
3323 duk_bool_t may_direct_eval; /* function may call direct eval */
3324 duk_bool_t id_access_arguments; /* function refers to 'arguments' identifier */
3325 duk_bool_t id_access_slow; /* function makes one or more slow path accesses */
3326 duk_bool_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */
3327 duk_bool_t needs_shuffle; /* function needs shuffle registers */
3328 duk_bool_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
3329};
3330
3333
3334 /* filename being compiled (ends up in functions' '_filename' property) */
3335 duk_hstring *h_filename; /* borrowed reference */
3336
3337 /* lexing (tokenization) state (contains two valstack slot indices) */
3339
3340 /* current and previous token for parsing */
3343 duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */
3344 duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */
3345 duk_idx_t tok21_idx; /* prev_token slot1 */
3346 duk_idx_t tok22_idx; /* prev_token slot2 */
3347
3348 /* recursion limit */
3351
3352 /* code emission temporary */
3354
3355 /* current function being compiled (embedded instead of pointer for more compact access) */
3357};
3358
3359/*
3360 * Prototypes
3361 */
3362
3363#define DUK_JS_COMPILE_FLAG_EVAL (1 << 0) /* source is eval code (not global) */
3364#define DUK_JS_COMPILE_FLAG_STRICT (1 << 1) /* strict outer context */
3365#define DUK_JS_COMPILE_FLAG_FUNCEXPR (1 << 2) /* source is a function expression (used for Function constructor) */
3366
3367DUK_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);
3368
3369#endif /* DUK_JS_COMPILER_H_INCLUDED */
3370/*
3371 * Regular expression structs, constants, and bytecode defines.
3372 */
3373
3374#ifndef DUK_REGEXP_H_INCLUDED
3375#define DUK_REGEXP_H_INCLUDED
3376
3377/* maximum bytecode copies for {n,m} quantifiers */
3378#define DUK_RE_MAX_ATOM_COPIES 1000
3379
3380/* regexp compilation limits */
3381#define DUK_RE_COMPILE_TOKEN_LIMIT 100000000L /* 1e8 */
3382
3383/* regexp execution limits */
3384#define DUK_RE_EXECUTE_STEPS_LIMIT 1000000000L /* 1e9 */
3385
3386/* regexp opcodes */
3387#define DUK_REOP_MATCH 1
3388#define DUK_REOP_CHAR 2
3389#define DUK_REOP_PERIOD 3
3390#define DUK_REOP_RANGES 4
3391#define DUK_REOP_INVRANGES 5
3392#define DUK_REOP_JUMP 6
3393#define DUK_REOP_SPLIT1 7
3394#define DUK_REOP_SPLIT2 8
3395#define DUK_REOP_SQMINIMAL 9
3396#define DUK_REOP_SQGREEDY 10
3397#define DUK_REOP_SAVE 11
3398#define DUK_REOP_WIPERANGE 12
3399#define DUK_REOP_LOOKPOS 13
3400#define DUK_REOP_LOOKNEG 14
3401#define DUK_REOP_BACKREFERENCE 15
3402#define DUK_REOP_ASSERT_START 16
3403#define DUK_REOP_ASSERT_END 17
3404#define DUK_REOP_ASSERT_WORD_BOUNDARY 18
3405#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY 19
3406
3407/* flags */
3408#define DUK_RE_FLAG_GLOBAL (1 << 0)
3409#define DUK_RE_FLAG_IGNORE_CASE (1 << 1)
3410#define DUK_RE_FLAG_MULTILINE (1 << 2)
3411
3414
3415 duk_uint32_t re_flags;
3416 const duk_uint8_t *input;
3417 const duk_uint8_t *input_end;
3418 const duk_uint8_t *bytecode;
3419 const duk_uint8_t *bytecode_end;
3420 const duk_uint8_t **saved; /* allocated from valstack (fixed buffer) */
3421 duk_uint32_t nsaved;
3422 duk_uint32_t recursion_depth;
3423 duk_uint32_t recursion_limit;
3424 duk_uint32_t steps_count;
3425 duk_uint32_t steps_limit;
3426};
3427
3430
3431 duk_uint32_t re_flags;
3435 duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */
3436 duk_uint32_t highest_backref;
3437 duk_uint32_t recursion_depth;
3438 duk_uint32_t recursion_limit;
3439 duk_uint32_t nranges; /* internal temporary value, used for char classes */
3440};
3441
3442/*
3443 * Prototypes
3444 */
3445
3449DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hacky helper for String.prototype.split() */
3450
3451#endif /* DUK_REGEXP_H_INCLUDED */
3452/*
3453 * Heap header definition and assorted macros, including ref counting.
3454 * Access all fields through the accessor macros.
3455 */
3456
3457#ifndef DUK_HEAPHDR_H_INCLUDED
3458#define DUK_HEAPHDR_H_INCLUDED
3459
3460/*
3461 * Common heap header
3462 *
3463 * All heap objects share the same flags and refcount fields. Objects other
3464 * than strings also need to have a single or double linked list pointers
3465 * for insertion into the "heap allocated" list. Strings are held in the
3466 * heap-wide string table so they don't need link pointers.
3467 *
3468 * Technically, 'h_refcount' must be wide enough to guarantee that it cannot
3469 * wrap (otherwise objects might be freed incorrectly after wrapping). This
3470 * means essentially that the refcount field must be as wide as data pointers.
3471 * On 64-bit platforms this means that the refcount needs to be 64 bits even
3472 * if an 'int' is 32 bits. This is a bit unfortunate, and compromising on
3473 * this might be reasonable in the future.
3474 *
3475 * Heap header size on 32-bit platforms: 8 bytes without reference counting,
3476 * 16 bytes with reference counting.
3477 */
3478
3480 duk_uint32_t h_flags;
3481
3482#if defined(DUK_USE_REFERENCE_COUNTING)
3483#if defined(DUK_USE_REFCOUNT16)
3484 duk_uint16_t h_refcount16;
3485#else
3487#endif
3488#endif
3489
3490#if defined(DUK_USE_HEAPPTR16)
3491 duk_uint16_t h_next16;
3492#else
3494#endif
3495
3496#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3497 /* refcounting requires direct heap frees, which in turn requires a dual linked heap */
3498#if defined(DUK_USE_HEAPPTR16)
3499 duk_uint16_t h_prev16;
3500#else
3502#endif
3503#endif
3504
3505 /* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
3506 * struct won't align nicely to 4 bytes. This 16-bit extra field
3507 * is added to make the alignment clean; the field can be used by
3508 * heap objects when 16-bit packing is used. This field is now
3509 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
3510 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
3511 * this only matter to low memory environments anyway.
3512 */
3513#if defined(DUK_USE_HEAPPTR16)
3514 duk_uint16_t h_extra16;
3515#endif
3516};
3517
3519 /* 16 bits would be enough for shared heaphdr flags and duk_hstring
3520 * flags. The initial parts of duk_heaphdr_string and duk_heaphdr
3521 * must match so changing the flags field size here would be quite
3522 * awkward. However, to minimize struct size, we can pack at least
3523 * 16 bits of duk_hstring data into the flags field.
3524 */
3525 duk_uint32_t h_flags;
3526
3527#if defined(DUK_USE_REFERENCE_COUNTING)
3528#if defined(DUK_USE_REFCOUNT16)
3529 duk_uint16_t h_refcount16;
3530 duk_uint16_t h_strextra16; /* round out to 8 bytes */
3531#else
3533#endif
3534#endif
3535};
3536
3537#define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL
3538#define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
3539
3540 /* 2 bits for heap type */
3541#define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */
3542#define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */
3543
3544#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
3545#define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n))
3546#define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
3547#define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
3548
3549#define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */
3550#define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */
3551#define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */
3552#define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */
3553#define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */
3554
3555#define DUK_HTYPE_MIN 1
3556#define DUK_HTYPE_STRING 1
3557#define DUK_HTYPE_OBJECT 2
3558#define DUK_HTYPE_BUFFER 3
3559#define DUK_HTYPE_MAX 3
3560
3561#if defined(DUK_USE_HEAPPTR16)
3562#define DUK_HEAPHDR_GET_NEXT(heap,h) \
3563 ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
3564#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
3565 (h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
3566 } while (0)
3567#else
3568#define DUK_HEAPHDR_GET_NEXT(heap,h) ((h)->h_next)
3569#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
3570 (h)->h_next = (val); \
3571 } while (0)
3572#endif
3573
3574#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3575#if defined(DUK_USE_HEAPPTR16)
3576#define DUK_HEAPHDR_GET_PREV(heap,h) \
3577 ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
3578#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
3579 (h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
3580 } while (0)
3581#else
3582#define DUK_HEAPHDR_GET_PREV(heap,h) ((h)->h_prev)
3583#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
3584 (h)->h_prev = (val); \
3585 } while (0)
3586#endif
3587#endif
3588
3589#if defined(DUK_USE_REFERENCE_COUNTING)
3590#if defined(DUK_USE_REFCOUNT16)
3591#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount16)
3592#define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \
3593 (h)->h_refcount16 = (val); \
3594 } while (0)
3595#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount16) /* result: updated refcount */
3596#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount16) /* result: updated refcount */
3597#else
3598#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount)
3599#define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \
3600 (h)->h_refcount = (val); \
3601 } while (0)
3602#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */
3603#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */
3604#endif
3605#else
3606/* refcount macros not defined without refcounting, caller must #ifdef now */
3607#endif /* DUK_USE_REFERENCE_COUNTING */
3608
3609/*
3610 * Note: type is treated as a field separate from flags, so some masking is
3611 * involved in the macros below.
3612 */
3613
3614#define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags)
3615
3616#define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
3617#define DUK_HEAPHDR_SET_FLAGS(h,val) do { \
3618 (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
3619 } while (0)
3620
3621#define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
3622#define DUK_HEAPHDR_SET_TYPE(h,val) do { \
3623 (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
3624 } while (0)
3625
3626#define DUK_HEAPHDR_HTYPE_VALID(h) ( \
3627 DUK_HEAPHDR_GET_TYPE((h)) >= DUK_HTYPE_MIN && \
3628 DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
3629 )
3630
3631#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval) do { \
3632 (h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
3633 ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
3634 } while (0)
3635
3636#define DUK_HEAPHDR_SET_FLAG_BITS(h,bits) do { \
3637 DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3638 (h)->h_flags |= (bits); \
3639 } while (0)
3640
3641#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits) do { \
3642 DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3643 (h)->h_flags &= ~((bits)); \
3644 } while (0)
3645
3646#define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits) (((h)->h_flags & (bits)) != 0)
3647
3648#define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3649#define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3650#define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3651
3652#define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3653#define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3654#define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3655
3656#define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3657#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3658#define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3659
3660#define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3661#define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3662#define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3663
3664#define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3665#define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3666#define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3667
3668/* get or set a range of flags; m=first bit number, n=number of bits */
3669#define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
3670
3671#define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v) do { \
3672 (h)->h_flags = \
3673 ((h)->h_flags & (~(((1 << (n)) - 1) << (m)))) \
3674 | ((v) << (m)); \
3675 } while (0)
3676
3677/* init pointer fields to null */
3678#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3679#define DUK_HEAPHDR_INIT_NULLS(h) do { \
3680 DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3681 DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
3682 } while (0)
3683#else
3684#define DUK_HEAPHDR_INIT_NULLS(h) do { \
3685 DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3686 } while (0)
3687#endif
3688
3689#define DUK_HEAPHDR_STRING_INIT_NULLS(h) /* currently nop */
3690
3691/*
3692 * Assert helpers
3693 */
3694
3695/* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
3696 * h->prev->next should point back to h.
3697 */
3698#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
3699#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
3700 if ((h) != NULL) { \
3701 duk_heaphdr *h__prev, *h__next; \
3702 h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
3703 h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
3704 DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
3705 DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
3706 } \
3707 } while (0)
3708#else
3709#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
3710#endif
3711
3712/*
3713 * Reference counting helper macros. The macros take a thread argument
3714 * and must thus always be executed in a specific thread context. The
3715 * thread argument is needed for features like finalization. Currently
3716 * it is not required for INCREF, but it is included just in case.
3717 *
3718 * Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
3719 * defined without DUK_USE_REFERENCE_COUNTING, so caller must #ifdef
3720 * around them.
3721 */
3722
3723#if defined(DUK_USE_REFERENCE_COUNTING)
3724
3725#if defined(DUK_USE_ROM_OBJECTS)
3726/* With ROM objects "needs refcount update" is true when the value is
3727 * heap allocated and is not a ROM object.
3728 */
3729/* XXX: double evaluation for 'tv' argument. */
3730#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
3731 (DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
3732#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h)))
3733#else /* DUK_USE_ROM_OBJECTS */
3734/* Without ROM objects "needs refcount update" == is heap allocated. */
3735#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv))
3736#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1
3737#endif /* DUK_USE_ROM_OBJECTS */
3738
3739/* Fast variants, inline refcount operations except for refzero handling.
3740 * Can be used explicitly when speed is always more important than size.
3741 * For a good compiler and a single file build, these are basically the
3742 * same as a forced inline.
3743 */
3744#define DUK_TVAL_INCREF_FAST(thr,tv) do { \
3745 duk_tval *duk__tv = (tv); \
3746 DUK_ASSERT(duk__tv != NULL); \
3747 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
3748 duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
3749 DUK_ASSERT(duk__h != NULL); \
3750 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3751 DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
3752 } \
3753 } while (0)
3754#define DUK_TVAL_DECREF_FAST(thr,tv) do { \
3755 duk_tval *duk__tv = (tv); \
3756 DUK_ASSERT(duk__tv != NULL); \
3757 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
3758 duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
3759 DUK_ASSERT(duk__h != NULL); \
3760 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3761 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
3762 if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
3763 duk_heaphdr_refzero((thr), duk__h); \
3764 } \
3765 } \
3766 } while (0)
3767#define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
3768 duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
3769 DUK_ASSERT(duk__h != NULL); \
3770 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3771 if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
3772 DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
3773 } \
3774 } while (0)
3775#define DUK_HEAPHDR_DECREF_FAST(thr,h) do { \
3776 duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
3777 DUK_ASSERT(duk__h != NULL); \
3778 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3779 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
3780 if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
3781 if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
3782 duk_heaphdr_refzero((thr), duk__h); \
3783 } \
3784 } \
3785 } while (0)
3786
3787/* Slow variants, call to a helper to reduce code size.
3788 * Can be used explicitly when size is always more important than speed.
3789 */
3790#define DUK_TVAL_INCREF_SLOW(thr,tv) do { \
3791 duk_tval_incref((tv)); \
3792 } while (0)
3793#define DUK_TVAL_DECREF_SLOW(thr,tv) do { \
3794 duk_tval_decref((thr), (tv)); \
3795 } while (0)
3796#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { \
3797 duk_heaphdr_incref((duk_heaphdr *) (h)); \
3798 } while (0)
3799#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { \
3800 duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
3801 } while (0)
3802
3803/* Default variants. Selection depends on speed/size preference.
3804 * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
3805 * is about +1kB for _FAST variants.
3806 */
3807#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
3808#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_FAST((thr),(tv))
3809#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_FAST((thr),(tv))
3810#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_FAST((thr),(h))
3811#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST((thr),(h))
3812#else
3813#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_SLOW((thr),(tv))
3814#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_SLOW((thr),(tv))
3815#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_SLOW((thr),(h))
3816#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_SLOW((thr),(h))
3817#endif
3818
3819/* Casting convenience. */
3820#define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3821#define DUK_HSTRING_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3822#define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3823#define DUK_HOBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3824#define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3825#define DUK_HBUFFER_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3826#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3827#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3828#define DUK_HNATIVEFUNCTION_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3829#define DUK_HNATIVEFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3830#define DUK_HBUFFEROBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3831#define DUK_HBUFFEROBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3832#define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3833#define DUK_HTHREAD_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3834
3835/* Convenience for some situations; the above macros don't allow NULLs
3836 * for performance reasons.
3837 */
3838#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
3839 if ((h) != NULL) { \
3840 DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
3841 } \
3842 } while (0)
3843#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
3844 if ((h) != NULL) { \
3845 DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
3846 } \
3847 } while (0)
3848
3849/*
3850 * Macros to set a duk_tval and update refcount of the target (decref the
3851 * old value and incref the new value if necessary). This is both performance
3852 * and footprint critical; any changes made should be measured for size/speed.
3853 */
3854
3855#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
3856 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3857 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3858 DUK_TVAL_SET_UNDEFINED(tv__dst); \
3859 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3860 } while (0)
3861
3862#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
3863 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3864 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3865 DUK_TVAL_SET_UNUSED(tv__dst); \
3866 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3867 } while (0)
3868
3869#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
3870 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3871 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3872 DUK_TVAL_SET_NULL(tv__dst); \
3873 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3874 } while (0)
3875
3876#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3877 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3878 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3879 DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
3880 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3881 } while (0)
3882
3883#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3884 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3885 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3886 DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
3887 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3888 } while (0)
3889#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3890 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3891 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3892 DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
3893 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3894 } while (0)
3895#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3896 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3897 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3898 DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
3899 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3900 } while (0)
3901#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
3902 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3903 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3904 DUK_TVAL_SET_NAN(tv__dst); \
3905 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3906 } while (0)
3907#if defined(DUK_USE_FASTINT)
3908#define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3909 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3910 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3911 DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
3912 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3913 } while (0)
3914#define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3915 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3916 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3917 DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
3918 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3919 } while (0)
3920#define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3921 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3922 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3923 DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
3924 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3925 } while (0)
3926#else
3927#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
3928 DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
3929#endif /* DUK_USE_FASTINT */
3930
3931#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
3932 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3933 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3934 DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
3935 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3936 } while (0)
3937
3938#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3939 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3940 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3941 DUK_TVAL_SET_STRING(tv__dst, (newval)); \
3942 DUK_HSTRING_INCREF((thr), (newval)); \
3943 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3944 } while (0)
3945
3946#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3947 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3948 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3949 DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
3950 DUK_HOBJECT_INCREF((thr), (newval)); \
3951 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3952 } while (0)
3953
3954#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3955 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3956 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3957 DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
3958 DUK_HBUFFER_INCREF((thr), (newval)); \
3959 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3960 } while (0)
3961
3962#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3963 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3964 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3965 DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
3966 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3967 } while (0)
3968
3969/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
3970 * etc, so it's very important for performance. Measure when changing.
3971 *
3972 * NOTE: the source and destination duk_tval pointers may be the same, and
3973 * the macros MUST deal with that correctly.
3974 */
3975
3976/* Original idiom used, minimal code size. */
3977#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
3978 duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
3979 tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
3980 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3981 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
3982 DUK_TVAL_INCREF((thr), tv__src); \
3983 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3984 } while (0)
3985
3986/* Faster alternative: avoid making a temporary copy of tvptr_dst and use
3987 * fast incref/decref macros.
3988 */
3989#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
3990 duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
3991 tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
3992 DUK_TVAL_INCREF_FAST((thr), tv__src); \
3993 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
3994 h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
3995 DUK_ASSERT(h__obj != NULL); \
3996 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
3997 DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
3998 } else { \
3999 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4000 } \
4001 } while (0)
4002
4003/* XXX: no optimized variants yet */
4004#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4005#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4006#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
4007#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4008#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4009#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4010#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4011#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
4012#if defined(DUK_USE_FASTINT)
4013#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_FASTINT_UPDREF_ALT0
4014#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
4015#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
4016#else
4017#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */
4018#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4019#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4020#endif /* DUK_USE_FASTINT */
4021#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4022#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
4023#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4024#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4025#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
4026
4027#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4028/* Optimized for speed. */
4029#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1
4030#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1
4031#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4032#else
4033/* Optimized for size. */
4034#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
4035#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
4036#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4037#endif
4038
4039#else /* DUK_USE_REFERENCE_COUNTING */
4040
4041#define DUK_TVAL_INCREF_FAST(thr,v) do {} while (0) /* nop */
4042#define DUK_TVAL_DECREF_FAST(thr,v) do {} while (0) /* nop */
4043#define DUK_TVAL_INCREF_SLOW(thr,v) do {} while (0) /* nop */
4044#define DUK_TVAL_DECREF_SLOW(thr,v) do {} while (0) /* nop */
4045#define DUK_TVAL_INCREF(thr,v) do {} while (0) /* nop */
4046#define DUK_TVAL_DECREF(thr,v) do {} while (0) /* nop */
4047#define DUK_HEAPHDR_INCREF_FAST(thr,h) do {} while (0) /* nop */
4048#define DUK_HEAPHDR_DECREF_FAST(thr,h) do {} while (0) /* nop */
4049#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do {} while (0) /* nop */
4050#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do {} while (0) /* nop */
4051#define DUK_HEAPHDR_INCREF(thr,h) do {} while (0) /* nop */
4052#define DUK_HEAPHDR_DECREF(thr,h) do {} while (0) /* nop */
4053#define DUK_HSTRING_INCREF(thr,h) do {} while (0) /* nop */
4054#define DUK_HSTRING_DECREF(thr,h) do {} while (0) /* nop */
4055#define DUK_HOBJECT_INCREF(thr,h) do {} while (0) /* nop */
4056#define DUK_HOBJECT_DECREF(thr,h) do {} while (0) /* nop */
4057#define DUK_HBUFFER_INCREF(thr,h) do {} while (0) /* nop */
4058#define DUK_HBUFFER_DECREF(thr,h) do {} while (0) /* nop */
4059#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h) do {} while (0) /* nop */
4060#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) do {} while (0) /* nop */
4061#define DUK_HNATIVEFUNCTION_INCREF(thr,h) do {} while (0) /* nop */
4062#define DUK_HNATIVEFUNCTION_DECREF(thr,h) do {} while (0) /* nop */
4063#define DUK_HBUFFEROBJECT_INCREF(thr,h) do {} while (0) /* nop */
4064#define DUK_HBUFFEROBJECT_DECREF(thr,h) do {} while (0) /* nop */
4065#define DUK_HTHREAD_INCREF(thr,h) do {} while (0) /* nop */
4066#define DUK_HTHREAD_DECREF(thr,h) do {} while (0) /* nop */
4067#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4068#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4069
4070#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4071 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4072 DUK_TVAL_SET_UNDEFINED(tv__dst); \
4073 DUK_UNREF((thr)); \
4074 } while (0)
4075
4076#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4077 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4078 DUK_TVAL_SET_UNUSED(tv__dst); \
4079 DUK_UNREF((thr)); \
4080 } while (0)
4081
4082#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4083 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4084 DUK_TVAL_SET_NULL(tv__dst); \
4085 DUK_UNREF((thr)); \
4086 } while (0)
4087
4088#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4089 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4090 DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4091 DUK_UNREF((thr)); \
4092 } while (0)
4093
4094#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4095 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4096 DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
4097 DUK_UNREF((thr)); \
4098 } while (0)
4099#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4100 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4101 DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
4102 DUK_UNREF((thr)); \
4103 } while (0)
4104#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4105 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4106 DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
4107 DUK_UNREF((thr)); \
4108 } while (0)
4109#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
4110 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4111 DUK_TVAL_SET_NAN(tv__dst); \
4112 DUK_UNREF((thr)); \
4113 } while (0)
4114#if defined(DUK_USE_FASTINT)
4115#define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4116 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4117 DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
4118 DUK_UNREF((thr)); \
4119 } while (0)
4120#define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4121 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4122 DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
4123 DUK_UNREF((thr)); \
4124 } while (0)
4125#define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4126 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4127 DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
4128 DUK_UNREF((thr)); \
4129 } while (0)
4130#else
4131#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
4132 DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
4133#endif /* DUK_USE_FASTINT */
4134
4135#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
4136 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4137 DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
4138 DUK_UNREF((thr)); \
4139 } while (0)
4140
4141#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4142 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4143 DUK_TVAL_SET_STRING(tv__dst, (newval)); \
4144 DUK_UNREF((thr)); \
4145 } while (0)
4146
4147#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4148 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4149 DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
4150 DUK_UNREF((thr)); \
4151 } while (0)
4152
4153#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4154 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4155 DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
4156 DUK_UNREF((thr)); \
4157 } while (0)
4158
4159#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4160 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4161 DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
4162 DUK_UNREF((thr)); \
4163 } while (0)
4164
4165#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
4166 duk_tval *tv__dst, *tv__src; \
4167 tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
4168 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4169 DUK_UNREF((thr)); \
4170 } while (0)
4171
4172#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4173#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4174#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
4175#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4176#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4177#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4178#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4179#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
4180#if defined(DUK_USE_FASTINT)
4181#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_FASTINT_UPDREF_ALT0
4182#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
4183#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
4184#else
4185#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */
4186#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4187#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4188#endif /* DUK_USE_FASTINT */
4189#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4190#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
4191#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4192#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4193#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
4194
4195#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
4196#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
4197#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4198
4199#endif /* DUK_USE_REFERENCE_COUNTING */
4200
4201#endif /* DUK_HEAPHDR_H_INCLUDED */
4202/*
4203 * Internal API calls which have (stack and other) semantics similar
4204 * to the public API.
4205 */
4206
4207#ifndef DUK_API_INTERNAL_H_INCLUDED
4208#define DUK_API_INTERNAL_H_INCLUDED
4209
4210/* duk_push_sprintf constants */
4211#define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L
4212#define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L)
4213
4214/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
4215 * blamed as source of error for error fileName / lineNumber.
4216 */
4217#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24)
4218
4219/* Valstack resize flags */
4220#define DUK_VSRESIZE_FLAG_SHRINK (1 << 0)
4221#define DUK_VSRESIZE_FLAG_COMPACT (1 << 1)
4222#define DUK_VSRESIZE_FLAG_THROW (1 << 2)
4223
4224/* Current convention is to use duk_size_t for value stack sizes and global indices,
4225 * and duk_idx_t for local frame indices.
4226 */
4229 duk_size_t min_new_size,
4230 duk_small_uint_t flags);
4231
4232#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
4233DUK_INTERNAL_DECL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index);
4234#endif
4235
4239
4240/* Push the current 'this' binding; throw TypeError if binding is not object
4241 * coercible (CheckObjectCoercible).
4242 */
4244
4245/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
4247
4248/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
4250
4251/* Get a borrowed duk_tval pointer to the current 'this' binding. Caller must
4252 * make sure there's an active callstack entry. Note that the returned pointer
4253 * is unstable with regards to side effects.
4254 */
4256
4257/* XXX: add fastint support? */
4258#define duk_push_u64(ctx,val) \
4259 duk_push_number((ctx), (duk_double_t) (val))
4260#define duk_push_i64(ctx,val) \
4261 duk_push_number((ctx), (duk_double_t) (val))
4262
4263/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
4264#define duk_push_u32(ctx,val) \
4265 duk_push_uint((ctx), (duk_uint_t) (val))
4266#define duk_push_i32(ctx,val) \
4267 duk_push_int((ctx), (duk_int_t) (val))
4268
4269/* sometimes stack and array indices need to go on the stack */
4270#define duk_push_idx(ctx,val) \
4271 duk_push_int((ctx), (duk_int_t) (val))
4272#define duk_push_uarridx(ctx,val) \
4273 duk_push_uint((ctx), (duk_uint_t) (val))
4274#define duk_push_size_t(ctx,val) \
4275 duk_push_uint((ctx), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
4276
4283
4285
4286#if 0 /* This would be pointless: unexpected type and lightfunc would both return NULL */
4287DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
4288#endif
4290
4291#if 0 /*unused*/
4292DUK_INTERNAL_DECL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index);
4293#endif
4294
4296#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
4297DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index);
4298#endif
4300#if !defined(DUK_USE_PARANOID_ERRORS)
4302#endif
4303
4304DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */
4307#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
4309#endif
4310
4317
4319
4322
4327#define duk_push_hthread(ctx,h) \
4328 duk_push_hobject((ctx), (duk_hobject *) (h))
4329#define duk_push_hcompiledfunction(ctx,h) \
4330 duk_push_hobject((ctx), (duk_hobject *) (h))
4331#define duk_push_hnativefunction(ctx,h) \
4332 duk_push_hobject((ctx), (duk_hobject *) (h))
4334DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
4340
4341DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz);
4345
4346#if !defined(DUK_USE_PARANOID_ERRORS)
4349#endif
4350
4351DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [val] */
4352DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [val] -> [] */
4355
4356DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop); /* [] -> [] */
4357
4358DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags); /* [key val] -> [] */
4359DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags); /* [val] -> [] */
4360DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags); /* [val] -> [] */
4361DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags); /* [] -> [] */
4362DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags); /* [] -> [] */
4363
4364/* These are macros for now, but could be separate functions to reduce code
4365 * footprint (check call site count before refactoring).
4366 */
4367#define duk_xdef_prop_wec(ctx,obj_index) \
4368 duk_xdef_prop((ctx), (obj_index), DUK_PROPDESC_FLAGS_WEC)
4369#define duk_xdef_prop_index_wec(ctx,obj_index,arr_index) \
4370 duk_xdef_prop_index((ctx), (obj_index), (arr_index), DUK_PROPDESC_FLAGS_WEC)
4371#define duk_xdef_prop_stridx_wec(ctx,obj_index,stridx) \
4372 duk_xdef_prop_stridx((ctx), (obj_index), (stridx), DUK_PROPDESC_FLAGS_WEC)
4373
4374/* Set object 'length'. */
4376
4377/* Raw internal valstack access macros: access is unsafe so call site
4378 * must have a guarantee that the index is valid. When that is the case,
4379 * using these macro results in faster and smaller code than duk_get_tval().
4380 * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
4381 */
4382#define DUK_ASSERT_VALID_NEGIDX(ctx,idx) \
4383 (DUK_ASSERT_EXPR((idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4384#define DUK_ASSERT_VALID_POSIDX(ctx,idx) \
4385 (DUK_ASSERT_EXPR((idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4386#define DUK_GET_TVAL_NEGIDX(ctx,idx) \
4387 (DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_top + (idx))
4388#define DUK_GET_TVAL_POSIDX(ctx,idx) \
4389 (DUK_ASSERT_VALID_POSIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_bottom + (idx))
4390#define DUK_GET_HOBJECT_NEGIDX(ctx,idx) \
4391 (DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_top + (idx)))
4392#define DUK_GET_HOBJECT_POSIDX(ctx,idx) \
4393 (DUK_ASSERT_VALID_POSIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_bottom + (idx)))
4394
4395#endif /* DUK_API_INTERNAL_H_INCLUDED */
4396/*
4397 * Heap string representation.
4398 *
4399 * Strings are byte sequences ordinarily stored in extended UTF-8 format,
4400 * allowing values larger than the official UTF-8 range (used internally)
4401 * and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
4402 * Strings may also be invalid UTF-8 altogether which is the case e.g. with
4403 * strings used as internal property names and raw buffers converted to
4404 * strings. In such cases the 'clen' field contains an inaccurate value.
4405 *
4406 * Ecmascript requires support for 32-bit long strings. However, since each
4407 * 16-bit codepoint can take 3 bytes in CESU-8, this representation can only
4408 * support about 1.4G codepoint long strings in extreme cases. This is not
4409 * really a practical issue.
4410 */
4411
4412#ifndef DUK_HSTRING_H_INCLUDED
4413#define DUK_HSTRING_H_INCLUDED
4414
4415/* Impose a maximum string length for now. Restricted artificially to
4416 * ensure adding a heap header length won't overflow size_t. The limit
4417 * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
4418 *
4419 * E5.1 makes provisions to support strings longer than 4G characters.
4420 * This limit should be eliminated on 64-bit platforms (and increased
4421 * closer to maximum support on 32-bit platforms).
4422 */
4423
4424#if defined(DUK_USE_STRLEN16)
4425#define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL)
4426#else
4427#define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL)
4428#endif
4429
4430/* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings),
4431 * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
4432 * regexp bytecode is), and "contains non-BMP characters". These are not
4433 * needed right now.
4434 */
4435
4436#define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */
4437#define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */
4438#define DUK_HSTRING_FLAG_INTERNAL DUK_HEAPHDR_USER_FLAG(2) /* string is internal */
4439#define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(3) /* string is a reserved word (non-strict) */
4440#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(4) /* string is a reserved word (strict) */
4441#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(5) /* string is 'eval' or 'arguments' */
4442#define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(6) /* string data is external (duk_hstring_external) */
4443
4444#define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4445#define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4446#define DUK_HSTRING_HAS_INTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4447#define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4448#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4449#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4450#define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4451
4452#define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4453#define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4454#define DUK_HSTRING_SET_INTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4455#define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4456#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4457#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4458#define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4459
4460#define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4461#define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4462#define DUK_HSTRING_CLEAR_INTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4463#define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4464#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4465#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4466#define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4467
4468#if 0 /* Slightly smaller code without explicit flag, but explicit flag
4469 * is very useful when 'clen' is dropped.
4470 */
4471#define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
4472#endif
4473#define DUK_HSTRING_IS_ASCII(x) DUK_HSTRING_HAS_ASCII((x))
4474#define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
4475
4476#if defined(DUK_USE_STRHASH16)
4477#define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16)
4478#define DUK_HSTRING_SET_HASH(x,v) do { \
4479 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
4480 } while (0)
4481#else
4482#define DUK_HSTRING_GET_HASH(x) ((x)->hash)
4483#define DUK_HSTRING_SET_HASH(x,v) do { \
4484 (x)->hash = (v); \
4485 } while (0)
4486#endif
4487
4488#if defined(DUK_USE_STRLEN16)
4489#define DUK_HSTRING_GET_BYTELEN(x) ((x)->hdr.h_strextra16)
4490#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
4491 (x)->hdr.h_strextra16 = (v); \
4492 } while (0)
4493#if defined(DUK_USE_HSTRING_CLEN)
4494#define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen16)
4495#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4496 (x)->clen16 = (v); \
4497 } while (0)
4498#else
4499#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
4500#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4501 DUK_ASSERT(0); /* should never be called */ \
4502 } while (0)
4503#endif
4504#else
4505#define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen)
4506#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
4507 (x)->blen = (v); \
4508 } while (0)
4509#define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen)
4510#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4511 (x)->clen = (v); \
4512 } while (0)
4513#endif
4514
4515#if defined(DUK_USE_HSTRING_EXTDATA)
4516#define DUK_HSTRING_GET_EXTDATA(x) \
4517 ((x)->extdata)
4518#define DUK_HSTRING_GET_DATA(x) \
4519 (DUK_HSTRING_HAS_EXTDATA((x)) ? \
4520 DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
4521#else
4522#define DUK_HSTRING_GET_DATA(x) \
4523 ((const duk_uint8_t *) ((x) + 1))
4524#endif
4525
4526#define DUK_HSTRING_GET_DATA_END(x) \
4527 (DUK_HSTRING_GET_DATA((x)) + (x)->blen)
4528
4529/* marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest valid) */
4530#define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
4531
4532/* get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
4533 * avoids helper call if string has no array index value.
4534 */
4535#define DUK_HSTRING_GET_ARRIDX_FAST(h) \
4536 (DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_string_helper((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
4537
4538/* slower but more compact variant */
4539#define DUK_HSTRING_GET_ARRIDX_SLOW(h) \
4540 (duk_js_to_arrayindex_string_helper((h)))
4541
4542/*
4543 * Misc
4544 */
4545
4547 /* Smaller heaphdr than for other objects, because strings are held
4548 * in string intern table which requires no link pointers. Much of
4549 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
4550 * field in there.
4551 */
4553
4554 /* Note: we could try to stuff a partial hash (e.g. 16 bits) into the
4555 * shared heap header. Good hashing needs more hash bits though.
4556 */
4557
4558 /* string hash */
4559#if defined(DUK_USE_STRHASH16)
4560 /* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
4561#else
4562 duk_uint32_t hash;
4563#endif
4564
4565 /* length in bytes (not counting NUL term) */
4566#if defined(DUK_USE_STRLEN16)
4567 /* placed in duk_heaphdr_string */
4568#else
4569 duk_uint32_t blen;
4570#endif
4571
4572 /* length in codepoints (must be E5 compatible) */
4573#if defined(DUK_USE_STRLEN16)
4574#if defined(DUK_USE_HSTRING_CLEN)
4575 duk_uint16_t clen16;
4576#else
4577 /* computed live */
4578#endif
4579#else
4580 duk_uint32_t clen;
4581#endif
4582
4583 /*
4584 * String value of 'blen+1' bytes follows (+1 for NUL termination
4585 * convenience for C API). No alignment needs to be guaranteed
4586 * for strings, but fields above should guarantee alignment-by-4
4587 * (but not alignment-by-8).
4588 */
4589};
4590
4591/* The external string struct is defined even when the feature is inactive. */
4594
4595 /*
4596 * For an external string, the NUL-terminated string data is stored
4597 * externally. The user must guarantee that data behind this pointer
4598 * doesn't change while it's used.
4599 */
4600
4601 const duk_uint8_t *extdata;
4602};
4603
4604/*
4605 * Prototypes
4606 */
4607
4609
4610#if !defined(DUK_USE_HSTRING_CLEN)
4612#endif
4613
4614#endif /* DUK_HSTRING_H_INCLUDED */
4615/*
4616 * Heap object representation.
4617 *
4618 * Heap objects are used for Ecmascript objects, arrays, and functions,
4619 * but also for internal control like declarative and object environment
4620 * records. Compiled functions, native functions, and threads are also
4621 * objects but with an extended C struct.
4622 *
4623 * Objects provide the required Ecmascript semantics and exotic behaviors
4624 * especially for property access.
4625 *
4626 * Properties are stored in three conceptual parts:
4627 *
4628 * 1. A linear 'entry part' contains ordered key-value-attributes triples
4629 * and is the main method of string properties.
4630 *
4631 * 2. An optional linear 'array part' is used for array objects to store a
4632 * (dense) range of [0,N[ array indexed entries with default attributes
4633 * (writable, enumerable, configurable). If the array part would become
4634 * sparse or non-default attributes are required, the array part is
4635 * abandoned and moved to the 'entry part'.
4636 *
4637 * 3. An optional 'hash part' is used to optimize lookups of the entry
4638 * part; it is used only for objects with sufficiently many properties
4639 * and can be abandoned without loss of information.
4640 *
4641 * These three conceptual parts are stored in a single memory allocated area.
4642 * This minimizes memory allocation overhead but also means that all three
4643 * parts are resized together, and makes property access a bit complicated.
4644 */
4645
4646#ifndef DUK_HOBJECT_H_INCLUDED
4647#define DUK_HOBJECT_H_INCLUDED
4648
4649/* Object flag. There are currently 26 flag bits available. Make sure
4650 * this stays in sync with debugger object inspection code.
4651 */
4652#define DUK_HOBJECT_FLAG_EXTENSIBLE DUK_HEAPHDR_USER_FLAG(0) /* object is extensible */
4653#define DUK_HOBJECT_FLAG_CONSTRUCTABLE DUK_HEAPHDR_USER_FLAG(1) /* object is constructable */
4654#define DUK_HOBJECT_FLAG_BOUND DUK_HEAPHDR_USER_FLAG(2) /* object established using Function.prototype.bind() */
4655#define DUK_HOBJECT_FLAG_COMPILEDFUNCTION DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompiledfunction) */
4656#define DUK_HOBJECT_FLAG_NATIVEFUNCTION DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnativefunction) */
4657#define DUK_HOBJECT_FLAG_BUFFEROBJECT DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufferobject) (always exotic) */
4658#define DUK_HOBJECT_FLAG_THREAD DUK_HEAPHDR_USER_FLAG(7) /* object is a thread (duk_hthread) */
4659#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */
4660#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */
4661#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tail called */
4662#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompiledfunction) */
4663#define DUK_HOBJECT_FLAG_NAMEBINDING DUK_HEAPHDR_USER_FLAG(12) /* function: create binding for func name (function templates only, used for named function expressions) */
4664#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */
4665#define DUK_HOBJECT_FLAG_ENVRECCLOSED DUK_HEAPHDR_USER_FLAG(14) /* envrec: (declarative) record is closed */
4666#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */
4667#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */
4668#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
4669#define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC DUK_HEAPHDR_USER_FLAG(18) /* Duktape/C (nativefunction) object, exotic 'length' */
4670#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(19) /* 'Proxy' object */
4671
4672#define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(20)
4673#define DUK_HOBJECT_FLAG_CLASS_BITS 5
4674
4675#define DUK_HOBJECT_GET_CLASS_NUMBER(h) \
4676 DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
4677#define DUK_HOBJECT_SET_CLASS_NUMBER(h,v) \
4678 DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
4679
4680#define DUK_HOBJECT_GET_CLASS_MASK(h) \
4681 (1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
4682
4683/* Macro for creating flag initializer from a class number.
4684 * Unsigned type cast is needed to avoid warnings about coercing
4685 * a signed integer to an unsigned one; the largest class values
4686 * have the highest bit (bit 31) set which causes this.
4687 */
4688#define DUK_HOBJECT_CLASS_AS_FLAGS(v) (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
4689
4690/* E5 Section 8.6.2 + custom classes */
4691#define DUK_HOBJECT_CLASS_UNUSED 0
4692#define DUK_HOBJECT_CLASS_ARGUMENTS 1
4693#define DUK_HOBJECT_CLASS_ARRAY 2
4694#define DUK_HOBJECT_CLASS_BOOLEAN 3
4695#define DUK_HOBJECT_CLASS_DATE 4
4696#define DUK_HOBJECT_CLASS_ERROR 5
4697#define DUK_HOBJECT_CLASS_FUNCTION 6
4698#define DUK_HOBJECT_CLASS_JSON 7
4699#define DUK_HOBJECT_CLASS_MATH 8
4700#define DUK_HOBJECT_CLASS_NUMBER 9
4701#define DUK_HOBJECT_CLASS_OBJECT 10
4702#define DUK_HOBJECT_CLASS_REGEXP 11
4703#define DUK_HOBJECT_CLASS_STRING 12
4704#define DUK_HOBJECT_CLASS_GLOBAL 13
4705#define DUK_HOBJECT_CLASS_OBJENV 14 /* custom */
4706#define DUK_HOBJECT_CLASS_DECENV 15 /* custom */
4707#define DUK_HOBJECT_CLASS_BUFFER 16 /* custom; implies DUK_HOBJECT_IS_BUFFEROBJECT */
4708#define DUK_HOBJECT_CLASS_POINTER 17 /* custom */
4709#define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */
4710#define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFFEROBJECT */
4711#define DUK_HOBJECT_CLASS_DATAVIEW 20
4712#define DUK_HOBJECT_CLASS_INT8ARRAY 21
4713#define DUK_HOBJECT_CLASS_UINT8ARRAY 22
4714#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23
4715#define DUK_HOBJECT_CLASS_INT16ARRAY 24
4716#define DUK_HOBJECT_CLASS_UINT16ARRAY 25
4717#define DUK_HOBJECT_CLASS_INT32ARRAY 26
4718#define DUK_HOBJECT_CLASS_UINT32ARRAY 27
4719#define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28
4720#define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29
4721#define DUK_HOBJECT_CLASS_MAX 29
4722
4723/* class masks */
4724#define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
4725#define DUK_HOBJECT_CMASK_UNUSED (1UL << DUK_HOBJECT_CLASS_UNUSED)
4726#define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
4727#define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY)
4728#define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
4729#define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE)
4730#define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR)
4731#define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION)
4732#define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON)
4733#define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH)
4734#define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER)
4735#define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT)
4736#define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP)
4737#define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING)
4738#define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL)
4739#define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV)
4740#define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV)
4741#define DUK_HOBJECT_CMASK_BUFFER (1UL << DUK_HOBJECT_CLASS_BUFFER)
4742#define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER)
4743#define DUK_HOBJECT_CMASK_THREAD (1UL << DUK_HOBJECT_CLASS_THREAD)
4744#define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
4745#define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
4746#define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
4747#define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
4748#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
4749#define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
4750#define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
4751#define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
4752#define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
4753#define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
4754#define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
4755
4756#define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS \
4757 (DUK_HOBJECT_CMASK_BUFFER | \
4758 DUK_HOBJECT_CMASK_ARRAYBUFFER | \
4759 DUK_HOBJECT_CMASK_DATAVIEW | \
4760 DUK_HOBJECT_CMASK_INT8ARRAY | \
4761 DUK_HOBJECT_CMASK_UINT8ARRAY | \
4762 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
4763 DUK_HOBJECT_CMASK_INT16ARRAY | \
4764 DUK_HOBJECT_CMASK_UINT16ARRAY | \
4765 DUK_HOBJECT_CMASK_INT32ARRAY | \
4766 DUK_HOBJECT_CMASK_UINT32ARRAY | \
4767 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
4768 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
4769
4770#define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
4771#define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
4772#define DUK_HOBJECT_IS_ENV(h) (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
4773#define DUK_HOBJECT_IS_ARRAY(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY)
4774#define DUK_HOBJECT_IS_COMPILEDFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4775#define DUK_HOBJECT_IS_NATIVEFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4776#define DUK_HOBJECT_IS_BUFFEROBJECT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4777#define DUK_HOBJECT_IS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4778
4779#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4780 DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4781 DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4782
4783#define DUK_HOBJECT_IS_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4784 DUK_HOBJECT_FLAG_BOUND | \
4785 DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4786 DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4787
4788#define DUK_HOBJECT_IS_CALLABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4789 DUK_HOBJECT_FLAG_BOUND | \
4790 DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4791 DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4792
4793/* object has any exotic behavior(s) */
4794#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
4795 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
4796 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
4797 DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \
4798 DUK_HOBJECT_FLAG_BUFFEROBJECT | \
4799 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4800
4801#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
4802
4803#define DUK_HOBJECT_HAS_EXTENSIBLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4804#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4805#define DUK_HOBJECT_HAS_BOUND(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4806#define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4807#define DUK_HOBJECT_HAS_NATIVEFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4808#define DUK_HOBJECT_HAS_BUFFEROBJECT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4809#define DUK_HOBJECT_HAS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4810#define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4811#define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4812#define DUK_HOBJECT_HAS_NOTAIL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4813#define DUK_HOBJECT_HAS_NEWENV(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4814#define DUK_HOBJECT_HAS_NAMEBINDING(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4815#define DUK_HOBJECT_HAS_CREATEARGS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4816#define DUK_HOBJECT_HAS_ENVRECCLOSED(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4817#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4818#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4819#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4820#define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4821#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4822
4823#define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4824#define DUK_HOBJECT_SET_CONSTRUCTABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4825#define DUK_HOBJECT_SET_BOUND(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4826#define DUK_HOBJECT_SET_COMPILEDFUNCTION(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4827#define DUK_HOBJECT_SET_NATIVEFUNCTION(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4828#define DUK_HOBJECT_SET_BUFFEROBJECT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4829#define DUK_HOBJECT_SET_THREAD(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4830#define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4831#define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4832#define DUK_HOBJECT_SET_NOTAIL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4833#define DUK_HOBJECT_SET_NEWENV(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4834#define DUK_HOBJECT_SET_NAMEBINDING(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4835#define DUK_HOBJECT_SET_CREATEARGS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4836#define DUK_HOBJECT_SET_ENVRECCLOSED(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4837#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4838#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4839#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4840#define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4841#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4842
4843#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4844#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4845#define DUK_HOBJECT_CLEAR_BOUND(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4846#define DUK_HOBJECT_CLEAR_COMPILEDFUNCTION(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4847#define DUK_HOBJECT_CLEAR_NATIVEFUNCTION(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4848#define DUK_HOBJECT_CLEAR_BUFFEROBJECT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4849#define DUK_HOBJECT_CLEAR_THREAD(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4850#define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4851#define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4852#define DUK_HOBJECT_CLEAR_NOTAIL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4853#define DUK_HOBJECT_CLEAR_NEWENV(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4854#define DUK_HOBJECT_CLEAR_NAMEBINDING(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4855#define DUK_HOBJECT_CLEAR_CREATEARGS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4856#define DUK_HOBJECT_CLEAR_ENVRECCLOSED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4857#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4858#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4859#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4860#define DUK_HOBJECT_CLEAR_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4861#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4862
4863/* flags used for property attributes in duk_propdesc and packed flags */
4864#define DUK_PROPDESC_FLAG_WRITABLE (1 << 0) /* E5 Section 8.6.1 */
4865#define DUK_PROPDESC_FLAG_ENUMERABLE (1 << 1) /* E5 Section 8.6.1 */
4866#define DUK_PROPDESC_FLAG_CONFIGURABLE (1 << 2) /* E5 Section 8.6.1 */
4867#define DUK_PROPDESC_FLAG_ACCESSOR (1 << 3) /* accessor */
4868#define DUK_PROPDESC_FLAG_VIRTUAL (1 << 4) /* property is virtual: used in duk_propdesc, never stored
4869 * (used by e.g. buffer virtual properties)
4870 */
4871#define DUK_PROPDESC_FLAGS_MASK (DUK_PROPDESC_FLAG_WRITABLE | \
4872 DUK_PROPDESC_FLAG_ENUMERABLE | \
4873 DUK_PROPDESC_FLAG_CONFIGURABLE | \
4874 DUK_PROPDESC_FLAG_ACCESSOR)
4875
4876/* additional flags which are passed in the same flags argument as property
4877 * flags but are not stored in object properties.
4878 */
4879#define DUK_PROPDESC_FLAG_NO_OVERWRITE (1 << 4) /* internal define property: skip write silently if exists */
4881/* convenience */
4882#define DUK_PROPDESC_FLAGS_NONE 0
4883#define DUK_PROPDESC_FLAGS_W (DUK_PROPDESC_FLAG_WRITABLE)
4884#define DUK_PROPDESC_FLAGS_E (DUK_PROPDESC_FLAG_ENUMERABLE)
4885#define DUK_PROPDESC_FLAGS_C (DUK_PROPDESC_FLAG_CONFIGURABLE)
4886#define DUK_PROPDESC_FLAGS_WE (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
4887#define DUK_PROPDESC_FLAGS_WC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
4888#define DUK_PROPDESC_FLAGS_EC (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
4889#define DUK_PROPDESC_FLAGS_WEC (DUK_PROPDESC_FLAG_WRITABLE | \
4890 DUK_PROPDESC_FLAG_ENUMERABLE | \
4891 DUK_PROPDESC_FLAG_CONFIGURABLE)
4893/* flags for duk_hobject_get_own_propdesc() and variants */
4894#define DUK_GETDESC_FLAG_PUSH_VALUE (1 << 0) /* push value to stack */
4895#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP (1 << 1) /* don't throw for prototype loop */
4896
4897/*
4898 * Macro for object validity check
4899 *
4900 * Assert for currently guaranteed relations between flags, for instance.
4902
4903#define DUK_ASSERT_HOBJECT_VALID(h) do { \
4904 DUK_ASSERT((h) != NULL); \
4905 DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
4906 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
4907 DUK_ASSERT(!DUK_HOBJECT_IS_BUFFEROBJECT((h)) || \
4908 (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_BUFFER || \
4909 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
4910 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
4911 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
4912 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
4913 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
4914 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
4915 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
4916 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
4917 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
4918 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
4919 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
4920 } while (0)
4921
4922/*
4923 * Macros to access the 'props' allocation.
4924 */
4925
4926#if defined(DUK_USE_HEAPPTR16)
4927#define DUK_HOBJECT_GET_PROPS(heap,h) \
4928 ((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
4929#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
4930 ((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
4931 } while (0)
4932#else
4933#define DUK_HOBJECT_GET_PROPS(heap,h) \
4934 ((h)->props)
4935#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
4936 (h)->props = (duk_uint8_t *) (x); \
4937 } while (0)
4938#endif
4939
4940#if defined(DUK_USE_HOBJECT_LAYOUT_1)
4941/* LAYOUT 1 */
4942#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
4943 ((duk_hstring **) (void *) ( \
4944 DUK_HOBJECT_GET_PROPS((heap), (h)) \
4945 ))
4946#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
4947 ((duk_propvalue *) (void *) ( \
4948 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4949 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
4950 ))
4951#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
4952 ((duk_uint8_t *) (void *) ( \
4953 DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
4954 ))
4955#define DUK_HOBJECT_A_GET_BASE(heap,h) \
4956 ((duk_tval *) (void *) ( \
4957 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4958 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
4959 ))
4960#define DUK_HOBJECT_H_GET_BASE(heap,h) \
4961 ((duk_uint32_t *) (void *) ( \
4962 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4963 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
4964 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
4965 ))
4966#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
4967 ( \
4968 (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
4969 (n_arr) * sizeof(duk_tval) + \
4970 (n_hash) * sizeof(duk_uint32_t) \
4971 )
4972#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) do { \
4973 (set_e_k) = (duk_hstring **) (void *) (p_base); \
4974 (set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
4975 (set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
4976 (set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
4977 (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
4978 } while (0)
4979#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
4980/* LAYOUT 2 */
4981#if (DUK_USE_ALIGN_BY == 4)
4982#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
4983#elif (DUK_USE_ALIGN_BY == 8)
4984#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
4985#elif (DUK_USE_ALIGN_BY == 1)
4986#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
4987#else
4988#error invalid DUK_USE_ALIGN_BY
4989#endif
4990#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
4991 ((duk_hstring **) (void *) ( \
4992 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4993 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
4994 ))
4995#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
4996 ((duk_propvalue *) (void *) ( \
4997 DUK_HOBJECT_GET_PROPS((heap), (h)) \
4998 ))
4999#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5000 ((duk_uint8_t *) (void *) ( \
5001 DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
5002 ))
5003#define DUK_HOBJECT_A_GET_BASE(heap,h) \
5004 ((duk_tval *) (void *) ( \
5005 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5006 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5007 DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
5008 ))
5009#define DUK_HOBJECT_H_GET_BASE(heap,h) \
5010 ((duk_uint32_t *) (void *) ( \
5011 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5012 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5013 DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
5014 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5015 ))
5016#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5017 ( \
5018 (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5019 DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
5020 (n_arr) * sizeof(duk_tval) + \
5021 (n_hash) * sizeof(duk_uint32_t) \
5022 )
5023#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) do { \
5024 (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5025 (set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
5026 (set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
5027 (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
5028 sizeof(duk_uint8_t) * (n_ent) + \
5029 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
5030 (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
5031 } while (0)
5032#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
5033/* LAYOUT 3 */
5034#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
5035 ((duk_hstring **) (void *) ( \
5036 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5037 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
5038 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5039 ))
5040#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5041 ((duk_propvalue *) (void *) ( \
5042 DUK_HOBJECT_GET_PROPS((heap), (h)) \
5043 ))
5044#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5045 ((duk_uint8_t *) (void *) ( \
5046 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5047 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5048 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
5049 DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
5050 ))
5051#define DUK_HOBJECT_A_GET_BASE(heap,h) \
5052 ((duk_tval *) (void *) ( \
5053 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5054 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
5055 ))
5056#define DUK_HOBJECT_H_GET_BASE(heap,h) \
5057 ((duk_uint32_t *) (void *) ( \
5058 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5059 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5060 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5061 ))
5062#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5063 ( \
5064 (n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
5065 (n_arr) * sizeof(duk_tval) + \
5066 (n_hash) * sizeof(duk_uint32_t) \
5067 )
5068#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) do { \
5069 (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5070 (set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
5071 (set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
5072 (set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
5073 (set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
5074 } while (0)
5075#else
5076#error invalid hobject layout defines
5077#endif /* hobject property layout */
5078
5079#define DUK_HOBJECT_P_ALLOC_SIZE(h) \
5080 DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
5082#define DUK_HOBJECT_E_GET_KEY(heap,h,i) (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5083#define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5084#define DUK_HOBJECT_E_GET_VALUE(heap,h,i) (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5085#define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5086#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5087#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5088#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5089#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5090#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5091#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5092#define DUK_HOBJECT_E_GET_FLAGS(heap,h,i) (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5093#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5094#define DUK_HOBJECT_A_GET_VALUE(heap,h,i) (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5095#define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5096#define DUK_HOBJECT_H_GET_INDEX(heap,h,i) (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5097#define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i) (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5098
5099#define DUK_HOBJECT_E_SET_KEY(heap,h,i,k) do { \
5100 DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
5101 } while (0)
5102#define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v) do { \
5103 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
5104 } while (0)
5105#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v) do { \
5106 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
5107 } while (0)
5108#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v) do { \
5109 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
5110 } while (0)
5111#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v) do { \
5112 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
5113 } while (0)
5114#define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f) do { \
5115 DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
5116 } while (0)
5117#define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v) do { \
5118 DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
5119 } while (0)
5120#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
5121 DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v)) /* alias for above */
5122#define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v) do { \
5123 DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
5124 } while (0)
5125
5126#define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask) do { \
5127 DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
5128 } while (0)
5129
5130#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask) do { \
5131 DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
5132 } while (0)
5134#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5135#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5136#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5137#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5139#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5140#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5141#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5142#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5144#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5145#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5146#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5147#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5149#define DUK_PROPDESC_IS_WRITABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5150#define DUK_PROPDESC_IS_ENUMERABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5151#define DUK_PROPDESC_IS_CONFIGURABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5152#define DUK_PROPDESC_IS_ACCESSOR(p) (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5154#define DUK_HOBJECT_HASHIDX_UNUSED 0xffffffffUL
5155#define DUK_HOBJECT_HASHIDX_DELETED 0xfffffffeUL
5156
5157/*
5158 * Macros for accessing size fields
5159 */
5160
5161#if defined(DUK_USE_OBJSIZES16)
5162#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
5163#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
5164#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
5165#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
5166#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
5167#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
5168#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
5169#if defined(DUK_USE_HOBJECT_HASH_PART)
5170#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
5171#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
5172#else
5173#define DUK_HOBJECT_GET_HSIZE(h) 0
5174#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5175#endif
5176#else
5177#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
5178#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
5179#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
5180#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
5181#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
5182#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
5183#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
5184#if defined(DUK_USE_HOBJECT_HASH_PART)
5185#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
5186#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
5187#else
5188#define DUK_HOBJECT_GET_HSIZE(h) 0
5189#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5190#endif
5191#endif
5192
5193/*
5194 * Misc
5195 */
5196
5197/* Maximum prototype traversal depth. Sanity limit which handles e.g.
5198 * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
5199 */
5200#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L
5202/* Maximum traversal depth for "bound function" chains. */
5203#define DUK_HOBJECT_BOUND_CHAIN_SANITY 10000L
5204
5205/*
5206 * Ecmascript [[Class]]
5207 */
5209/* range check not necessary because all 4-bit values are mapped */
5210#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n) duk_class_number_to_stridx[(n)]
5211
5212#define DUK_HOBJECT_GET_CLASS_STRING(heap,h) \
5213 DUK_HEAP_GET_STRING( \
5214 (heap), \
5215 DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
5216 )
5217
5218/*
5219 * Macros for property handling
5220 */
5221
5222#if defined(DUK_USE_HEAPPTR16)
5223#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5224 ((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
5225#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5226 (h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
5227 } while (0)
5228#else
5229#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5230 ((h)->prototype)
5231#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5232 (h)->prototype = (x); \
5233 } while (0)
5234#endif
5236/* note: this updates refcounts */
5237#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p) duk_hobject_set_prototype_updref((thr), (h), (p))
5238
5239/*
5240 * Resizing and hash behavior
5241 */
5242
5243/* Sanity limit on max number of properties (allocated, not necessarily used).
5244 * This is somewhat arbitrary, but if we're close to 2**32 properties some
5245 * algorithms will fail (e.g. hash size selection, next prime selection).
5246 * Also, we use negative array/entry table indices to indicate 'not found',
5247 * so anything above 0x80000000 will cause trouble now.
5248 */
5249#if defined(DUK_USE_OBJSIZES16)
5250#define DUK_HOBJECT_MAX_PROPERTIES 0x0000ffffUL
5251#else
5252#define DUK_HOBJECT_MAX_PROPERTIES 0x7fffffffUL /* 2**31-1 ~= 2G properties */
5253#endif
5255/* higher value conserves memory; also note that linear scan is cache friendly */
5256#define DUK_HOBJECT_E_USE_HASH_LIMIT 32
5258/* hash size relative to entries size: for value X, approx. hash_prime(e_size + e_size / X) */
5259#define DUK_HOBJECT_H_SIZE_DIVISOR 4 /* hash size approx. 1.25 times entries size */
5261/* if new_size < L * old_size, resize without abandon check; L = 3-bit fixed point, e.g. 9 -> 9/8 = 112.5% */
5262#define DUK_HOBJECT_A_FAST_RESIZE_LIMIT 9 /* 112.5%, i.e. new size less than 12.5% higher -> fast resize */
5263
5264/* if density < L, abandon array part, L = 3-bit fixed point, e.g. 2 -> 2/8 = 25% */
5265/* limit is quite low: one array entry is 8 bytes, one normal entry is 4+1+8+4 = 17 bytes (with hash entry) */
5266#define DUK_HOBJECT_A_ABANDON_LIMIT 2 /* 25%, i.e. less than 25% used -> abandon */
5267
5268/* internal align target for props allocation, must be 2*n for some n */
5269#if (DUK_USE_ALIGN_BY == 4)
5270#define DUK_HOBJECT_ALIGN_TARGET 4
5271#elif (DUK_USE_ALIGN_BY == 8)
5272#define DUK_HOBJECT_ALIGN_TARGET 8
5273#elif (DUK_USE_ALIGN_BY == 1)
5274#define DUK_HOBJECT_ALIGN_TARGET 1
5275#else
5276#error invalid DUK_USE_ALIGN_BY
5277#endif
5279/* controls for minimum entry part growth */
5280#define DUK_HOBJECT_E_MIN_GROW_ADD 16
5281#define DUK_HOBJECT_E_MIN_GROW_DIVISOR 8 /* 2^3 -> 1/8 = 12.5% min growth */
5283/* controls for minimum array part growth */
5284#define DUK_HOBJECT_A_MIN_GROW_ADD 16
5285#define DUK_HOBJECT_A_MIN_GROW_DIVISOR 8 /* 2^3 -> 1/8 = 12.5% min growth */
5287/* probe sequence */
5288#define DUK_HOBJECT_HASH_INITIAL(hash,h_size) ((hash) % (h_size))
5289#define DUK_HOBJECT_HASH_PROBE_STEP(hash) DUK_UTIL_GET_HASH_PROBE_STEP((hash))
5290
5291/*
5292 * PC-to-line constants
5294
5295#define DUK_PC2LINE_SKIP 64
5297/* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
5298#define DUK_PC2LINE_MAX_DIFF_LENGTH (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
5299
5300/*
5301 * Struct defs
5308
5309union duk_propvalue {
5310 /* The get/set pointers could be 16-bit pointer compressed but it
5311 * would make no difference on 32-bit platforms because duk_tval is
5312 * 8 bytes or more anyway.
5314 duk_tval v;
5317
5319 /* read-only values 'lifted' for ease of use */
5324 /* for updating (all are set to < 0 for virtual properties) */
5325 duk_int_t e_idx; /* prop index in 'entry part', < 0 if not there */
5326 duk_int_t h_idx; /* prop index in 'hash part', < 0 if not there */
5327 duk_int_t a_idx; /* prop index in 'array part', < 0 if not there */
5330struct duk_hobject {
5332
5333 /*
5334 * 'props' contains {key,value,flags} entries, optional array entries, and
5335 * an optional hash lookup table for non-array entries in a single 'sliced'
5336 * allocation. There are several layout options, which differ slightly in
5337 * generated code size/speed and alignment/padding; duk_features.h selects
5338 * the layout used.
5339 *
5340 * Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
5341 *
5342 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5343 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5344 * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
5345 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5346 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5347 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5348 *
5349 * Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
5350 *
5351 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5352 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5353 * e_size * sizeof(duk_uint8_t) + pad bytes of entry flags (e_next gc reachable)
5354 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5355 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5356 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5357 *
5358 * Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
5359 *
5360 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5361 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5362 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5363 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5364 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5365 * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
5366 *
5367 * In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
5368 * requiring 4 or 8 byte alignment. This ensures proper alignment
5369 * for the entries, at the cost of memory footprint. However, it's
5370 * probably preferable to use another layout on such platforms instead.
5371 *
5372 * In layout 2, the key and value parts are swapped to avoid padding
5373 * the key array on platforms requiring alignment by 8. The flags part
5374 * is padded to get alignment for array entries. The 'e_next' count does
5375 * not need to be rounded as in layout 1.
5376 *
5377 * In layout 3, entry values and array values are always aligned properly,
5378 * and assuming pointers are at most 8 bytes, so are the entry keys. Hash
5379 * indices will be properly aligned (assuming pointers are at least 4 bytes).
5380 * Finally, flags don't need additional alignment. This layout provides
5381 * compact allocations without padding (even on platforms with alignment
5382 * requirements) at the cost of a bit slower lookups.
5383 *
5384 * Objects with few keys don't have a hash index; keys are looked up linearly,
5385 * which is cache efficient because the keys are consecutive. Larger objects
5386 * have a hash index part which contains integer indexes to the entries part.
5387 *
5388 * A single allocation reduces memory allocation overhead but requires more
5389 * work when any part needs to be resized. A sliced allocation for entries
5390 * makes linear key matching faster on most platforms (more locality) and
5391 * skimps on flags size (which would be followed by 3 bytes of padding in
5392 * most architectures if entries were placed in a struct).
5393 *
5394 * 'props' also contains internal properties distinguished with a non-BMP
5395 * prefix. Often used properties should be placed early in 'props' whenever
5396 * possible to make accessing them as fast a possible.
5397 */
5398
5399#if defined(DUK_USE_HEAPPTR16)
5400 /* Located in duk_heaphdr h_extra16. Subclasses of duk_hobject (like
5401 * duk_hcompiledfunction) are not free to use h_extra16 for this reason.
5403#else
5404 duk_uint8_t *props;
5405#endif
5406
5407 /* prototype: the only internal property lifted outside 'e' as it is so central */
5408#if defined(DUK_USE_HEAPPTR16)
5409 duk_uint16_t prototype16;
5410#else
5412#endif
5413
5414#if defined(DUK_USE_OBJSIZES16)
5415 duk_uint16_t e_size16;
5416 duk_uint16_t e_next16;
5417 duk_uint16_t a_size16;
5418#if defined(DUK_USE_HOBJECT_HASH_PART)
5419 duk_uint16_t h_size16;
5420#endif
5421#else
5422 duk_uint32_t e_size; /* entry part size */
5423 duk_uint32_t e_next; /* index for next new key ([0,e_next[ are gc reachable) */
5424 duk_uint32_t a_size; /* array part size (entirely gc reachable) */
5425#if defined(DUK_USE_HOBJECT_HASH_PART)
5426 duk_uint32_t h_size; /* hash part size or 0 if unused */
5427#endif
5428#endif
5429};
5430
5431/*
5432 * Exposed data
5433 */
5434
5435#if !defined(DUK_SINGLE_FILE)
5437#endif /* !DUK_SINGLE_FILE */
5438
5439/*
5440 * Prototypes
5441 */
5442
5443/* alloc and init */
5445#if 0 /* unused */
5446DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags);
5447#endif
5452
5453/* low-level property functions */
5459
5460/* XXX: when optimizing for guaranteed property slots, use a guaranteed
5461 * slot for internal value; this call can then access it directly.
5462 */
5463#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
5464 duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
5465
5466/* core property functions */
5472/* internal property functions */
5473#define DUK_DELPROP_FLAG_THROW (1 << 0)
5474#define DUK_DELPROP_FLAG_FORCE (1 << 1)
5480DUK_INTERNAL_DECL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length); /* XXX: duk_uarridx_t? */
5482DUK_INTERNAL_DECL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj); /* XXX: duk_uarridx_t? */
5483
5484/* helpers for defineProperty() and defineProperties() */
5487 duk_idx_t idx_in,
5488 duk_uint_t *out_defprop_flags,
5489 duk_idx_t *out_idx_value,
5490 duk_hobject **out_getter,
5491 duk_hobject **out_setter);
5494 duk_uint_t defprop_flags,
5495 duk_hobject *obj,
5496 duk_hstring *key,
5497 duk_idx_t idx_value,
5498 duk_hobject *get,
5499 duk_hobject *set);
5500
5501/* Object built-in methods */
5506
5507/* internal properties */
5510
5511/* hobject management functions */
5513
5514/* ES6 proxy */
5515#if defined(DUK_USE_ES6_PROXY)
5518#endif
5519
5520/* enumeration */
5524
5525/* macros */
5527
5528/* finalization */
5530
5531/* pc2line */
5532#if defined(DUK_USE_PC2LINE)
5535#endif
5536
5537/* misc */
5539
5540#endif /* DUK_HOBJECT_H_INCLUDED */
5541/*
5542 * Heap compiled function (Ecmascript function) representation.
5543 *
5544 * There is a single data buffer containing the Ecmascript function's
5545 * bytecode, constants, and inner functions.
5546 */
5548#ifndef DUK_HCOMPILEDFUNCTION_H_INCLUDED
5549#define DUK_HCOMPILEDFUNCTION_H_INCLUDED
5550
5551/*
5552 * Field accessor macros
5553 */
5554
5555/* XXX: casts could be improved, especially for GET/SET DATA */
5556
5557#if defined(DUK_USE_HEAPPTR16)
5558#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
5559 ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
5560#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
5561 (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5562 } while (0)
5563#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h) \
5564 ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
5565#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v) do { \
5566 (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5567 } while (0)
5568#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h) \
5569 ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
5570#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v) do { \
5571 (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5572 } while (0)
5573#else
5574#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
5575 ((duk_hbuffer_fixed *) (void *) (h)->data)
5576#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
5577 (h)->data = (duk_hbuffer *) (v); \
5578 } while (0)
5579#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h) \
5580 ((h)->funcs)
5581#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v) do { \
5582 (h)->funcs = (v); \
5583 } while (0)
5584#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h) \
5585 ((h)->bytecode)
5586#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v) do { \
5587 (h)->bytecode = (v); \
5588 } while (0)
5589#endif
5590
5591/*
5592 * Accessor macros for function specific data areas
5593 */
5595/* Note: assumes 'data' is always a fixed buffer */
5596#define DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE(heap,h) \
5597 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h)))
5598
5599#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap,h) \
5600 ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((heap), (h)))
5601
5602#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap,h) \
5603 DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h))
5604
5605#define DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap,h) \
5606 DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h))
5607
5608#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap,h) \
5609 ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h)))
5610
5611#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap,h) \
5612 ((duk_hobject **) (void *) DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h)))
5614/* XXX: double evaluation of DUK_HCOMPILEDFUNCTION_GET_DATA() */
5615#define DUK_HCOMPILEDFUNCTION_GET_CODE_END(heap,h) \
5616 ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) + \
5617 DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA((heap), h))))
5618
5619#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap,h) \
5620 ( \
5621 (duk_size_t) \
5622 ( \
5623 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END((heap), (h))) - \
5624 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE((heap), (h))) \
5625 ) \
5627
5628#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(heap,h) \
5629 ( \
5630 (duk_size_t) \
5631 ( \
5632 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END((heap), (h))) - \
5633 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE((heap), (h))) \
5634 ) \
5636
5637#define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap,h) \
5638 ( \
5639 (duk_size_t) \
5640 ( \
5641 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END((heap),(h))) - \
5642 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE((heap),(h))) \
5643 ) \
5645
5646#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap,h) \
5647 ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
5648
5649#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap,h) \
5650 ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
5651
5652#define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(heap,h) \
5653 ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
5654
5655
5656/*
5657 * Main struct
5659
5661 /* shared object part */
5663
5664 /*
5665 * Pointers to function data area for faster access. Function
5666 * data is a buffer shared between all closures of the same
5667 * "template" function. The data buffer is always fixed (non-
5668 * dynamic, hence stable), with a layout as follows:
5669 *
5670 * constants (duk_tval)
5671 * inner functions (duk_hobject *)
5672 * bytecode (duk_instr_t)
5673 *
5674 * Note: bytecode end address can be computed from 'data' buffer
5675 * size. It is not strictly necessary functionally, assuming
5676 * bytecode never jumps outside its allocated area. However,
5677 * it's a safety/robustness feature for avoiding the chance of
5678 * executing random data as bytecode due to a compiler error.
5679 *
5680 * Note: values in the data buffer must be incref'd (they will
5681 * be decref'd on release) for every compiledfunction referring
5682 * to the 'data' element.
5683 */
5684
5685 /* Data area, fixed allocation, stable data ptrs. */
5686#if defined(DUK_USE_HEAPPTR16)
5687 duk_uint16_t data16;
5688#else
5690#endif
5691
5692 /* No need for constants pointer (= same as data).
5693 *
5694 * When using 16-bit packing alignment to 4 is nice. 'funcs' will be
5695 * 4-byte aligned because 'constants' are duk_tvals. For now the
5696 * inner function pointers are not compressed, so that 'bytecode' will
5697 * also be 4-byte aligned.
5698 */
5699#if defined(DUK_USE_HEAPPTR16)
5700 duk_uint16_t funcs16;
5701 duk_uint16_t bytecode16;
5702#else
5705#endif
5706
5707 /*
5708 * 'nregs' registers are allocated on function entry, at most 'nargs'
5709 * are initialized to arguments, and the rest to undefined. Arguments
5710 * above 'nregs' are not mapped to registers. All registers in the
5711 * active stack range must be initialized because they are GC reachable.
5712 * 'nargs' is needed so that if the function is given more than 'nargs'
5713 * arguments, the additional arguments do not 'clobber' registers
5714 * beyond 'nregs' which must be consistently initialized to undefined.
5715 *
5716 * Usually there is no need to know which registers are mapped to
5717 * local variables. Registers may be allocated to variable in any
5718 * way (even including gaps). However, a register-variable mapping
5719 * must be the same for the duration of the function execution and
5720 * the register cannot be used for anything else.
5721 *
5722 * When looking up variables by name, the '_Varmap' map is used.
5723 * When an activation closes, registers mapped to arguments are
5724 * copied into the environment record based on the same map. The
5725 * reverse map (from register to variable) is not currently needed
5726 * at run time, except for debugging, so it is not maintained.
5729 duk_uint16_t nregs; /* regs to allocate */
5730 duk_uint16_t nargs; /* number of arguments allocated to regs */
5731
5732 /*
5733 * Additional control information is placed into the object itself
5734 * as internal properties to avoid unnecessary fields for the
5735 * majority of functions. The compiler tries to omit internal
5736 * control fields when possible.
5737 *
5738 * Function templates:
5739 *
5740 * {
5741 * name: "func", // declaration, named function expressions
5742 * fileName: <debug info for creating nice errors>
5743 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
5744 * _Formals: [ "arg1", "arg2" ],
5745 * _Source: "function func(arg1, arg2) { ... }",
5746 * _Pc2line: <debug info for pc-to-line mapping>,
5747 * }
5748 *
5749 * Function instances:
5750 *
5751 * {
5752 * length: 2,
5753 * prototype: { constructor: <func> },
5754 * caller: <thrower>,
5755 * arguments: <thrower>,
5756 * name: "func", // declaration, named function expressions
5757 * fileName: <debug info for creating nice errors>
5758 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
5759 * _Formals: [ "arg1", "arg2" ],
5760 * _Source: "function func(arg1, arg2) { ... }",
5761 * _Pc2line: <debug info for pc-to-line mapping>,
5762 * _Varenv: <variable environment of closure>,
5763 * _Lexenv: <lexical environment of closure (if differs from _Varenv)>
5764 * }
5765 *
5766 * More detailed description of these properties can be found
5767 * in the documentation.
5768 */
5769
5770#if defined(DUK_USE_DEBUGGER_SUPPORT)
5771 /* Line number range for function. Needed during debugging to
5772 * determine active breakpoints.
5773 */
5774 duk_uint32_t start_line;
5775 duk_uint32_t end_line;
5776#endif
5777};
5778
5779#endif /* DUK_HCOMPILEDFUNCTION_H_INCLUDED */
5780/*
5781 * Heap native function representation.
5782 */
5784#ifndef DUK_HNATIVEFUNCTION_H_INCLUDED
5785#define DUK_HNATIVEFUNCTION_H_INCLUDED
5787#define DUK_HNATIVEFUNCTION_NARGS_VARARGS ((duk_int16_t) -1)
5788#define DUK_HNATIVEFUNCTION_NARGS_MAX ((duk_int16_t) 0x7fff)
5789
5791 /* shared object part */
5795 duk_int16_t nargs;
5796 duk_int16_t magic;
5797
5798 /* The 'magic' field allows an opaque 16-bit field to be accessed by the
5799 * Duktape/C function. This allows, for instance, the same native function
5800 * to be used for a set of very similar functions, with the 'magic' field
5801 * providing the necessary non-argument flags / values to guide the behavior
5802 * of the native function. The value is signed on purpose: it is easier to
5803 * convert a signed value to unsigned (simply AND with 0xffff) than vice
5804 * versa.
5805 *
5806 * Note: cannot place nargs/magic into the heaphdr flags, because
5807 * duk_hobject takes almost all flags already (and needs the spare).
5808 */
5809};
5810
5811#endif /* DUK_HNATIVEFUNCTION_H_INCLUDED */
5812/*
5813 * Heap Buffer object representation. Used for all Buffer variants.
5814 */
5816#ifndef DUK_HBUFFEROBJECT_H_INCLUDED
5817#define DUK_HBUFFEROBJECT_H_INCLUDED
5819/* All element accessors are host endian now (driven by TypedArray spec). */
5820#define DUK_HBUFFEROBJECT_ELEM_UINT8 0
5821#define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED 1
5822#define DUK_HBUFFEROBJECT_ELEM_INT8 2
5823#define DUK_HBUFFEROBJECT_ELEM_UINT16 3
5824#define DUK_HBUFFEROBJECT_ELEM_INT16 4
5825#define DUK_HBUFFEROBJECT_ELEM_UINT32 5
5826#define DUK_HBUFFEROBJECT_ELEM_INT32 6
5827#define DUK_HBUFFEROBJECT_ELEM_FLOAT32 7
5828#define DUK_HBUFFEROBJECT_ELEM_FLOAT64 8
5829#define DUK_HBUFFEROBJECT_ELEM_MAX 8
5830
5831#define DUK_ASSERT_HBUFFEROBJECT_VALID(h) do { \
5832 DUK_ASSERT((h) != NULL); \
5833 DUK_ASSERT((h)->shift <= 3); \
5834 DUK_ASSERT((h)->elem_type <= DUK_HBUFFEROBJECT_ELEM_MAX); \
5835 DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8) || \
5836 ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) || \
5837 ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT8) || \
5838 ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT16) || \
5839 ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT16) || \
5840 ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT32) || \
5841 ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT32) || \
5842 ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT32) || \
5843 ((h)->shift == 3 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT64)); \
5844 DUK_ASSERT((h)->is_view == 0 || (h)->is_view == 1); \
5845 DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) (h))); \
5846 if ((h)->buf == NULL) { \
5847 DUK_ASSERT((h)->offset == 0); \
5848 DUK_ASSERT((h)->length == 0); \
5849 } else { \
5850 /* No assertions for offset or length; in particular, \
5851 * it's OK for length to be longer than underlying \
5852 * buffer. Just ensure they don't wrap when added. \
5853 */ \
5854 DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
5855 } \
5856 } while (0)
5857
5858/* Get the current data pointer (caller must ensure buf != NULL) as a
5859 * duk_uint8_t ptr.
5860 */
5861#define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap,h) \
5862 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5863 (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
5864
5865/* True if slice is full, i.e. offset is zero and length covers the entire
5866 * buffer. This status may change independently of the duk_hbufferobject if
5867 * the underlying buffer is dynamic and changes without the hbufferobject
5868 * being changed.
5869 */
5870#define DUK_HBUFFEROBJECT_FULL_SLICE(h) \
5871 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5872 ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
5873
5874/* Validate that the whole slice [0,length[ is contained in the underlying
5875 * buffer. Caller must ensure 'buf' != NULL.
5876 */
5877#define DUK_HBUFFEROBJECT_VALID_SLICE(h) \
5878 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5879 ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
5880
5881/* Validate byte read/write for virtual 'offset', i.e. check that the
5882 * offset, taking into account h->offset, is within the underlying
5883 * buffer size. This is a safety check which is needed to ensure
5884 * that even a misconfigured duk_hbufferobject never causes memory
5885 * unsafe behavior (e.g. if an underlying dynamic buffer changes
5886 * after being setup). Caller must ensure 'buf' != NULL.
5888#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_INCL(h,off) \
5889 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5890 ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
5891
5892#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h,off) \
5893 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5894 ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
5895
5896/* Clamp an input byte length (already assumed to be within the nominal
5897 * duk_hbufferobject 'length') to the current dynamic buffer limits to
5898 * yield a byte length limit that's safe for memory accesses. This value
5899 * can be invalidated by any side effect because it may trigger a user
5900 * callback that resizes the underlying buffer.
5902#define DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h,len) \
5903 (DUK_ASSERT_EXPR((h) != NULL), \
5904 duk_hbufferobject_clamp_bytelength((h), (len)))
5905
5907 /* Shared object part. */
5909
5910 /* Underlying buffer (refcounted), may be NULL. */
5912
5913 /* Slice and accessor information.
5914 *
5915 * Because the underlying buffer may be dynamic, these may be
5916 * invalidated by the buffer being modified so that both offset
5917 * and length should be validated before every access. Behavior
5918 * when the underlying buffer has changed doesn't need to be clean:
5919 * virtual 'length' doesn't need to be affected, reads can return
5920 * zero/NaN, and writes can be ignored.
5922 * Note that a data pointer cannot be precomputed because 'buf' may
5923 * be dynamic and its pointer unstable.
5924 */
5925
5926 duk_uint_t offset; /* byte offset to buf */
5927 duk_uint_t length; /* byte index limit for element access, exclusive */
5928 duk_uint8_t shift; /* element size shift:
5929 * 0 = u8/i8
5930 * 1 = u16/i16
5931 * 2 = u32/i32/float
5932 * 3 = double
5933 */
5934 duk_uint8_t elem_type; /* element type */
5935 duk_uint8_t is_view;
5936};
5937
5938#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5940#endif
5943
5944#endif /* DUK_HBUFFEROBJECT_H_INCLUDED */
5945/*
5946 * Heap thread object representation.
5947 *
5948 * duk_hthread is also the 'context' (duk_context) for exposed APIs
5949 * which mostly operate on the topmost frame of the value stack.
5950 */
5951
5952#ifndef DUK_HTHREAD_H_INCLUDED
5953#define DUK_HTHREAD_H_INCLUDED
5956 * Stack constants
5959#define DUK_VALSTACK_GROW_STEP 128 /* roughly 1 kiB */
5960#define DUK_VALSTACK_SHRINK_THRESHOLD 256 /* roughly 2 kiB */
5961#define DUK_VALSTACK_SHRINK_SPARE 64 /* roughly 0.5 kiB */
5962#define DUK_VALSTACK_INITIAL_SIZE 128 /* roughly 1.0 kiB -> but rounds up to DUK_VALSTACK_GROW_STEP in practice */
5963#define DUK_VALSTACK_INTERNAL_EXTRA 64 /* internal extra elements assumed on function entry,
5964 * always added to user-defined 'extra' for e.g. the
5965 * duk_check_stack() call.
5966 */
5967#define DUK_VALSTACK_API_ENTRY_MINIMUM DUK_API_ENTRY_STACK
5968 /* number of elements guaranteed to be user accessible
5969 * (in addition to call arguments) on Duktape/C function entry.
5970 */
5972/* Note: DUK_VALSTACK_INITIAL_SIZE must be >= DUK_VALSTACK_API_ENTRY_MINIMUM
5973 * + DUK_VALSTACK_INTERNAL_EXTRA so that the initial stack conforms to spare
5974 * requirements.
5976
5977#define DUK_VALSTACK_DEFAULT_MAX 1000000L
5979#define DUK_CALLSTACK_GROW_STEP 8 /* roughly 256 bytes */
5980#define DUK_CALLSTACK_SHRINK_THRESHOLD 16 /* roughly 512 bytes */
5981#define DUK_CALLSTACK_SHRINK_SPARE 8 /* roughly 256 bytes */
5982#define DUK_CALLSTACK_INITIAL_SIZE 8
5983#define DUK_CALLSTACK_DEFAULT_MAX 10000L
5984
5985#define DUK_CATCHSTACK_GROW_STEP 4 /* roughly 64 bytes */
5986#define DUK_CATCHSTACK_SHRINK_THRESHOLD 8 /* roughly 128 bytes */
5987#define DUK_CATCHSTACK_SHRINK_SPARE 4 /* roughly 64 bytes */
5988#define DUK_CATCHSTACK_INITIAL_SIZE 4
5989#define DUK_CATCHSTACK_DEFAULT_MAX 10000L
5992 * Activation defines
5993 */
5995#define DUK_ACT_FLAG_STRICT (1 << 0) /* function executes in strict mode */
5996#define DUK_ACT_FLAG_TAILCALLED (1 << 1) /* activation has tail called one or more times */
5997#define DUK_ACT_FLAG_CONSTRUCT (1 << 2) /* function executes as a constructor (called via "new") */
5998#define DUK_ACT_FLAG_PREVENT_YIELD (1 << 3) /* activation prevents yield (native call or "new") */
5999#define DUK_ACT_FLAG_DIRECT_EVAL (1 << 4) /* activation is a direct eval call */
6000#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE (1 << 5) /* activation has active breakpoint(s) */
6001
6002#define DUK_ACT_GET_FUNC(act) ((act)->func)
6003
6004/*
6005 * Flags for __FILE__ / __LINE__ registered into tracedata
6006 */
6008#define DUK_TB_FLAG_NOBLAME_FILELINE (1 << 0) /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
6011 * Catcher defines
6012 */
6014/* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
6015#define DUK_CAT_TYPE_MASK 0x0000000fUL
6016#define DUK_CAT_TYPE_BITS 4
6017#define DUK_CAT_LABEL_MASK 0xffffff00UL
6018#define DUK_CAT_LABEL_BITS 24
6019#define DUK_CAT_LABEL_SHIFT 8
6021#define DUK_CAT_FLAG_CATCH_ENABLED (1 << 4) /* catch part will catch */
6022#define DUK_CAT_FLAG_FINALLY_ENABLED (1 << 5) /* finally part will catch */
6023#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED (1 << 6) /* request to create catch binding */
6024#define DUK_CAT_FLAG_LEXENV_ACTIVE (1 << 7) /* catch or with binding is currently active */
6026#define DUK_CAT_TYPE_UNKNOWN 0
6027#define DUK_CAT_TYPE_TCF 1
6028#define DUK_CAT_TYPE_LABEL 2
6029
6030#define DUK_CAT_GET_TYPE(c) ((c)->flags & DUK_CAT_TYPE_MASK)
6031#define DUK_CAT_GET_LABEL(c) (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
6032
6033#define DUK_CAT_HAS_CATCH_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
6034#define DUK_CAT_HAS_FINALLY_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
6035#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
6036#define DUK_CAT_HAS_LEXENV_ACTIVE(c) ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
6037
6038#define DUK_CAT_SET_CATCH_ENABLED(c) do { \
6039 (c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
6040 } while (0)
6041#define DUK_CAT_SET_FINALLY_ENABLED(c) do { \
6042 (c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
6043 } while (0)
6044#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c) do { \
6045 (c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6046 } while (0)
6047#define DUK_CAT_SET_LEXENV_ACTIVE(c) do { \
6048 (c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
6049 } while (0)
6050
6051#define DUK_CAT_CLEAR_CATCH_ENABLED(c) do { \
6052 (c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
6053 } while (0)
6054#define DUK_CAT_CLEAR_FINALLY_ENABLED(c) do { \
6055 (c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
6056 } while (0)
6057#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c) do { \
6058 (c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6059 } while (0)
6060#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c) do { \
6061 (c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
6062 } while (0)
6063
6064/*
6065 * Thread defines
6066 */
6067
6068#if defined(DUK_USE_ROM_STRINGS)
6069#define DUK_HTHREAD_GET_STRING(thr,idx) \
6070 ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
6071#else /* DUK_USE_ROM_STRINGS */
6072#if defined(DUK_USE_HEAPPTR16)
6073#define DUK_HTHREAD_GET_STRING(thr,idx) \
6074 ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
6075#else
6076#define DUK_HTHREAD_GET_STRING(thr,idx) \
6077 ((thr)->strs[(idx)])
6078#endif
6079#endif /* DUK_USE_ROM_STRINGS */
6081#define DUK_HTHREAD_GET_CURRENT_ACTIVATION(thr) (&(thr)->callstack[(thr)->callstack_top - 1])
6082
6083/* values for the state field */
6084#define DUK_HTHREAD_STATE_INACTIVE 1 /* thread not currently running */
6085#define DUK_HTHREAD_STATE_RUNNING 2 /* thread currently running (only one at a time) */
6086#define DUK_HTHREAD_STATE_RESUMED 3 /* thread resumed another thread (active but not running) */
6087#define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */
6088#define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */
6089
6090/* Executor interrupt default interval when nothing else requires a
6091 * smaller value. The default interval must be small enough to allow
6092 * for reasonable execution timeout checking but large enough to keep
6093 * impact on execution performance low.
6094 */
6095#if defined(DUK_USE_INTERRUPT_COUNTER)
6096#define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L)
6097#endif
6098
6099/*
6100 * Assert context is valid: non-NULL pointer, fields look sane.
6101 *
6102 * This is used by public API call entrypoints to catch invalid 'ctx' pointers
6103 * as early as possible; invalid 'ctx' pointers cause very odd and difficult to
6104 * diagnose behavior so it's worth checking even when the check is not 100%.
6105 */
6107#if defined(DUK_USE_PREFER_SIZE)
6108#define DUK_ASSERT_CTX_VSSIZE(ctx) /*nop*/
6109#else
6110#define DUK_ASSERT_CTX_VSSIZE(ctx) \
6111 DUK_ASSERT((duk_size_t) (((duk_hthread *) (ctx))->valstack_end - ((duk_hthread *) (ctx))->valstack) == \
6112 ((duk_hthread *) (ctx))->valstack_size)
6113#endif
6114#define DUK_ASSERT_CTX_VALID(ctx) do { \
6115 DUK_ASSERT((ctx) != NULL); \
6116 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (ctx)) == DUK_HTYPE_OBJECT); \
6117 DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (ctx))); \
6118 DUK_ASSERT(((duk_hthread *) (ctx))->unused1 == 0); \
6119 DUK_ASSERT(((duk_hthread *) (ctx))->unused2 == 0); \
6120 DUK_ASSERT(((duk_hthread *) (ctx))->valstack != NULL); \
6121 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack); \
6122 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack); \
6123 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack_bottom); \
6124 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack_top); \
6125 DUK_ASSERT_CTX_VSSIZE((ctx)); \
6126 } while (0)
6127
6128/*
6129 * Struct defines
6132/* XXX: for a memory-code tradeoff, remove 'func' and make it's access either a function
6133 * or a macro. This would make the activation 32 bytes long on 32-bit platforms again.
6134 */
6135
6136/* Note: it's nice if size is 2^N (at least for 32-bit platforms). */
6137struct duk_activation {
6138 duk_tval tv_func; /* borrowed: full duk_tval for function being executed; for lightfuncs */
6139 duk_hobject *func; /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
6140 duk_hobject *var_env; /* current variable environment (may be NULL if delayed) */
6141 duk_hobject *lex_env; /* current lexical environment (may be NULL if delayed) */
6142#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
6143 /* Previous value of 'func' caller, restored when unwound. Only in use
6144 * when 'func' is non-strict.
6146 duk_hobject *prev_caller;
6147#endif
6148
6149 duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
6150#if defined(DUK_USE_DEBUGGER_SUPPORT)
6151 duk_uint32_t prev_line; /* needed for stepping */
6152#endif
6154
6155 /* idx_bottom and idx_retval are only used for book-keeping of
6156 * Ecmascript-initiated calls, to allow returning to an Ecmascript
6157 * function properly. They are duk_size_t to match the convention
6158 * that value stack sizes are duk_size_t and local frame indices
6159 * are duk_idx_t.
6160 */
6161
6162 /* Bottom of valstack for this activation, used to reset
6163 * valstack_bottom on return; index is absolute. Note:
6164 * idx_top not needed because top is set to 'nregs' always
6165 * when returning to an Ecmascript activation.
6166 */
6168
6169 /* Return value when returning to this activation (points to caller
6170 * reg, not callee reg); index is absolute (only set if activation is
6171 * not topmost).
6172 *
6173 * Note: idx_bottom is always set, while idx_retval is only applicable
6174 * for activations below the topmost one. Currently idx_retval for
6175 * the topmost activation is considered garbage (and it not initialized
6176 * on entry or cleared on return; may contain previous or garbage
6177 * values).
6178 */
6180
6181 /* Current 'this' binding is the value just below idx_bottom.
6182 * Previously, 'this' binding was handled with an index to the
6183 * (calling) valstack. This works for everything except tail
6184 * calls, which must not "cumulate" valstack temps.
6188/* Note: it's nice if size is 2^N (not 4x4 = 16 bytes on 32 bit) */
6189struct duk_catcher {
6190 duk_hstring *h_varname; /* borrowed reference to catch variable name (or NULL if none) */
6191 /* (reference is valid as long activation exists) */
6192 duk_instr_t *pc_base; /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
6193 duk_size_t callstack_index; /* callstack index of related activation */
6194 duk_size_t idx_base; /* idx_base and idx_base+1 get completion value and type */
6195 duk_uint32_t flags; /* type and control flags, label number */
6196};
6197
6198struct duk_hthread {
6199 /* Shared object part */
6201
6202 /* Pointer to bytecode executor's 'curr_pc' variable. Used to copy
6203 * the current PC back into the topmost activation when activation
6204 * state is about to change (or "syncing" is otherwise needed). This
6205 * is rather awkward but important for performance, see execution.rst.
6206 */
6209 /* Backpointers. */
6211
6212 /* Current strictness flag: affects API calls. */
6213 duk_uint8_t strict;
6215 /* Thread state. */
6216 duk_uint8_t state;
6217 duk_uint8_t unused1;
6218 duk_uint8_t unused2;
6219
6220 /* Sanity limits for stack sizes. */
6224
6225 /* XXX: Valstack, callstack, and catchstack are currently assumed
6226 * to have non-NULL pointers. Relaxing this would not lead to big
6227 * benefits (except perhaps for terminated threads).
6230 /* Value stack: these are expressed as pointers for faster stack manipulation.
6231 * [valstack,valstack_top[ is GC-reachable, [valstack_top,valstack_end[ is
6232 * not GC-reachable but kept initialized as 'undefined'.
6233 */
6234 duk_tval *valstack; /* start of valstack allocation */
6235 duk_tval *valstack_end; /* end of valstack allocation (exclusive) */
6236 duk_tval *valstack_bottom; /* bottom of current frame */
6237 duk_tval *valstack_top; /* top of current frame (exclusive) */
6238#if !defined(DUK_USE_PREFER_SIZE)
6239 duk_size_t valstack_size; /* cached: valstack_end - valstack (in entries, not bytes) */
6240#endif
6242 /* Call stack. [0,callstack_top[ is GC reachable. */
6244 duk_size_t callstack_size; /* allocation size */
6245 duk_size_t callstack_top; /* next to use, highest used is top - 1 */
6246 duk_size_t callstack_preventcount; /* number of activation records in callstack preventing a yield */
6247
6248 /* Catch stack. [0,catchstack_top[ is GC reachable. */
6250 duk_size_t catchstack_size; /* allocation size */
6251 duk_size_t catchstack_top; /* next to use, highest used is top - 1 */
6252
6253 /* Yield/resume book-keeping. */
6254 duk_hthread *resumer; /* who resumed us (if any) */
6255
6256 /* Current compiler state (if any), used for augmenting SyntaxErrors. */
6258
6259#if defined(DUK_USE_INTERRUPT_COUNTER)
6260 /* Interrupt counter for triggering a slow path check for execution
6261 * timeout, debugger interaction such as breakpoints, etc. The value
6262 * is valid for the current running thread, and both the init and
6263 * counter values are copied whenever a thread switch occurs. It's
6264 * important for the counter to be conveniently accessible for the
6265 * bytecode executor inner loop for performance reasons.
6266 */
6267 duk_int_t interrupt_counter; /* countdown state */
6268 duk_int_t interrupt_init; /* start value for current countdown */
6269#endif
6270
6271 /* Builtin-objects; may or may not be shared with other threads,
6272 * threads existing in different "compartments" will have different
6273 * built-ins. Must be stored on a per-thread basis because there
6274 * is no intermediate structure for a thread group / compartment.
6275 * This takes quite a lot of space, currently 43x4 = 172 bytes on
6276 * 32-bit platforms.
6277 *
6278 * In some cases the builtins array could be ROM based, but it's
6279 * sometimes edited (e.g. for sandboxing) so it's better to keep
6280 * this array in RAM.
6281 */
6284 /* Convenience copies from heap/vm for faster access. */
6285#if defined(DUK_USE_ROM_STRINGS)
6286 /* No field needed when strings are in ROM. */
6287#else
6288#if defined(DUK_USE_HEAPPTR16)
6289 duk_uint16_t *strs16;
6290#else
6291 duk_hstring **strs;
6292#endif
6293#endif
6294};
6295
6296/*
6297 * Prototypes
6298 */
6299
6304
6311
6313DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6314DUK_INTERNAL_DECL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6315DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6316
6317#if defined(DUK_USE_DEBUGGER_SUPPORT)
6318DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
6319#endif
6323
6324#endif /* DUK_HTHREAD_H_INCLUDED */
6325/*
6326 * Heap buffer representation.
6327 *
6328 * Heap allocated user data buffer which is either:
6330 * 1. A fixed size buffer (data follows header statically)
6331 * 2. A dynamic size buffer (data pointer follows header)
6332 *
6333 * The data pointer for a variable size buffer of zero size may be NULL.
6334 */
6335
6336#ifndef DUK_HBUFFER_H_INCLUDED
6337#define DUK_HBUFFER_H_INCLUDED
6338
6340 * Flags
6341 *
6342 * Fixed buffer: 0
6343 * Dynamic buffer: DUK_HBUFFER_FLAG_DYNAMIC
6344 * External buffer: DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
6347#define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */
6348#define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */
6350#define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6351#define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6352
6353#define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6354#define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6355
6356#define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6357#define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6358
6359/*
6360 * Misc defines
6361 */
6362
6363/* Impose a maximum buffer length for now. Restricted artificially to
6364 * ensure resize computations or adding a heap header length won't
6365 * overflow size_t and that a signed duk_int_t can hold a buffer
6366 * length. The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
6368
6369#if defined(DUK_USE_BUFLEN16)
6370#define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL)
6371#else
6372/* Intentionally not 0x7fffffffUL; at least JSON code expects that
6373 * 2*len + 2 fits in 32 bits.
6374 */
6375#define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL)
6376#endif
6377
6378/*
6379 * Field access
6380 */
6381
6382/* Get/set the current user visible size, without accounting for a dynamic
6383 * buffer's "spare" (= usable size).
6384 */
6385#if defined(DUK_USE_BUFLEN16)
6386/* size stored in duk_heaphdr unused flag bits */
6387#define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16)
6388#define DUK_HBUFFER_SET_SIZE(x,v) do { \
6389 duk_size_t duk__v; \
6390 duk__v = (v); \
6391 DUK_ASSERT(duk__v <= 0xffffUL); \
6392 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
6393 } while (0)
6394#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
6395 (x)->hdr.h_flags += ((dv) << 16); \
6396 } while (0)
6397#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
6398 (x)->hdr.h_flags -= ((dv) << 16); \
6399 } while (0)
6400#else
6401#define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size)
6402#define DUK_HBUFFER_SET_SIZE(x,v) do { \
6403 ((duk_hbuffer *) (x))->size = (v); \
6404 } while (0)
6405#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
6406 (x)->size += (dv); \
6407 } while (0)
6408#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
6409 (x)->size -= (dv); \
6410 } while (0)
6411#endif
6412
6413#define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6414#define DUK_HBUFFER_FIXED_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
6415
6416#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6417#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
6418#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
6419#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
6420
6421#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6422#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
6423
6424#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
6425
6426#if defined(DUK_USE_HEAPPTR16)
6427#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
6428 ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
6429#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
6430 ((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6431 } while (0)
6432#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
6433 ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \
6434 } while (0)
6435#else
6436#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) ((x)->curr_alloc)
6437#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
6438 (x)->curr_alloc = (void *) (v); \
6439 } while (0)
6440#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
6441 (x)->curr_alloc = (void *) NULL; \
6442 } while (0)
6443#endif
6444
6445/* No pointer compression because pointer is potentially outside of
6446 * Duktape heap.
6447 */
6448#if defined(DUK_USE_HEAPPTR16)
6449#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
6450 ((void *) (x)->curr_alloc)
6451#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
6452 (x)->curr_alloc = (void *) (v); \
6453 } while (0)
6454#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
6455 (x)->curr_alloc = (void *) NULL; \
6456 } while (0)
6457#else
6458#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
6459 ((void *) (x)->curr_alloc)
6460#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
6461 (x)->curr_alloc = (void *) (v); \
6462 } while (0)
6463#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
6464 (x)->curr_alloc = (void *) NULL; \
6465 } while (0)
6466#endif
6467
6468/* Get a pointer to the current buffer contents (matching current allocation
6469 * size). May be NULL for zero size dynamic/external buffer.
6470 */
6471#if defined(DUK_USE_HEAPPTR16)
6472#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
6473 DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
6474 ( \
6475 DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
6476 DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
6477 DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
6478 ) : \
6479 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
6480 )
6481#else
6482/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
6483 * have the same layout so checking for fixed vs. dynamic (or external) is enough.
6484 */
6485#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
6486 DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
6487 DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
6488 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
6490#endif
6491
6492/*
6493 * Structs
6494 */
6495
6496/* Shared prefix for all buffer types. */
6497struct duk_hbuffer {
6499
6500 /* It's not strictly necessary to track the current size, but
6501 * it is useful for writing robust native code.
6502 */
6503
6504 /* Current size (not counting a dynamic buffer's "spare"). */
6505#if defined(DUK_USE_BUFLEN16)
6506 /* Stored in duk_heaphdr unused flags. */
6507#else
6509#endif
6510
6511 /*
6512 * Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
6513 * flag.
6514 *
6515 * If the flag is clear (the buffer is a fixed size one), the buffer
6516 * data follows the header directly, consisting of 'size' bytes.
6517 *
6518 * If the flag is set, the actual buffer is allocated separately, and
6519 * a few control fields follow the header. Specifically:
6520 *
6521 * - a "void *" pointing to the current allocation
6522 * - a duk_size_t indicating the full allocated size (always >= 'size')
6523 *
6524 * If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
6525 * by user code, so that Duktape won't be able to resize it and won't
6526 * free it. This allows buffers to point to e.g. an externally
6527 * allocated structure such as a frame buffer.
6528 *
6529 * Unlike strings, no terminator byte (NUL) is guaranteed after the
6530 * data. This would be convenient, but would pad aligned user buffers
6531 * unnecessarily upwards in size. For instance, if user code requested
6532 * a 64-byte dynamic buffer, 65 bytes would actually be allocated which
6533 * would then potentially round upwards to perhaps 68 or 72 bytes.
6534 */
6536
6537/* Fixed buffer; data follows struct, with proper alignment guaranteed by
6538 * struct size.
6539 */
6540#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
6541#pragma pack(push, 8)
6542#endif
6543struct duk_hbuffer_fixed {
6544 /* A union is used here as a portable struct size / alignment trick:
6545 * by adding a 32-bit or a 64-bit (unused) union member, the size of
6546 * the struct is effectively forced to be a multiple of 4 or 8 bytes
6547 * (respectively) without increasing the size of the struct unless
6548 * necessary.
6549 */
6550 union {
6551 struct {
6553#if defined(DUK_USE_BUFLEN16)
6554 /* Stored in duk_heaphdr unused flags. */
6555#else
6557#endif
6558 } s;
6559#if (DUK_USE_ALIGN_BY == 4)
6560 duk_uint32_t dummy_for_align4;
6561#elif (DUK_USE_ALIGN_BY == 8)
6563#elif (DUK_USE_ALIGN_BY == 1)
6564 /* no extra padding */
6565#else
6566#error invalid DUK_USE_ALIGN_BY
6567#endif
6568 } u;
6569
6570 /*
6571 * Data follows the struct header. The struct size is padded by the
6572 * compiler based on the struct members. This guarantees that the
6573 * buffer data will be aligned-by-4 but not necessarily aligned-by-8.
6574 *
6575 * On platforms where alignment does not matter, the struct padding
6576 * could be removed (if there is any). On platforms where alignment
6577 * by 8 is required, the struct size must be forced to be a multiple
6578 * of 8 by some means. Without it, some user code may break, and also
6579 * Duktape itself breaks (e.g. the compiler stores duk_tvals in a
6580 * dynamic buffer).
6581 */
6582}
6583#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
6584__attribute__ ((aligned (8)))
6585#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
6586__attribute__ ((aligned (8)))
6587#endif
6588;
6589#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
6590#pragma pack(pop)
6591#endif
6592
6593/* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
6594 * heap allocation primitives. Also used for external buffers when low memory
6595 * options are not used.
6596 */
6597struct duk_hbuffer_dynamic {
6599
6600#if defined(DUK_USE_BUFLEN16)
6601 /* Stored in duk_heaphdr unused flags. */
6602#else
6604#endif
6605
6606#if defined(DUK_USE_HEAPPTR16)
6607 /* Stored in duk_heaphdr h_extra16. */
6608#else
6609 void *curr_alloc; /* may be NULL if alloc_size == 0 */
6610#endif
6611
6612 /*
6613 * Allocation size for 'curr_alloc' is alloc_size. There is no
6614 * automatic NUL terminator for buffers (see above for rationale).
6615 *
6616 * 'curr_alloc' is explicitly allocated with heap allocation
6617 * primitives and will thus always have alignment suitable for
6618 * e.g. duk_tval and an IEEE double.
6620};
6621
6622/* External buffer with 'curr_alloc' managed by user code and pointing to an
6623 * arbitrary address. When heap pointer compression is not used, this struct
6624 * has the same layout as duk_hbuffer_dynamic.
6625 */
6626struct duk_hbuffer_external {
6628
6629#if defined(DUK_USE_BUFLEN16)
6630 /* Stored in duk_heaphdr unused flags. */
6631#else
6633#endif
6634
6635 /* Cannot be compressed as a heap pointer because may point to
6636 * an arbitrary address.
6637 */
6638 void *curr_alloc; /* may be NULL if alloc_size == 0 */
6639};
6640
6641/*
6642 * Prototypes
6643 */
6644
6646DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6647
6648/* dynamic buffer ops */
6651
6652#endif /* DUK_HBUFFER_H_INCLUDED */
6654 * Heap structure.
6655 *
6656 * Heap contains allocated heap objects, interned strings, and built-in
6657 * strings for one or more threads.
6658 */
6659
6660#ifndef DUK_HEAP_H_INCLUDED
6661#define DUK_HEAP_H_INCLUDED
6663/* alloc function typedefs in duktape.h */
6666 * Heap flags
6667 */
6669#define DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING (1 << 0) /* mark-and-sweep is currently running */
6670#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED (1 << 1) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
6671#define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING (1 << 2) /* refcount code is processing refzero list */
6672#define DUK_HEAP_FLAG_ERRHANDLER_RUNNING (1 << 3) /* an error handler (user callback to augment/replace error) is running */
6673#define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1 << 4) /* executor interrupt running (used to avoid nested interrupts) */
6674#define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1 << 5) /* heap destruction ongoing, finalizer rescue no longer possible */
6675
6676#define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits))
6677#define DUK__HEAP_SET_FLAGS(heap,bits) do { \
6678 (heap)->flags |= (bits); \
6679 } while (0)
6680#define DUK__HEAP_CLEAR_FLAGS(heap,bits) do { \
6681 (heap)->flags &= ~(bits); \
6682 } while (0)
6684#define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6685#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6686#define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6687#define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6688#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6689#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6691#define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6692#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6693#define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6694#define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6695#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6696#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6697
6698#define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6699#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6700#define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6701#define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6702#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6703#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6706 * Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
6709#define DUK_LJ_TYPE_UNKNOWN 0 /* unused */
6710#define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */
6711#define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */
6712#define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
6713#define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
6714#define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
6715#define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
6716#define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
6717
6719 * Mark-and-sweep flags
6721 * These are separate from heap level flags now but could be merged.
6722 * The heap structure only contains a 'base mark-and-sweep flags'
6723 * field and the GC caller can impose further flags.
6724 */
6725
6726#define DUK_MS_FLAG_EMERGENCY (1 << 0) /* emergency mode: try extra hard */
6727#define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE (1 << 1) /* don't resize stringtable (but may sweep it); needed during stringtable resize */
6728#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1 << 2) /* don't compact objects; needed during object property allocation resize */
6729#define DUK_MS_FLAG_NO_FINALIZERS (1 << 3) /* don't run finalizers; leave finalizable objects in finalize_list for next round */
6730#define DUK_MS_FLAG_SKIP_FINALIZERS (1 << 4) /* don't run finalizers; queue finalizable objects back to heap_allocated */
6731
6732/*
6733 * Thread switching
6734 *
6735 * To switch heap->curr_thread, use the macro below so that interrupt counters
6736 * get updated correctly. The macro allows a NULL target thread because that
6737 * happens e.g. in call handling.
6738 */
6739
6740#if defined(DUK_USE_INTERRUPT_COUNTER)
6741#define DUK_HEAP_SWITCH_THREAD(heap,newthr) duk_heap_switch_thread((heap), (newthr))
6742#else
6743#define DUK_HEAP_SWITCH_THREAD(heap,newthr) do { \
6744 (heap)->curr_thread = (newthr); \
6745 } while (0)
6746#endif
6747
6748/*
6749 * Other heap related defines
6750 */
6751
6752/* Mark-and-sweep interval is relative to combined count of objects and
6753 * strings kept in the heap during the latest mark-and-sweep pass.
6754 * Fixed point .8 multiplier and .0 adder. Trigger count (interval) is
6755 * decreased by each (re)allocation attempt (regardless of size), and each
6756 * refzero processed object.
6758 * 'SKIP' indicates how many (re)allocations to wait until a retry if
6759 * GC is skipped because there is no thread do it with yet (happens
6760 * only during init phases).
6761 */
6762#if defined(DUK_USE_MARK_AND_SWEEP)
6763#if defined(DUK_USE_REFERENCE_COUNTING)
6764#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */
6765#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
6766#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
6767#else
6768#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */
6769#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
6770#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
6771#endif
6772#endif
6774/* Stringcache is used for speeding up char-offset-to-byte-offset
6775 * translations for non-ASCII strings.
6776 */
6777#define DUK_HEAP_STRCACHE_SIZE 4
6778#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */
6779
6780/* helper to insert a (non-string) heap object into heap allocated list */
6781#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap),(hdr))
6782
6784 * Stringtable
6785 */
6787/* initial stringtable size, must be prime and higher than DUK_UTIL_MIN_HASH_PRIME */
6788#define DUK_STRTAB_INITIAL_SIZE 17
6789
6790/* indicates a deleted string; any fixed non-NULL, non-hstring pointer works */
6791#define DUK_STRTAB_DELETED_MARKER(heap) ((duk_hstring *) heap)
6792
6793/* resizing parameters */
6794#define DUK_STRTAB_MIN_FREE_DIVISOR 4 /* load factor max 75% */
6795#define DUK_STRTAB_MIN_USED_DIVISOR 4 /* load factor min 25% */
6796#define DUK_STRTAB_GROW_ST_SIZE(n) ((n) + (n)) /* used entries + approx 100% -> reset load to 50% */
6797
6798#define DUK_STRTAB_U32_MAX_STRLEN 10 /* 4'294'967'295 */
6799#define DUK_STRTAB_HIGHEST_32BIT_PRIME 0xfffffffbUL
6800
6801/* probe sequence (open addressing) */
6802#define DUK_STRTAB_HASH_INITIAL(hash,h_size) ((hash) % (h_size))
6803#define DUK_STRTAB_HASH_PROBE_STEP(hash) DUK_UTIL_GET_HASH_PROBE_STEP((hash))
6804
6805/* fixed top level hashtable size (separate chaining) */
6806#define DUK_STRTAB_CHAIN_SIZE DUK_USE_STRTAB_CHAIN_SIZE
6807
6808/*
6809 * Built-in strings
6810 */
6811
6812/* heap string indices are autogenerated in duk_strings.h */
6813#if defined(DUK_USE_ROM_STRINGS)
6814#define DUK_HEAP_GET_STRING(heap,idx) \
6815 ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
6816#else /* DUK_USE_ROM_STRINGS */
6817#if defined(DUK_USE_HEAPPTR16)
6818#define DUK_HEAP_GET_STRING(heap,idx) \
6819 ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
6820#else
6821#define DUK_HEAP_GET_STRING(heap,idx) \
6822 ((heap)->strs[(idx)])
6823#endif
6824#endif /* DUK_USE_ROM_STRINGS */
6826/*
6827 * Raw memory calls: relative to heap, but no GC interaction
6829
6830#define DUK_ALLOC_RAW(heap,size) \
6831 ((heap)->alloc_func((heap)->heap_udata, (size)))
6832
6833#define DUK_REALLOC_RAW(heap,ptr,newsize) \
6834 ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
6835
6836#define DUK_FREE_RAW(heap,ptr) \
6837 ((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
6838
6839/*
6840 * Memory calls: relative to heap, GC interaction, but no error throwing.
6841 *
6842 * XXX: Currently a mark-and-sweep triggered by memory allocation will run
6843 * using the heap->heap_thread. This thread is also used for running
6844 * mark-and-sweep finalization; this is not ideal because it breaks the
6845 * isolation between multiple global environments.
6846 *
6847 * Notes:
6848 *
6849 * - DUK_FREE() is required to ignore NULL and any other possible return
6850 * value of a zero-sized alloc/realloc (same as ANSI C free()).
6851 *
6852 * - There is no DUK_REALLOC_ZEROED because we don't assume to know the
6853 * old size. Caller must zero the reallocated memory.
6854 *
6855 * - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
6856 * by an allocation failure might invalidate the original 'ptr', thus
6857 * causing a realloc retry to use an invalid pointer. Example: we're
6858 * reallocating the value stack and a finalizer resizes the same value
6859 * stack during mark-and-sweep. The indirect variant requests for the
6860 * current location of the pointer being reallocated using a callback
6861 * right before every realloc attempt; this circuitous approach is used
6862 * to avoid strict aliasing issues in a more straightforward indirect
6863 * pointer (void **) approach. Note: the pointer in the storage
6864 * location is read but is NOT updated; the caller must do that.
6867/* callback for indirect reallocs, request for current pointer */
6868typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
6869
6870#define DUK_ALLOC(heap,size) duk_heap_mem_alloc((heap), (size))
6871#define DUK_ALLOC_ZEROED(heap,size) duk_heap_mem_alloc_zeroed((heap), (size))
6872#define DUK_REALLOC(heap,ptr,newsize) duk_heap_mem_realloc((heap), (ptr), (newsize))
6873#define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
6874#define DUK_FREE(heap,ptr) duk_heap_mem_free((heap), (ptr))
6875
6876/*
6877 * Memory constants
6878 */
6879
6880#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT 5 /* Retry allocation after mark-and-sweep for this
6881 * many times. A single mark-and-sweep round is
6882 * not guaranteed to free all unreferenced memory
6883 * because of finalization (in fact, ANY number of
6884 * rounds is strictly not enough).
6885 */
6886
6887#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT 3 /* Starting from this round, use emergency mode
6888 * for mark-and-sweep.
6889 */
6891/*
6892 * Debugger support
6894
6895/* Maximum number of breakpoints. Only breakpoints that are set are
6896 * consulted so increasing this has no performance impact.
6898#define DUK_HEAP_MAX_BREAKPOINTS 16
6900/* Opcode interval for a Date-based status/peek rate limit check. Only
6901 * relevant when debugger is attached. Requesting a timestamp may be a
6902 * slow operation on some platforms so this shouldn't be too low. On the
6903 * other hand a high value makes Duktape react to a pause request slowly.
6904 */
6905#define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000
6906
6907/* Milliseconds between status notify and transport peeks. */
6908#define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200
6909
6910/* Step types */
6911#define DUK_STEP_TYPE_NONE 0
6912#define DUK_STEP_TYPE_INTO 1
6913#define DUK_STEP_TYPE_OVER 2
6914#define DUK_STEP_TYPE_OUT 3
6915
6916struct duk_breakpoint {
6918 duk_uint32_t line;
6919};
6920
6921#if defined(DUK_USE_DEBUGGER_SUPPORT)
6922#define DUK_HEAP_IS_DEBUGGER_ATTACHED(heap) ((heap)->dbg_read_cb != NULL)
6923#define DUK_HEAP_CLEAR_STEP_STATE(heap) do { \
6924 (heap)->dbg_step_type = DUK_STEP_TYPE_NONE; \
6925 (heap)->dbg_step_thread = NULL; \
6926 (heap)->dbg_step_csindex = 0; \
6927 (heap)->dbg_step_startline = 0; \
6928 } while (0)
6929#define DUK_HEAP_SET_PAUSED(heap) do { \
6930 (heap)->dbg_paused = 1; \
6931 (heap)->dbg_state_dirty = 1; \
6932 DUK_HEAP_CLEAR_STEP_STATE((heap)); \
6933 } while (0)
6934#define DUK_HEAP_CLEAR_PAUSED(heap) do { \
6935 (heap)->dbg_paused = 0; \
6936 (heap)->dbg_state_dirty = 1; \
6937 DUK_HEAP_CLEAR_STEP_STATE((heap)); \
6938 } while (0)
6939#define DUK_HEAP_IS_PAUSED(heap) ((heap)->dbg_paused)
6940#endif /* DUK_USE_DEBUGGER_SUPPORT */
6941
6942/*
6943 * String cache should ideally be at duk_hthread level, but that would
6944 * cause string finalization to slow down relative to the number of
6945 * threads; string finalization must check the string cache for "weak"
6946 * references to the string being finalized to avoid dead pointers.
6948 * Thus, string caches are now at the heap level now.
6953 duk_uint32_t bidx;
6954 duk_uint32_t cidx;
6955};
6956
6957/*
6958 * Longjmp state, contains the information needed to perform a longjmp.
6959 * Longjmp related values are written to value1, value2, and iserror.
6960 */
6961
6962struct duk_ljstate {
6963 duk_jmpbuf *jmpbuf_ptr; /* current setjmp() catchpoint */
6964 duk_small_uint_t type; /* longjmp type */
6965 duk_bool_t iserror; /* isError flag for yield */
6966 duk_tval value1; /* 1st related value (type specific) */
6967 duk_tval value2; /* 2nd related value (type specific) */
6968};
6969
6971 * Stringtable entry for fixed size stringtable
6975#if defined(DUK_USE_HEAPPTR16)
6976 /* A 16-bit listlen makes sense with 16-bit heap pointers: there
6977 * won't be space for 64k strings anyway.
6978 */
6979 duk_uint16_t listlen; /* if 0, 'str16' used, if > 0, 'strlist16' used */
6980 union {
6981 duk_uint16_t strlist16;
6982 duk_uint16_t str16;
6983 } u;
6984#else
6985 duk_size_t listlen; /* if 0, 'str' used, if > 0, 'strlist' used */
6986 union {
6989 } u;
6990#endif
6991};
6992
6994 * Main heap structure
6995 */
6996
6997struct duk_heap {
6999
7000 /* Allocator functions. */
7004
7005 /* Heap udata, used for allocator functions but also for other heap
7006 * level callbacks like pointer compression, etc.
7007 */
7008 void *heap_udata;
7010 /* Precomputed pointers when using 16-bit heap pointer packing. */
7011#if defined(DUK_USE_HEAPPTR16)
7012 duk_uint16_t heapptr_null16;
7013 duk_uint16_t heapptr_deleted16;
7014#endif
7015
7016 /* Fatal error handling, called e.g. when a longjmp() is needed but
7017 * lj.jmpbuf_ptr is NULL. fatal_func must never return; it's not
7018 * declared as "noreturn" because doing that for typedefs is a bit
7019 * challenging portability-wise.
7020 */
7022
7023 /* allocated heap objects */
7026 /* work list for objects whose refcounts are zero but which have not been
7027 * "finalized"; avoids recursive C calls when refcounts go to zero in a
7028 * chain of objects.
7029 */
7030#if defined(DUK_USE_REFERENCE_COUNTING)
7033#endif
7034
7035#if defined(DUK_USE_MARK_AND_SWEEP)
7036 /* mark-and-sweep control */
7037#if defined(DUK_USE_VOLUNTARY_GC)
7039#endif
7042 /* mark-and-sweep flags automatically active (used for critical sections) */
7045 /* work list for objects to be finalized (by mark-and-sweep) */
7047#endif
7048
7049 /* longjmp state */
7052 /* marker for detecting internal "double faults", see duk_error_throw.c */
7055 /* heap thread, used internally and for finalization */
7058 /* current thread */
7059 duk_hthread *curr_thread; /* currently running thread */
7060
7061 /* heap level "stash" object (e.g., various reachability roots) */
7063
7064 /* duk_handle_call / duk_handle_safe_call recursion depth limiting */
7067
7068 /* mix-in value for computing string hashes; should be reasonably unpredictable */
7069 duk_uint32_t hash_seed;
7070
7071 /* rnd_state for duk_util_tinyrandom.c */
7072 duk_uint32_t rnd_state;
7073
7074 /* For manual debugging: instruction count based on executor and
7075 * interrupt counter book-keeping. Inspect debug logs to see how
7076 * they match up.
7077 */
7078#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
7079 duk_int_t inst_count_exec;
7080 duk_int_t inst_count_interrupt;
7081#endif
7082
7083 /* debugger */
7084
7085#if defined(DUK_USE_DEBUGGER_SUPPORT)
7086 /* callbacks and udata; dbg_read_cb != NULL is used to indicate attached state */
7087 duk_debug_read_function dbg_read_cb; /* required, NULL implies detached */
7088 duk_debug_write_function dbg_write_cb; /* required */
7089 duk_debug_peek_function dbg_peek_cb;
7090 duk_debug_read_flush_function dbg_read_flush_cb;
7091 duk_debug_write_flush_function dbg_write_flush_cb;
7092 duk_debug_request_function dbg_request_cb;
7093 duk_debug_detached_function dbg_detached_cb;
7094 void *dbg_udata;
7095
7096 /* debugger state, only relevant when attached */
7097 duk_bool_t dbg_processing; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
7098 duk_bool_t dbg_paused; /* currently paused: talk with debug client until step/resume */
7099 duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */
7100 duk_bool_t dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
7101 duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */
7102 duk_small_uint_t dbg_step_type; /* step type: none, step into, step over, step out */
7103 duk_hthread *dbg_step_thread; /* borrowed; NULL if no step state (NULLed in unwind) */
7104 duk_size_t dbg_step_csindex; /* callstack index */
7105 duk_uint32_t dbg_step_startline; /* starting line number */
7106 duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS]; /* breakpoints: [0,breakpoint_count[ gc reachable */
7107 duk_small_uint_t dbg_breakpoint_count;
7108 duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1]; /* currently active breakpoints: NULL term, borrowed pointers */
7109 /* XXX: make active breakpoints actual copies instead of pointers? */
7110
7111 /* These are for rate limiting Status notifications and transport peeking. */
7112 duk_uint32_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */
7113 duk_uint32_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */
7114 duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */
7115
7116 /* Used to support single-byte stream lookahead. */
7117 duk_bool_t dbg_have_next_byte;
7118 duk_uint8_t dbg_next_byte;
7119#endif
7120
7121 /* string intern table (weak refs) */
7122#if defined(DUK_USE_STRTAB_PROBE)
7123#if defined(DUK_USE_HEAPPTR16)
7124 duk_uint16_t *strtable16;
7125#else
7127#endif
7128 duk_uint32_t st_size; /* alloc size in elements */
7129 duk_uint32_t st_used; /* used elements (includes DELETED) */
7130#endif
7131
7132 /* XXX: static alloc is OK until separate chaining stringtable
7133 * resizing is implemented.
7134 */
7135#if defined(DUK_USE_STRTAB_CHAIN)
7137#endif
7138
7139 /* string access cache (codepoint offset -> byte offset) for fast string
7140 * character looping; 'weak' reference which needs special handling in GC.
7141 */
7143
7144 /* built-in strings */
7145#if defined(DUK_USE_ROM_STRINGS)
7146 /* No field needed when strings are in ROM. */
7147#else
7148#if defined(DUK_USE_HEAPPTR16)
7149 duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
7150#else
7152#endif
7153#endif
7154};
7155
7156/*
7157 * Prototypes
7158 */
7159
7162 duk_realloc_function realloc_func,
7163 duk_free_function free_func,
7164 void *heap_udata,
7165 duk_fatal_function fatal_func);
7171
7173#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
7175#endif
7176#if defined(DUK_USE_INTERRUPT_COUNTER)
7177DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
7178#endif
7179
7180#if 0 /*unused*/
7181DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7182#endif
7183DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7184DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
7185#if 0 /*unused*/
7186DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val);
7187#endif
7190#if defined(DUK_USE_REFERENCE_COUNTING)
7192#endif
7193#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
7195#endif
7197#if defined(DUK_USE_DEBUG)
7198DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap);
7199#endif
7200
7201
7204
7205#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
7207DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
7208DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
7209#endif
7210
7213DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
7215DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
7216
7217#ifdef DUK_USE_REFERENCE_COUNTING
7218#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
7219DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
7220#endif
7221#if 0 /* unused */
7222DUK_INTERNAL_DECL void duk_tval_incref_allownull(duk_tval *tv);
7223#endif
7225#if 0 /* unused */
7226DUK_INTERNAL_DECL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv);
7227#endif
7228#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
7229DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
7230#endif
7231#if 0 /* unused */
7232DUK_INTERNAL_DECL void duk_heaphdr_incref_allownull(duk_heaphdr *h);
7233#endif
7238#else
7239/* no refcounting */
7240#endif
7242#if defined(DUK_USE_MARK_AND_SWEEP)
7244#endif
7245
7246DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
7248#endif /* DUK_HEAP_H_INCLUDED */
7249#ifndef DUK_DEBUGGER_H_INCLUDED
7250#define DUK_DEBUGGER_H_INCLUDED
7252/* Debugger protocol version is defined in the public API header. */
7254/* Initial bytes for markers. */
7255#define DUK_DBG_IB_EOM 0x00
7256#define DUK_DBG_IB_REQUEST 0x01
7257#define DUK_DBG_IB_REPLY 0x02
7258#define DUK_DBG_IB_ERROR 0x03
7259#define DUK_DBG_IB_NOTIFY 0x04
7261/* Other initial bytes. */
7262#define DUK_DBG_IB_INT4 0x10
7263#define DUK_DBG_IB_STR4 0x11
7264#define DUK_DBG_IB_STR2 0x12
7265#define DUK_DBG_IB_BUF4 0x13
7266#define DUK_DBG_IB_BUF2 0x14
7267#define DUK_DBG_IB_UNUSED 0x15
7268#define DUK_DBG_IB_UNDEFINED 0x16
7269#define DUK_DBG_IB_NULL 0x17
7270#define DUK_DBG_IB_TRUE 0x18
7271#define DUK_DBG_IB_FALSE 0x19
7272#define DUK_DBG_IB_NUMBER 0x1a
7273#define DUK_DBG_IB_OBJECT 0x1b
7274#define DUK_DBG_IB_POINTER 0x1c
7275#define DUK_DBG_IB_LIGHTFUNC 0x1d
7276#define DUK_DBG_IB_HEAPPTR 0x1e
7277/* The short string/integer initial bytes starting from 0x60 don't have
7278 * defines now.
7281/* Error codes. */
7282#define DUK_DBG_ERR_UNKNOWN 0x00
7283#define DUK_DBG_ERR_UNSUPPORTED 0x01
7284#define DUK_DBG_ERR_TOOMANY 0x02
7285#define DUK_DBG_ERR_NOTFOUND 0x03
7286#define DUK_DBG_ERR_APPLICATION 0x04
7288/* Commands and notifys initiated by Duktape. */
7289#define DUK_DBG_CMD_STATUS 0x01
7290#define DUK_DBG_CMD_PRINT 0x02
7291#define DUK_DBG_CMD_ALERT 0x03
7292#define DUK_DBG_CMD_LOG 0x04
7293#define DUK_DBG_CMD_THROW 0x05
7294#define DUK_DBG_CMD_DETACHING 0x06
7295#define DUK_DBG_CMD_APPNOTIFY 0x07
7297/* Commands initiated by debug client. */
7298#define DUK_DBG_CMD_BASICINFO 0x10
7299#define DUK_DBG_CMD_TRIGGERSTATUS 0x11
7300#define DUK_DBG_CMD_PAUSE 0x12
7301#define DUK_DBG_CMD_RESUME 0x13
7302#define DUK_DBG_CMD_STEPINTO 0x14
7303#define DUK_DBG_CMD_STEPOVER 0x15
7304#define DUK_DBG_CMD_STEPOUT 0x16
7305#define DUK_DBG_CMD_LISTBREAK 0x17
7306#define DUK_DBG_CMD_ADDBREAK 0x18
7307#define DUK_DBG_CMD_DELBREAK 0x19
7308#define DUK_DBG_CMD_GETVAR 0x1a
7309#define DUK_DBG_CMD_PUTVAR 0x1b
7310#define DUK_DBG_CMD_GETCALLSTACK 0x1c
7311#define DUK_DBG_CMD_GETLOCALS 0x1d
7312#define DUK_DBG_CMD_EVAL 0x1e
7313#define DUK_DBG_CMD_DETACH 0x1f
7314#define DUK_DBG_CMD_DUMPHEAP 0x20
7315#define DUK_DBG_CMD_GETBYTECODE 0x21
7316#define DUK_DBG_CMD_APPREQUEST 0x22
7317#define DUK_DBG_CMD_GETHEAPOBJINFO 0x23
7318#define DUK_DBG_CMD_GETOBJPROPDESC 0x24
7319#define DUK_DBG_CMD_GETOBJPROPDESCRANGE 0x25
7320
7321/* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
7322 * The remaining flags are specific to the debugger.
7323 */
7324#define DUK_DBG_PROPFLAG_INTERNAL (1 << 8)
7325
7326#if defined(DUK_USE_DEBUGGER_SUPPORT)
7327DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
7328
7329DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
7330DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
7331
7332DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
7333DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
7334
7335DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
7336DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
7337DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
7338DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
7339/* XXX: exposed duk_debug_read_pointer */
7340/* XXX: exposed duk_debug_read_buffer */
7341/* XXX: exposed duk_debug_read_hbuffer */
7342#if 0
7343DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
7344#endif
7345#if defined(DUK_USE_DEBUGGER_INSPECT)
7346DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
7347#endif
7348DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
7349
7350DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
7351DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
7352DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
7353DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
7354#if defined(DUK_USE_DEBUGGER_INSPECT)
7355DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
7356#endif
7357DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
7358DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
7359DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
7360DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
7361DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
7362DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
7363DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
7364DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
7365DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
7366#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
7367DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
7368#endif
7369DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
7370DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
7371#if 0 /* unused */
7372DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
7373#endif
7374DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
7375DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
7376DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
7377DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
7378
7379DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
7380DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
7381#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
7382DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
7383#endif
7384
7385DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
7386DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
7387
7388DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
7389DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
7390#endif
7391
7392#endif /* DUK_DEBUGGER_H_INCLUDED */
7393/*
7394 * Debugging macros, DUK_DPRINT() and its variants in particular.
7395 *
7396 * DUK_DPRINT() allows formatted debug prints, and supports standard
7397 * and Duktape specific formatters. See duk_debug_vsnprintf.c for details.
7398 *
7399 * DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
7400 * for technical reasons. They are concretely used to hide 'x' from the
7401 * compiler when the corresponding log level is disabled. This allows
7402 * clean builds on non-C99 compilers, at the cost of more verbose code.
7403 * Examples:
7404 *
7405 * DUK_D(DUK_DPRINT("foo"));
7406 * DUK_DD(DUK_DDPRINT("foo"));
7407 * DUK_DDD(DUK_DDDPRINT("foo"));
7408 *
7409 * This approach is preferable to the old "double parentheses" hack because
7410 * double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
7411 * no longer be added transparently without going through globals, which
7412 * works poorly with threading.
7413 */
7414
7415#ifndef DUK_DEBUG_H_INCLUDED
7416#define DUK_DEBUG_H_INCLUDED
7417
7418#ifdef DUK_USE_DEBUG
7419
7420#if defined(DUK_USE_DPRINT)
7421#define DUK_D(x) x
7422#else
7423#define DUK_D(x) do { } while (0) /* omit */
7424#endif
7425
7426#if defined(DUK_USE_DDPRINT)
7427#define DUK_DD(x) x
7428#else
7429#define DUK_DD(x) do { } while (0) /* omit */
7430#endif
7431
7432#if defined(DUK_USE_DDDPRINT)
7433#define DUK_DDD(x) x
7434#else
7435#define DUK_DDD(x) do { } while (0) /* omit */
7436#endif
7437
7438/*
7439 * Exposed debug macros: debugging enabled
7440 */
7441
7442#define DUK_LEVEL_DEBUG 1
7443#define DUK_LEVEL_DDEBUG 2
7444#define DUK_LEVEL_DDDEBUG 3
7445
7446#ifdef DUK_USE_VARIADIC_MACROS
7447
7448/* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
7449 * possible compile time, but waste some space with shared function names.
7450 */
7451#define DUK__DEBUG_LOG(lev,...) duk_debug_log((duk_small_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
7452
7453#define DUK_DPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
7454
7455#ifdef DUK_USE_DDPRINT
7456#define DUK_DDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
7457#else
7458#define DUK_DDPRINT(...)
7459#endif
7460
7461#ifdef DUK_USE_DDDPRINT
7462#define DUK_DDDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
7463#else
7464#define DUK_DDDPRINT(...)
7465#endif
7466
7467#else /* DUK_USE_VARIADIC_MACROS */
7468
7469#define DUK__DEBUG_STASH(lev) \
7470 (void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
7471 duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7472 (void) DUK_SNPRINTF(duk_debug_line_stash, DUK_DEBUG_STASH_SIZE, "%ld", (long) DUK_LINE_MACRO), \
7473 duk_debug_line_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7474 (void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
7475 duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7476 (void) (duk_debug_level_stash = (lev))
7477
7478/* Without variadic macros resort to comma expression trickery to handle debug
7479 * prints. This generates a lot of harmless warnings. These hacks are not
7480 * needed normally because DUK_D() and friends will hide the entire debug log
7481 * statement from the compiler.
7482 */
7483
7484#ifdef DUK_USE_DPRINT
7485#define DUK_DPRINT DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log /* args go here in parens */
7486#else
7487#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
7488#endif
7489
7490#ifdef DUK_USE_DDPRINT
7491#define DUK_DDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log /* args go here in parens */
7492#else
7493#define DUK_DDPRINT 0 && /* args */
7494#endif
7496#ifdef DUK_USE_DDDPRINT
7497#define DUK_DDDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log /* args go here in parens */
7498#else
7499#define DUK_DDDPRINT 0 && /* args */
7500#endif
7501
7502#endif /* DUK_USE_VARIADIC_MACROS */
7503
7504#else /* DUK_USE_DEBUG */
7505
7506/*
7507 * Exposed debug macros: debugging disabled
7510#define DUK_D(x) do { } while (0) /* omit */
7511#define DUK_DD(x) do { } while (0) /* omit */
7512#define DUK_DDD(x) do { } while (0) /* omit */
7513
7514#ifdef DUK_USE_VARIADIC_MACROS
7515
7516#define DUK_DPRINT(...)
7517#define DUK_DDPRINT(...)
7518#define DUK_DDDPRINT(...)
7519
7520#else /* DUK_USE_VARIADIC_MACROS */
7521
7522#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
7523#define DUK_DDPRINT 0 && /* args */
7524#define DUK_DDDPRINT 0 && /* args */
7525
7526#endif /* DUK_USE_VARIADIC_MACROS */
7527
7528#endif /* DUK_USE_DEBUG */
7529
7530/*
7531 * Structs
7532 */
7533
7534#ifdef DUK_USE_DEBUG
7535struct duk_fixedbuffer {
7536 duk_uint8_t *buffer;
7537 duk_size_t length;
7538 duk_size_t offset;
7539 duk_bool_t truncated;
7540};
7541#endif
7542
7543/*
7544 * Prototypes
7545 */
7546
7547#ifdef DUK_USE_DEBUG
7548DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
7549#if 0 /*unused*/
7550DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
7551#endif
7552DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
7553
7554#ifdef DUK_USE_VARIADIC_MACROS
7555DUK_INTERNAL_DECL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
7556#else /* DUK_USE_VARIADIC_MACROS */
7557/* parameter passing, not thread safe */
7558#define DUK_DEBUG_STASH_SIZE 128
7559#if !defined(DUK_SINGLE_FILE)
7560DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
7561DUK_INTERNAL_DECL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
7562DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
7563DUK_INTERNAL_DECL duk_small_int_t duk_debug_level_stash;
7564#endif
7565DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
7566#endif /* DUK_USE_VARIADIC_MACROS */
7567
7568DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
7569DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
7570DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
7571DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
7572DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
7573DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
7574
7575#endif /* DUK_USE_DEBUG */
7576
7577#endif /* DUK_DEBUG_H_INCLUDED */
7579 * Error handling macros, assertion macro, error codes.
7580 *
7581 * There are three level of 'errors':
7582 *
7583 * 1. Ordinary errors, relative to a thread, cause a longjmp, catchable.
7584 * 2. Fatal errors, relative to a heap, cause fatal handler to be called.
7585 * 3. Panic errors, unrelated to a heap and cause a process exit.
7586 *
7587 * Panics are used by the default fatal error handler and by debug code
7588 * such as assertions. By providing a proper fatal error handler, user
7589 * code can avoid panics in non-debug builds.
7590 */
7591
7592#ifndef DUK_ERROR_H_INCLUDED
7593#define DUK_ERROR_H_INCLUDED
7594
7595/*
7596 * Error codes: defined in duktape.h
7597 *
7598 * Error codes are used as a shorthand to throw exceptions from inside
7599 * the implementation. The appropriate Ecmascript object is constructed
7600 * based on the code. Ecmascript code throws objects directly. The error
7601 * codes are defined in the public API header because they are also used
7602 * by calling code.
7603 */
7604
7605/*
7606 * Normal error
7607 *
7608 * Normal error is thrown with a longjmp() through the current setjmp()
7609 * catchpoint record in the duk_heap. The 'curr_thread' of the duk_heap
7610 * identifies the throwing thread.
7611 *
7612 * Error formatting is usually unnecessary. The error macros provide a
7613 * zero argument version (no formatting) and separate macros for small
7614 * argument counts. Variadic macros are not used to avoid portability
7615 * issues and avoid the need for stash-based workarounds when they're not
7616 * available. Vararg calls are avoided for non-formatted error calls
7617 * because vararg call sites are larger than normal, and there are a lot
7618 * of call sites with no formatting.
7619 *
7620 * Note that special formatting provided by debug macros is NOT available.
7621 *
7622 * The _RAW variants allow the caller to specify file and line. This makes
7623 * it easier to write checked calls which want to use the call site of the
7624 * checked function, not the error macro call inside the checked function.
7625 */
7626
7627#if defined(DUK_USE_VERBOSE_ERRORS)
7629/* Because there are quite many call sites, pack error code (require at most
7630 * 8-bit) into a single argument.
7631 */
7632#define DUK_ERROR(thr,err,msg) do { \
7633 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7634 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7635 duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
7636 } while (0)
7637#define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
7638 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7639 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7640 duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
7641 } while (0)
7642
7643#define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
7644 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7645 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7646 duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
7647 } while (0)
7648#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
7649 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7650 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7651 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
7652 } while (0)
7653
7654#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
7655 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7656 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7657 duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
7658 } while (0)
7659#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
7660 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7661 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7662 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
7663 } while (0)
7664
7665#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
7666 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7667 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7668 duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
7669 } while (0)
7670#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
7671 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7672 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7673 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
7674 } while (0)
7675
7676#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
7677 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7678 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7679 duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
7680 } while (0)
7681#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
7682 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7683 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7684 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
7685 } while (0)
7686
7687#else /* DUK_USE_VERBOSE_ERRORS */
7688
7689#define DUK_ERROR(thr,err,msg) duk_err_handle_error((thr), (err))
7690#define DUK_ERROR_RAW(thr,file,line,err,msg) duk_err_handle_error((thr), (err))
7691
7692#define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
7693#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7694
7695#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
7696#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7697
7698#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
7699#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7700
7701#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
7702#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7703
7704#endif /* DUK_USE_VERBOSE_ERRORS */
7705
7706/*
7707 * Fatal error
7708 *
7709 * There are no fatal error macros at the moment. There are so few call
7710 * sites that the fatal error handler is called directly.
7711 */
7712
7713/*
7714 * Panic error
7715 *
7716 * Panic errors are not relative to either a heap or a thread, and cause
7717 * DUK_PANIC() macro to be invoked. Unless a user provides DUK_USE_PANIC_HANDLER,
7718 * DUK_PANIC() calls a helper which prints out the error and causes a process
7719 * exit.
7720 *
7721 * The user can override the macro to provide custom handling. A macro is
7722 * used to allow the user to have inline panic handling if desired (without
7723 * causing a potentially risky function call).
7724 *
7725 * Panics are only used in debug code such as assertions, and by the default
7726 * fatal error handler.
7727 */
7728
7729#if defined(DUK_USE_PANIC_HANDLER)
7730/* already defined, good */
7731#define DUK_PANIC(code,msg) DUK_USE_PANIC_HANDLER((code),(msg))
7732#else
7733#define DUK_PANIC(code,msg) duk_default_panic_handler((code),(msg))
7734#endif /* DUK_USE_PANIC_HANDLER */
7735
7736/*
7737 * Assert macro: failure causes panic.
7738 */
7739
7740#if defined(DUK_USE_ASSERTIONS)
7741
7742/* the message should be a compile time constant without formatting (less risk);
7743 * we don't care about assertion text size because they're not used in production
7744 * builds.
7745 */
7746#define DUK_ASSERT(x) do { \
7747 if (!(x)) { \
7748 DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
7749 "assertion failed: " #x \
7750 " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
7751 } \
7752 } while (0)
7753
7754/* Assertion compatible inside a comma expression, evaluates to void.
7755 * Currently not compatible with DUK_USE_PANIC_HANDLER() which may have
7756 * a statement block.
7758#if defined(DUK_USE_PANIC_HANDLER)
7759/* XXX: resolve macro definition issue or call through a helper function? */
7760#define DUK_ASSERT_EXPR(x) ((void) 0)
7761#else
7762#define DUK_ASSERT_EXPR(x) \
7763 ((void) ((x) ? 0 : (DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
7764 "assertion failed: " #x \
7765 " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
7766#endif
7767
7768#else /* DUK_USE_ASSERTIONS */
7769
7770#define DUK_ASSERT(x) do { /* assertion omitted */ } while (0)
7771
7772#define DUK_ASSERT_EXPR(x) ((void) 0)
7773
7774#endif /* DUK_USE_ASSERTIONS */
7775
7776/* this variant is used when an assert would generate a compile warning by
7777 * being always true (e.g. >= 0 comparison for an unsigned value
7778 */
7779#define DUK_ASSERT_DISABLE(x) do { /* assertion disabled */ } while (0)
7782 * Assertion helpers
7783 */
7785#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
7786#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) do { \
7787 DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
7788 } while (0)
7789#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) do { \
7790 if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
7791 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
7792 } \
7793 } while (0)
7794#else
7795#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) /* no refcount check */
7796#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) /* no refcount check */
7797#endif
7798
7799#define DUK_ASSERT_TOP(ctx,n) DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
7800
7801#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
7802#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) do { \
7803 duk_double_union duk__assert_tmp_du; \
7804 duk__assert_tmp_du.d = (dval); \
7805 DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
7806 } while (0)
7807#else
7808#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) /* nop */
7809#endif
7810
7812 * Helper for valstack space
7813 *
7814 * Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
7815 * required for its own use, and any child calls which are not (a) Duktape API calls
7816 * or (b) Duktape calls which involve extending the valstack (e.g. getter call).
7817 */
7818
7819#define DUK_VALSTACK_ASSERT_EXTRA 5 /* this is added to checks to allow for Duktape
7820 * API calls in addition to function's own use
7821 */
7822#if defined(DUK_USE_ASSERTIONS)
7823#define DUK_ASSERT_VALSTACK_SPACE(thr,n) do { \
7824 DUK_ASSERT((thr) != NULL); \
7825 DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
7826 } while (0)
7827#else
7828#define DUK_ASSERT_VALSTACK_SPACE(thr,n) /* no valstack space check */
7829#endif
7830
7831/*
7832 * Error throwing helpers
7833 *
7834 * The goal is to provide verbose and configurable error messages. Call
7835 * sites should be clean in source code and compile to a small footprint.
7836 * Small footprint is also useful for performance because small cold paths
7837 * reduce code cache pressure. Adding macros here only makes sense if there
7838 * are enough call sites to get concrete benefits.
7840
7841#if defined(DUK_USE_VERBOSE_ERRORS)
7842/* Verbose errors with key/value summaries (non-paranoid) or without key/value
7843 * summaries (paranoid, for some security sensitive environments), the paranoid
7844 * vs. non-paranoid distinction affects only a few specific errors.
7846#if defined(DUK_USE_PARANOID_ERRORS)
7847#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7848 duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index), (expectname)); \
7849 } while (0)
7850#else /* DUK_USE_PARANOID_ERRORS */
7851#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7852 duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index), (expectname)); \
7853 } while (0)
7854#endif /* DUK_USE_PARANOID_ERRORS */
7855
7856#define DUK_ERROR_UNIMPLEMENTED(thr,msg) do { \
7857 DUK_ERROR((thr), DUK_ERR_UNIMPLEMENTED_ERROR, (msg)); \
7858 } while (0)
7859#define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr) do { \
7860 duk_err_unimplemented_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7861 } while (0)
7862#define DUK_ERROR_UNSUPPORTED(thr,msg) do { \
7863 DUK_ERROR((thr), DUK_ERR_UNSUPPORTED_ERROR, (msg)); \
7864 } while (0)
7865#if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
7866#define DUK_ERROR_UNSUPPORTED_DEFMSG(thr) do { \
7867 duk_err_unsupported_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7868 } while (0)
7869#endif
7870#define DUK_ERROR_INTERNAL(thr,msg) do { \
7871 duk_err_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7872 } while (0)
7873#define DUK_ERROR_INTERNAL_DEFMSG(thr) do { \
7874 duk_err_internal_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7875 } while (0)
7876#define DUK_ERROR_ALLOC(thr,msg) do { \
7877 duk_err_alloc((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7878 } while (0)
7879#define DUK_ERROR_ALLOC_DEFMSG(thr) do { \
7880 DUK_ERROR_ALLOC((thr), DUK_STR_ALLOC_FAILED); \
7881 } while (0)
7882/* DUK_ERR_ASSERTION_ERROR: no macros needed */
7883#define DUK_ERROR_API_INDEX(thr,index) do { \
7884 duk_err_api_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index)); \
7885 } while (0)
7886#define DUK_ERROR_API(thr,msg) do { \
7887 duk_err_api((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7888 } while (0)
7889/* DUK_ERR_UNCAUGHT_ERROR: no macros needed */
7890/* DUK_ERR_ERROR: no macros needed */
7891/* DUK_ERR_EVAL: no macros needed */
7892#define DUK_ERROR_RANGE(thr,msg) do { \
7893 duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7894 } while (0)
7895/* DUK_ERR_REFERENCE_ERROR: no macros needed */
7896#define DUK_ERROR_SYNTAX(thr,msg) do { \
7897 DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
7898 } while (0)
7899#define DUK_ERROR_TYPE(thr,msg) do { \
7900 DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
7901 } while (0)
7902/* DUK_ERR_URI_ERROR: no macros needed */
7903#else /* DUK_USE_VERBOSE_ERRORS */
7904/* Non-verbose errors for low memory targets: no file, line, or message. */
7905
7906#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7907 duk_err_type((thr)); \
7908 } while (0)
7909
7910#define DUK_ERROR_UNIMPLEMENTED(thr,msg) do { \
7911 duk_err_unimplemented((thr)); \
7912 } while (0)
7913#define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr) do { \
7914 duk_err_unimplemented((thr)); \
7915 } while (0)
7916#define DUK_ERROR_UNSUPPORTED(thr,msg) do { \
7917 duk_err_unsupported((thr)); \
7918 } while (0)
7919#define DUK_ERROR_UNSUPPORTED_DEFMSG(thr) do { \
7920 duk_err_unsupported((thr)); \
7921 } while (0)
7922#define DUK_ERROR_INTERNAL(thr,msg) do { \
7923 duk_err_internal((thr)); \
7924 } while (0)
7925#define DUK_ERROR_INTERNAL_DEFMSG(thr) do { \
7926 duk_err_internal((thr)); \
7927 } while (0)
7928#define DUK_ERROR_ALLOC(thr,msg) do { \
7929 duk_err_alloc((thr)); \
7930 } while (0)
7931#define DUK_ERROR_ALLOC_DEFMSG(thr) do { \
7932 duk_err_alloc((thr)); \
7933 } while (0)
7934#define DUK_ERROR_API_INDEX(thr,index) do { \
7935 duk_err_api((thr)); \
7936 } while (0)
7937#define DUK_ERROR_API(thr,msg) do { \
7938 duk_err_api((thr)); \
7939 } while (0)
7940#define DUK_ERROR_RANGE(thr,msg) do { \
7941 duk_err_range((thr)); \
7942 } while (0)
7943#define DUK_ERROR_SYNTAX(thr,msg) do { \
7944 duk_err_syntax((thr)); \
7945 } while (0)
7946#define DUK_ERROR_TYPE(thr,msg) do { \
7947 duk_err_type((thr)); \
7948 } while (0)
7949#endif /* DUK_USE_VERBOSE_ERRORS */
7950
7952 * Prototypes
7953 */
7954
7955#if defined(DUK_USE_VERBOSE_ERRORS)
7956DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));
7957DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...));
7958#else /* DUK_USE_VERBOSE_ERRORS */
7960#endif /* DUK_USE_VERBOSE_ERRORS */
7961
7962#if defined(DUK_USE_VERBOSE_ERRORS)
7963DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));
7964#else
7966#endif
7970#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
7971DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline);
7972#endif
7973#if defined(DUK_USE_AUGMENT_ERROR_THROW)
7975#endif
7976
7977#if defined(DUK_USE_VERBOSE_ERRORS)
7978#if defined(DUK_USE_PARANOID_ERRORS)
7979DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name));
7980#else
7981DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name));
7982#endif
7983DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index));
7984DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7985DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7986DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
7987#if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
7988DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unsupported_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
7989#endif
7990DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
7991DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7992DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7993#else /* DUK_VERBOSE_ERRORS */
7995DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
7996DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
7998DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unimplemented(duk_hthread *thr));
7999DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unsupported(duk_hthread *thr));
8002#endif /* DUK_VERBOSE_ERRORS */
8003
8007
8008#if !defined(DUK_USE_PANIC_HANDLER)
8010#endif
8015
8016#endif /* DUK_ERROR_H_INCLUDED */
8017/*
8018 * Unicode helpers
8019 */
8020
8021#ifndef DUK_UNICODE_H_INCLUDED
8022#define DUK_UNICODE_H_INCLUDED
8025 * UTF-8 / XUTF-8 / CESU-8 constants
8026 */
8027
8028#define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */
8029#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
8030#define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */
8031#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
8032
8033/*
8034 * Useful Unicode codepoints
8035 *
8036 * Integer constants must be signed to avoid unexpected coercions
8037 * in comparisons.
8040#define DUK_UNICODE_CP_ZWNJ 0x200cL /* zero-width non-joiner */
8041#define DUK_UNICODE_CP_ZWJ 0x200dL /* zero-width joiner */
8042#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER 0xfffdL /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
8045 * ASCII character constants
8047 * C character literals like 'x' have a platform specific value and do
8048 * not match ASCII (UTF-8) values on e.g. EBCDIC platforms. So, use
8049 * these (admittedly awkward) constants instead. These constants must
8050 * also have signed values to avoid unexpected coercions in comparisons.
8052 * http://en.wikipedia.org/wiki/ASCII
8055#define DUK_ASC_NUL 0x00
8056#define DUK_ASC_SOH 0x01
8057#define DUK_ASC_STX 0x02
8058#define DUK_ASC_ETX 0x03
8059#define DUK_ASC_EOT 0x04
8060#define DUK_ASC_ENQ 0x05
8061#define DUK_ASC_ACK 0x06
8062#define DUK_ASC_BEL 0x07
8063#define DUK_ASC_BS 0x08
8064#define DUK_ASC_HT 0x09
8065#define DUK_ASC_LF 0x0a
8066#define DUK_ASC_VT 0x0b
8067#define DUK_ASC_FF 0x0c
8068#define DUK_ASC_CR 0x0d
8069#define DUK_ASC_SO 0x0e
8070#define DUK_ASC_SI 0x0f
8071#define DUK_ASC_DLE 0x10
8072#define DUK_ASC_DC1 0x11
8073#define DUK_ASC_DC2 0x12
8074#define DUK_ASC_DC3 0x13
8075#define DUK_ASC_DC4 0x14
8076#define DUK_ASC_NAK 0x15
8077#define DUK_ASC_SYN 0x16
8078#define DUK_ASC_ETB 0x17
8079#define DUK_ASC_CAN 0x18
8080#define DUK_ASC_EM 0x19
8081#define DUK_ASC_SUB 0x1a
8082#define DUK_ASC_ESC 0x1b
8083#define DUK_ASC_FS 0x1c
8084#define DUK_ASC_GS 0x1d
8085#define DUK_ASC_RS 0x1e
8086#define DUK_ASC_US 0x1f
8087#define DUK_ASC_SPACE 0x20
8088#define DUK_ASC_EXCLAMATION 0x21
8089#define DUK_ASC_DOUBLEQUOTE 0x22
8090#define DUK_ASC_HASH 0x23
8091#define DUK_ASC_DOLLAR 0x24
8092#define DUK_ASC_PERCENT 0x25
8093#define DUK_ASC_AMP 0x26
8094#define DUK_ASC_SINGLEQUOTE 0x27
8095#define DUK_ASC_LPAREN 0x28
8096#define DUK_ASC_RPAREN 0x29
8097#define DUK_ASC_STAR 0x2a
8098#define DUK_ASC_PLUS 0x2b
8099#define DUK_ASC_COMMA 0x2c
8100#define DUK_ASC_MINUS 0x2d
8101#define DUK_ASC_PERIOD 0x2e
8102#define DUK_ASC_SLASH 0x2f
8103#define DUK_ASC_0 0x30
8104#define DUK_ASC_1 0x31
8105#define DUK_ASC_2 0x32
8106#define DUK_ASC_3 0x33
8107#define DUK_ASC_4 0x34
8108#define DUK_ASC_5 0x35
8109#define DUK_ASC_6 0x36
8110#define DUK_ASC_7 0x37
8111#define DUK_ASC_8 0x38
8112#define DUK_ASC_9 0x39
8113#define DUK_ASC_COLON 0x3a
8114#define DUK_ASC_SEMICOLON 0x3b
8115#define DUK_ASC_LANGLE 0x3c
8116#define DUK_ASC_EQUALS 0x3d
8117#define DUK_ASC_RANGLE 0x3e
8118#define DUK_ASC_QUESTION 0x3f
8119#define DUK_ASC_ATSIGN 0x40
8120#define DUK_ASC_UC_A 0x41
8121#define DUK_ASC_UC_B 0x42
8122#define DUK_ASC_UC_C 0x43
8123#define DUK_ASC_UC_D 0x44
8124#define DUK_ASC_UC_E 0x45
8125#define DUK_ASC_UC_F 0x46
8126#define DUK_ASC_UC_G 0x47
8127#define DUK_ASC_UC_H 0x48
8128#define DUK_ASC_UC_I 0x49
8129#define DUK_ASC_UC_J 0x4a
8130#define DUK_ASC_UC_K 0x4b
8131#define DUK_ASC_UC_L 0x4c
8132#define DUK_ASC_UC_M 0x4d
8133#define DUK_ASC_UC_N 0x4e
8134#define DUK_ASC_UC_O 0x4f
8135#define DUK_ASC_UC_P 0x50
8136#define DUK_ASC_UC_Q 0x51
8137#define DUK_ASC_UC_R 0x52
8138#define DUK_ASC_UC_S 0x53
8139#define DUK_ASC_UC_T 0x54
8140#define DUK_ASC_UC_U 0x55
8141#define DUK_ASC_UC_V 0x56
8142#define DUK_ASC_UC_W 0x57
8143#define DUK_ASC_UC_X 0x58
8144#define DUK_ASC_UC_Y 0x59
8145#define DUK_ASC_UC_Z 0x5a
8146#define DUK_ASC_LBRACKET 0x5b
8147#define DUK_ASC_BACKSLASH 0x5c
8148#define DUK_ASC_RBRACKET 0x5d
8149#define DUK_ASC_CARET 0x5e
8150#define DUK_ASC_UNDERSCORE 0x5f
8151#define DUK_ASC_GRAVE 0x60
8152#define DUK_ASC_LC_A 0x61
8153#define DUK_ASC_LC_B 0x62
8154#define DUK_ASC_LC_C 0x63
8155#define DUK_ASC_LC_D 0x64
8156#define DUK_ASC_LC_E 0x65
8157#define DUK_ASC_LC_F 0x66
8158#define DUK_ASC_LC_G 0x67
8159#define DUK_ASC_LC_H 0x68
8160#define DUK_ASC_LC_I 0x69
8161#define DUK_ASC_LC_J 0x6a
8162#define DUK_ASC_LC_K 0x6b
8163#define DUK_ASC_LC_L 0x6c
8164#define DUK_ASC_LC_M 0x6d
8165#define DUK_ASC_LC_N 0x6e
8166#define DUK_ASC_LC_O 0x6f
8167#define DUK_ASC_LC_P 0x70
8168#define DUK_ASC_LC_Q 0x71
8169#define DUK_ASC_LC_R 0x72
8170#define DUK_ASC_LC_S 0x73
8171#define DUK_ASC_LC_T 0x74
8172#define DUK_ASC_LC_U 0x75
8173#define DUK_ASC_LC_V 0x76
8174#define DUK_ASC_LC_W 0x77
8175#define DUK_ASC_LC_X 0x78
8176#define DUK_ASC_LC_Y 0x79
8177#define DUK_ASC_LC_Z 0x7a
8178#define DUK_ASC_LCURLY 0x7b
8179#define DUK_ASC_PIPE 0x7c
8180#define DUK_ASC_RCURLY 0x7d
8181#define DUK_ASC_TILDE 0x7e
8182#define DUK_ASC_DEL 0x7f
8183
8184/*
8185 * Unicode tables
8186 */
8187
8188#ifdef DUK_USE_SOURCE_NONBMP
8189/*
8190 * Automatically generated by extract_chars.py, do not edit!
8191 */
8192
8193extern const duk_uint8_t duk_unicode_ids_noa[791];
8194#else
8195/*
8196 * Automatically generated by extract_chars.py, do not edit!
8197 */
8198
8199extern const duk_uint8_t duk_unicode_ids_noabmp[611];
8200#endif
8201
8202#ifdef DUK_USE_SOURCE_NONBMP
8203/*
8204 * Automatically generated by extract_chars.py, do not edit!
8205 */
8206
8207extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
8208#else
8209/*
8210 * Automatically generated by extract_chars.py, do not edit!
8211 */
8212
8213extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
8214#endif
8215
8216#ifdef DUK_USE_SOURCE_NONBMP
8217/*
8218 * Automatically generated by extract_chars.py, do not edit!
8219 */
8220
8221extern const duk_uint8_t duk_unicode_idp_m_ids_noa[397];
8222#else
8223/*
8224 * Automatically generated by extract_chars.py, do not edit!
8225 */
8226
8227extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348];
8228#endif
8229
8230/*
8231 * Automatically generated by extract_caseconv.py, do not edit!
8232 */
8233
8234extern const duk_uint8_t duk_unicode_caseconv_uc[1288];
8235extern const duk_uint8_t duk_unicode_caseconv_lc[616];
8236
8237#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
8238/*
8239 * Automatically generated by extract_caseconv.py, do not edit!
8240 */
8241
8242extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
8243#endif
8244
8245/*
8246 * Extern
8247 */
8248
8249/* duk_unicode_support.c */
8250#if !defined(DUK_SINGLE_FILE)
8251DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
8253DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
8258DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
8259#endif /* !DUK_SINGLE_FILE */
8260
8261/*
8262 * Prototypes
8263 */
8264
8266#if defined(DUK_USE_ASSERTIONS)
8267DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
8268#endif
8271DUK_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);
8272DUK_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);
8282
8283#endif /* DUK_UNICODE_H_INCLUDED */
8285 * Defines for JSON, especially duk_bi_json.c.
8286 */
8288#ifndef DUK_JSON_H_INCLUDED
8289#define DUK_JSON_H_INCLUDED
8291/* Encoding/decoding flags */
8292#define DUK_JSON_FLAG_ASCII_ONLY (1 << 0) /* escape any non-ASCII characters */
8293#define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1 << 1) /* avoid key quotes when key is an ASCII Identifier */
8294#define DUK_JSON_FLAG_EXT_CUSTOM (1 << 2) /* extended types: custom encoding */
8295#define DUK_JSON_FLAG_EXT_COMPATIBLE (1 << 3) /* extended types: compatible encoding */
8297/* How much stack to require on entry to object/array encode */
8298#define DUK_JSON_ENC_REQSTACK 32
8300/* How much stack to require on entry to object/array decode */
8301#define DUK_JSON_DEC_REQSTACK 32
8303/* How large a loop detection stack to use */
8304#define DUK_JSON_ENC_LOOPARRAY 64
8306/* Encoding state. Heap object references are all borrowed. */
8307typedef struct {
8308 duk_hthread *thr;
8309 duk_bufwriter_ctx bw; /* output bufwriter */
8310 duk_hobject *h_replacer; /* replacer function */
8311 duk_hstring *h_gap; /* gap (if empty string, NULL) */
8312 duk_idx_t idx_proplist; /* explicit PropertyList */
8313 duk_idx_t idx_loop; /* valstack index of loop detection object */
8314 duk_small_uint_t flags;
8315 duk_small_uint_t flag_ascii_only;
8316 duk_small_uint_t flag_avoid_key_quotes;
8317#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8318 duk_small_uint_t flag_ext_custom;
8319 duk_small_uint_t flag_ext_compatible;
8320 duk_small_uint_t flag_ext_custom_or_compatible;
8321#endif
8322 duk_int_t recursion_depth;
8323 duk_int_t recursion_limit;
8324 duk_uint_t mask_for_undefined; /* type bit mask: types which certainly produce 'undefined' */
8325#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8326 duk_small_uint_t stridx_custom_undefined;
8327 duk_small_uint_t stridx_custom_nan;
8328 duk_small_uint_t stridx_custom_neginf;
8329 duk_small_uint_t stridx_custom_posinf;
8330 duk_small_uint_t stridx_custom_function;
8331#endif
8332 duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY]; /* indexed by recursion_depth */
8334
8335typedef struct {
8336 duk_hthread *thr;
8337 const duk_uint8_t *p;
8338 const duk_uint8_t *p_start;
8339 const duk_uint8_t *p_end;
8340 duk_idx_t idx_reviver;
8341 duk_small_uint_t flags;
8342#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8343 duk_small_uint_t flag_ext_custom;
8344 duk_small_uint_t flag_ext_compatible;
8345 duk_small_uint_t flag_ext_custom_or_compatible;
8346#endif
8347 duk_int_t recursion_depth;
8348 duk_int_t recursion_limit;
8351#endif /* DUK_JSON_H_INCLUDED */
8352/*
8353 * Ecmascript execution, support primitives.
8356#ifndef DUK_JS_H_INCLUDED
8357#define DUK_JS_H_INCLUDED
8358
8359/* Flags for call handling. */
8360#define DUK_CALL_FLAG_IGNORE_RECLIMIT (1 << 0) /* duk_handle_call_xxx: call ignores C recursion limit (for errhandler calls) */
8361#define DUK_CALL_FLAG_CONSTRUCTOR_CALL (1 << 1) /* duk_handle_call_xxx: constructor call (i.e. called as 'new Foo()') */
8362#define DUK_CALL_FLAG_IS_RESUME (1 << 2) /* duk_handle_ecma_call_setup: setup for a resume() */
8363#define DUK_CALL_FLAG_IS_TAILCALL (1 << 3) /* duk_handle_ecma_call_setup: setup for a tail call */
8364#define DUK_CALL_FLAG_DIRECT_EVAL (1 << 4) /* call is a direct eval call */
8365
8366/* Flags for duk_js_equals_helper(). */
8367#define DUK_EQUALS_FLAG_SAMEVALUE (1 << 0) /* use SameValue instead of non-strict equality */
8368#define DUK_EQUALS_FLAG_STRICT (1 << 1) /* use strict equality instead of non-strict equality */
8369
8370/* Flags for duk_js_compare_helper(). */
8371#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST (1 << 0) /* eval left argument first */
8372#define DUK_COMPARE_FLAG_NEGATE (1 << 1) /* negate result */
8373
8374/* conversions, coercions, comparison, etc */
8385DUK_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);
8388DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
8389#endif
8395#define duk_js_equals(thr,tv_x,tv_y) \
8396 duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
8397#define duk_js_strict_equals(tv_x,tv_y) \
8398 duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
8399#define duk_js_samevalue(tv_x,tv_y) \
8400 duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
8401
8402/* E5 Sections 11.8.1, 11.8.5; x < y */
8403#define duk_js_lessthan(thr,tv_x,tv_y) \
8404 duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
8405
8406/* E5 Sections 11.8.2, 11.8.5; x > y --> y < x */
8407#define duk_js_greaterthan(thr,tv_x,tv_y) \
8408 duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
8409
8410/* E5 Sections 11.8.3, 11.8.5; x <= y --> not (x > y) --> not (y < x) */
8411#define duk_js_lessthanorequal(thr,tv_x,tv_y) \
8412 duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
8413
8414/* E5 Sections 11.8.4, 11.8.5; x >= y --> not (x < y) */
8415#define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
8416 duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
8417
8418/* identifiers and environment handling */
8419#if 0 /*unused*/
8420DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
8421#endif
8426#if 0 /*unused*/
8427DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
8428#endif
8436 duk_hcompiledfunction *fun_temp,
8437 duk_hobject *outer_var_env,
8438 duk_hobject *outer_lex_env,
8439 duk_bool_t add_auto_proto);
8440
8441/* call handling */
8446
8447/* bytecode execution */
8449
8450#endif /* DUK_JS_H_INCLUDED */
8451#ifndef DUK_NUMCONV_H_INCLUDED
8452#define DUK_NUMCONV_H_INCLUDED
8453
8454/*
8455 * Number-to-string conversion. The semantics of these is very tightly
8456 * bound with the Ecmascript semantics required for call sites.
8457 */
8458
8459/* Output a specified number of digits instead of using the shortest
8460 * form. Used for toPrecision() and toFixed().
8462#define DUK_N2S_FLAG_FIXED_FORMAT (1 << 0)
8463
8464/* Force exponential format. Used for toExponential(). */
8465#define DUK_N2S_FLAG_FORCE_EXP (1 << 1)
8466
8467/* If number would need zero padding (for whole number part), use
8468 * exponential format instead. E.g. if input number is 12300, 3
8469 * digits are generated ("123"), output "1.23e+4" instead of "12300".
8470 * Used for toPrecision().
8472#define DUK_N2S_FLAG_NO_ZERO_PAD (1 << 2)
8473
8474/* Digit count indicates number of fractions (i.e. an absolute
8475 * digit index instead of a relative one). Used together with
8476 * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
8478#define DUK_N2S_FLAG_FRACTION_DIGITS (1 << 3)
8479
8481 * String-to-number conversion
8482 */
8484/* Maximum exponent value when parsing numbers. This is not strictly
8485 * compliant as there should be no upper limit, but as we parse the
8486 * exponent without a bigint, impose some limit.
8487 */
8488#define DUK_S2N_MAX_EXPONENT 1000000000
8490/* Trim white space (= allow leading and trailing whitespace) */
8491#define DUK_S2N_FLAG_TRIM_WHITE (1 << 0)
8493/* Allow exponent */
8494#define DUK_S2N_FLAG_ALLOW_EXP (1 << 1)
8496/* Allow trailing garbage (e.g. treat "123foo" as "123) */
8497#define DUK_S2N_FLAG_ALLOW_GARBAGE (1 << 2)
8499/* Allow leading plus sign */
8500#define DUK_S2N_FLAG_ALLOW_PLUS (1 << 3)
8502/* Allow leading minus sign */
8503#define DUK_S2N_FLAG_ALLOW_MINUS (1 << 4)
8505/* Allow 'Infinity' */
8506#define DUK_S2N_FLAG_ALLOW_INF (1 << 5)
8507
8508/* Allow fraction part */
8509#define DUK_S2N_FLAG_ALLOW_FRAC (1 << 6)
8510
8511/* Allow naked fraction (e.g. ".123") */
8512#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC (1 << 7)
8513
8514/* Allow empty fraction (e.g. "123.") */
8515#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC (1 << 8)
8516
8517/* Allow empty string to be interpreted as 0 */
8518#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO (1 << 9)
8519
8520/* Allow leading zeroes (e.g. "0123" -> "123") */
8521#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO (1 << 10)
8522
8523/* Allow automatic detection of hex base ("0x" or "0X" prefix),
8524 * overrides radix argument and forces integer mode.
8525 */
8526#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT (1 << 11)
8527
8528/* Allow automatic detection of octal base, overrides radix
8529 * argument and forces integer mode.
8531#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT (1 << 12)
8532
8533/*
8534 * Prototypes
8535 */
8536
8539
8540#endif /* DUK_NUMCONV_H_INCLUDED */
8541/*
8542 * Prototypes for built-in functions not automatically covered by the
8543 * header declarations emitted by genbuiltins.py.
8545
8546#ifndef DUK_BUILTIN_PROTOS_H_INCLUDED
8547#define DUK_BUILTIN_PROTOS_H_INCLUDED
8548
8549/* Buffer size needed for duk_bi_date_format_timeval().
8550 * Accurate value is 32 + 1 for NUL termination:
8551 * >>> len('+123456-01-23T12:34:56.123+12:34')
8552 * 32
8553 * Include additional space to be safe.
8554 */
8555#define DUK_BI_DATE_ISO8601_BUFSIZE 48
8556
8557/* Maximum length of CommonJS module identifier to resolve. Length includes
8558 * both current module ID, requested (possibly relative) module ID, and a
8559 * slash in between.
8560 */
8561#define DUK_BI_COMMONJS_MODULE_ID_LIMIT 256
8562
8563/* Helpers exposed for internal use */
8566DUK_INTERNAL_DECL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf);
8571/* Built-in providers */
8572#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
8573DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx);
8574#endif
8575#if defined(DUK_USE_DATE_NOW_TIME)
8577#endif
8578#if defined(DUK_USE_DATE_NOW_WINDOWS)
8579DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
8580#endif
8581#if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
8583#endif
8584#if defined(DUK_USE_DATE_TZO_WINDOWS)
8585DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
8586#endif
8587#if defined(DUK_USE_DATE_PRS_STRPTIME)
8588DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str);
8589#endif
8590#if defined(DUK_USE_DATE_PRS_GETDATE)
8591DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str);
8592#endif
8593#if defined(DUK_USE_DATE_FMT_STRFTIME)
8594DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
8595#endif
8596
8599 duk_idx_t idx_value,
8600 duk_idx_t idx_reviver,
8601 duk_small_uint_t flags);
8604 duk_idx_t idx_value,
8605 duk_idx_t idx_replacer,
8606 duk_idx_t idx_space,
8607 duk_small_uint_t flags);
8608
8609#endif /* DUK_BUILTIN_PROTOS_H_INCLUDED */
8610/*
8611 * Selftest code
8612 */
8613
8614#ifndef DUK_SELFTEST_H_INCLUDED
8615#define DUK_SELFTEST_H_INCLUDED
8616
8617#if defined(DUK_USE_SELF_TESTS)
8618DUK_INTERNAL_DECL void duk_selftest_run_tests(void);
8619#endif
8620
8621#endif /* DUK_SELFTEST_H_INCLUDED */
8622
8623#endif /* DUK_INTERNAL_H_INCLUDED */
8624/*
8625 * Replacements for missing platform functions.
8627 * Unlike the originals, fpclassify() and signbit() replacements don't
8628 * work on any floating point types, only doubles. The C typing here
8629 * mimics the standard prototypes.
8630 */
8631
8632/* include removed: duk_internal.h */
8633
8634#if defined(DUK_USE_COMPUTED_NAN)
8635DUK_INTERNAL double duk_computed_nan;
8636#endif
8637
8638#if defined(DUK_USE_COMPUTED_INFINITY)
8639DUK_INTERNAL double duk_computed_infinity;
8640#endif
8641
8642#if defined(DUK_USE_REPL_FPCLASSIFY)
8643DUK_INTERNAL int duk_repl_fpclassify(double x) {
8645 duk_uint_fast16_t expt;
8646 duk_small_int_t mzero;
8647
8648 u.d = x;
8649 expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
8650 if (expt > 0x0000UL && expt < 0x7ff0UL) {
8651 /* expt values [0x001,0x7fe] = normal */
8652 return DUK_FP_NORMAL;
8653 }
8654
8655 mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
8656 if (expt == 0x0000UL) {
8657 /* expt 0x000 is zero/subnormal */
8658 if (mzero) {
8659 return DUK_FP_ZERO;
8660 } else {
8661 return DUK_FP_SUBNORMAL;
8662 }
8663 } else {
8664 /* expt 0xfff is infinite/nan */
8665 if (mzero) {
8667 } else {
8668 return DUK_FP_NAN;
8669 }
8670 }
8671}
8672#endif
8673
8674#if defined(DUK_USE_REPL_SIGNBIT)
8675DUK_INTERNAL int duk_repl_signbit(double x) {
8677 u.d = x;
8678 return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
8679}
8680#endif
8681
8682#if defined(DUK_USE_REPL_ISFINITE)
8683DUK_INTERNAL int duk_repl_isfinite(double x) {
8684 int c = DUK_FPCLASSIFY(x);
8685 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
8686 return 0;
8687 } else {
8688 return 1;
8689 }
8690}
8691#endif
8692
8693#if defined(DUK_USE_REPL_ISNAN)
8694DUK_INTERNAL int duk_repl_isnan(double x) {
8695 int c = DUK_FPCLASSIFY(x);
8696 return (c == DUK_FP_NAN);
8697}
8698#endif
8699
8700#if defined(DUK_USE_REPL_ISINF)
8702 int c = DUK_FPCLASSIFY(x);
8703 return (c == DUK_FP_INFINITE);
8705#endif
8707 * Shared error message strings
8708 *
8709 * To minimize code footprint, try to share error messages inside Duktape
8710 * code. Modern compilers will do this automatically anyway, this is mostly
8711 * for older compilers.
8714/* include removed: duk_internal.h */
8716/* Mostly API and built-in method related */
8717DUK_INTERNAL const char *duk_str_internal_error = "internal error";
8718DUK_INTERNAL const char *duk_str_invalid_count = "invalid count";
8719DUK_INTERNAL const char *duk_str_invalid_call_args = "invalid call args";
8720DUK_INTERNAL const char *duk_str_not_constructable = "not constructable";
8721DUK_INTERNAL const char *duk_str_not_callable = "not callable";
8722DUK_INTERNAL const char *duk_str_not_extensible = "not extensible";
8723DUK_INTERNAL const char *duk_str_not_writable = "not writable";
8724DUK_INTERNAL const char *duk_str_not_configurable = "not configurable";
8726DUK_INTERNAL const char *duk_str_invalid_context = "invalid context";
8727DUK_INTERNAL const char *duk_str_push_beyond_alloc_stack = "attempt to push beyond currently allocated stack";
8728DUK_INTERNAL const char *duk_str_not_buffer = "not buffer"; /* still in use with verbose messages */
8729DUK_INTERNAL const char *duk_str_unexpected_type = "unexpected type";
8730DUK_INTERNAL const char *duk_str_defaultvalue_coerce_failed = "[[DefaultValue]] coerce failed";
8731DUK_INTERNAL const char *duk_str_number_outside_range = "number outside range";
8732DUK_INTERNAL const char *duk_str_not_object_coercible = "not object coercible";
8733DUK_INTERNAL const char *duk_str_string_too_long = "string too long";
8734DUK_INTERNAL const char *duk_str_buffer_too_long = "buffer too long";
8735DUK_INTERNAL const char *duk_str_sprintf_too_long = "sprintf message too long";
8736DUK_INTERNAL const char *duk_str_alloc_failed = "alloc failed";
8737DUK_INTERNAL const char *duk_str_pop_too_many = "attempt to pop too many entries";
8738DUK_INTERNAL const char *duk_str_wrong_buffer_type = "wrong buffer type";
8739DUK_INTERNAL const char *duk_str_encode_failed = "encode failed";
8740DUK_INTERNAL const char *duk_str_decode_failed = "decode failed";
8741DUK_INTERNAL const char *duk_str_no_sourcecode = "no sourcecode";
8742DUK_INTERNAL const char *duk_str_concat_result_too_long = "concat result too long";
8743DUK_INTERNAL const char *duk_str_unimplemented = "unimplemented";
8744DUK_INTERNAL const char *duk_str_unsupported = "unsupported";
8745DUK_INTERNAL const char *duk_str_array_length_over_2g = "array length over 2G";
8747/* JSON */
8749DUK_INTERNAL const char *duk_str_fmt_invalid_json = "invalid json (at offset %ld)";
8750DUK_INTERNAL const char *duk_str_jsondec_reclimit = "json decode recursion limit";
8751DUK_INTERNAL const char *duk_str_jsonenc_reclimit = "json encode recursion limit";
8752DUK_INTERNAL const char *duk_str_cyclic_input = "cyclic input";
8754/* Object property access */
8755DUK_INTERNAL const char *duk_str_proxy_revoked = "proxy revoked";
8756DUK_INTERNAL const char *duk_str_invalid_base = "invalid base value";
8757DUK_INTERNAL const char *duk_str_strict_caller_read = "attempt to read strict 'caller'";
8758DUK_INTERNAL const char *duk_str_proxy_rejected = "proxy rejected";
8759DUK_INTERNAL const char *duk_str_invalid_array_length = "invalid array length";
8760DUK_INTERNAL const char *duk_str_array_length_write_failed = "array length write failed";
8761DUK_INTERNAL const char *duk_str_array_length_not_writable = "array length non-writable";
8762DUK_INTERNAL const char *duk_str_setter_undefined = "setter undefined";
8763DUK_INTERNAL const char *duk_str_redefine_virt_prop = "attempt to redefine virtual property";
8764DUK_INTERNAL const char *duk_str_invalid_descriptor = "invalid descriptor";
8765DUK_INTERNAL const char *duk_str_property_is_virtual = "property is virtual";
8767/* Compiler */
8768DUK_INTERNAL const char *duk_str_parse_error = "parse error";
8769DUK_INTERNAL const char *duk_str_duplicate_label = "duplicate label";
8770DUK_INTERNAL const char *duk_str_invalid_label = "invalid label";
8771DUK_INTERNAL const char *duk_str_invalid_array_literal = "invalid array literal";
8772DUK_INTERNAL const char *duk_str_invalid_object_literal = "invalid object literal";
8773DUK_INTERNAL const char *duk_str_invalid_var_declaration = "invalid variable declaration";
8774DUK_INTERNAL const char *duk_str_cannot_delete_identifier = "cannot delete identifier";
8775DUK_INTERNAL const char *duk_str_invalid_expression = "invalid expression";
8776DUK_INTERNAL const char *duk_str_invalid_lvalue = "invalid lvalue";
8777DUK_INTERNAL const char *duk_str_expected_identifier = "expected identifier";
8778DUK_INTERNAL const char *duk_str_empty_expr_not_allowed = "empty expression not allowed";
8779DUK_INTERNAL const char *duk_str_invalid_for = "invalid for statement";
8780DUK_INTERNAL const char *duk_str_invalid_switch = "invalid switch statement";
8781DUK_INTERNAL const char *duk_str_invalid_break_cont_label = "invalid break/continue label";
8782DUK_INTERNAL const char *duk_str_invalid_return = "invalid return";
8783DUK_INTERNAL const char *duk_str_invalid_try = "invalid try";
8784DUK_INTERNAL const char *duk_str_invalid_throw = "invalid throw";
8785DUK_INTERNAL const char *duk_str_with_in_strict_mode = "with in strict mode";
8786DUK_INTERNAL const char *duk_str_func_stmt_not_allowed = "function statement not allowed";
8787DUK_INTERNAL const char *duk_str_unterminated_stmt = "unterminated statement";
8788DUK_INTERNAL const char *duk_str_invalid_arg_name = "invalid argument name";
8789DUK_INTERNAL const char *duk_str_invalid_func_name = "invalid function name";
8790DUK_INTERNAL const char *duk_str_invalid_getset_name = "invalid getter/setter name";
8791DUK_INTERNAL const char *duk_str_func_name_required = "function name required";
8793/* Regexp */
8794DUK_INTERNAL const char *duk_str_invalid_quantifier_no_atom = "quantifier without preceding atom";
8795DUK_INTERNAL const char *duk_str_invalid_quantifier_values = "quantifier values invalid (qmin > qmax)";
8796DUK_INTERNAL const char *duk_str_quantifier_too_many_copies = "quantifier expansion requires too many atom copies";
8797DUK_INTERNAL const char *duk_str_unexpected_closing_paren = "unexpected closing parenthesis";
8798DUK_INTERNAL const char *duk_str_unexpected_end_of_pattern = "unexpected end of pattern";
8799DUK_INTERNAL const char *duk_str_unexpected_regexp_token = "unexpected token in regexp";
8800DUK_INTERNAL const char *duk_str_invalid_regexp_flags = "invalid regexp flags";
8801DUK_INTERNAL const char *duk_str_invalid_backrefs = "invalid backreference(s)";
8802
8803/* Limits */
8804DUK_INTERNAL const char *duk_str_valstack_limit = "valstack limit";
8805DUK_INTERNAL const char *duk_str_callstack_limit = "callstack limit";
8806DUK_INTERNAL const char *duk_str_catchstack_limit = "catchstack limit";
8807DUK_INTERNAL const char *duk_str_prototype_chain_limit = "prototype chain limit";
8808DUK_INTERNAL const char *duk_str_bound_chain_limit = "function call bound chain limit";
8809DUK_INTERNAL const char *duk_str_c_callstack_limit = "C call stack depth limit";
8810DUK_INTERNAL const char *duk_str_compiler_recursion_limit = "compiler recursion limit";
8811DUK_INTERNAL const char *duk_str_bytecode_limit = "bytecode limit";
8812DUK_INTERNAL const char *duk_str_reg_limit = "register limit";
8813DUK_INTERNAL const char *duk_str_temp_limit = "temp limit";
8814DUK_INTERNAL const char *duk_str_const_limit = "const limit";
8815DUK_INTERNAL const char *duk_str_func_limit = "function limit";
8816DUK_INTERNAL const char *duk_str_regexp_compiler_recursion_limit = "regexp compiler recursion limit";
8817DUK_INTERNAL const char *duk_str_regexp_executor_recursion_limit = "regexp executor recursion limit";
8818DUK_INTERNAL const char *duk_str_regexp_executor_step_limit = "regexp step limit";
8819
8820/* Misc */
8821/*
8822 * Debugging macro calls.
8823 */
8824
8825/* include removed: duk_internal.h */
8826
8827#ifdef DUK_USE_DEBUG
8828
8829/*
8830 * Debugging enabled
8831 */
8832
8833#include <stdio.h>
8834#include <stdlib.h>
8835#include <stdarg.h>
8836
8837#define DUK__DEBUG_BUFSIZE DUK_USE_DEBUG_BUFSIZE
8838DUK_LOCAL char duk__debug_buf[DUK__DEBUG_BUFSIZE];
8839
8840DUK_LOCAL const char *duk__get_level_string(duk_small_int_t level) {
8841 switch ((int) level) {
8842 case DUK_LEVEL_DEBUG:
8843 return "D";
8844 case DUK_LEVEL_DDEBUG:
8845 return "DD";
8846 case DUK_LEVEL_DDDEBUG:
8847 return "DDD";
8848 }
8849 return "???";
8850}
8851
8852#ifdef DUK_USE_DPRINT_COLORS
8853
8854/* http://en.wikipedia.org/wiki/ANSI_escape_code */
8855#define DUK__TERM_REVERSE "\x1b[7m"
8856#define DUK__TERM_BRIGHT "\x1b[1m"
8857#define DUK__TERM_RESET "\x1b[0m"
8858#define DUK__TERM_BLUE "\x1b[34m"
8859#define DUK__TERM_RED "\x1b[31m"
8860
8861DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
8862 DUK_UNREF(level);
8863 return (const char *) DUK__TERM_RED;
8864}
8865
8866DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
8867 switch ((int) level) {
8868 case DUK_LEVEL_DEBUG:
8869 return (const char *) (DUK__TERM_RESET DUK__TERM_BRIGHT);
8870 case DUK_LEVEL_DDEBUG:
8871 return (const char *) (DUK__TERM_RESET);
8872 case DUK_LEVEL_DDDEBUG:
8873 return (const char *) (DUK__TERM_RESET DUK__TERM_BLUE);
8874 }
8875 return (const char *) DUK__TERM_RESET;
8876}
8877
8878DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
8879 DUK_UNREF(level);
8880 return (const char *) DUK__TERM_RESET;
8881}
8882
8883#else
8884
8885DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
8886 DUK_UNREF(level);
8887 return (const char *) "";
8888}
8889
8890DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
8891 DUK_UNREF(level);
8892 return (const char *) "";
8893}
8894
8895DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
8896 DUK_UNREF(level);
8897 return (const char *) "";
8898}
8899
8900#endif /* DUK_USE_DPRINT_COLORS */
8901
8902#ifdef DUK_USE_VARIADIC_MACROS
8903
8904DUK_INTERNAL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
8905 va_list ap;
8906
8907 va_start(ap, fmt);
8908
8909 DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
8910 duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
8911
8912 DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%ld (%s):%s %s%s\n",
8913 (const char *) duk__get_term_1(level),
8914 (const char *) duk__get_level_string(level),
8915 (const char *) file,
8916 (long) line,
8917 (const char *) func,
8918 (const char *) duk__get_term_2(level),
8919 (const char *) duk__debug_buf,
8920 (const char *) duk__get_term_3(level));
8922
8923 va_end(ap);
8924}
8925
8926#else /* DUK_USE_VARIADIC_MACROS */
8927
8928DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
8929DUK_INTERNAL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
8930DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
8931DUK_INTERNAL duk_small_int_t duk_debug_level_stash;
8932
8933DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
8934 va_list ap;
8935 duk_small_int_t level = duk_debug_level_stash;
8936
8937 va_start(ap, fmt);
8938
8939 DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
8940 duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
8941
8942 DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%s (%s):%s %s%s\n",
8943 (const char *) duk__get_term_1(level),
8944 (const char *) duk__get_level_string(duk_debug_level_stash),
8945 (const char *) duk_debug_file_stash,
8946 (const char *) duk_debug_line_stash,
8947 (const char *) duk_debug_func_stash,
8948 (const char *) duk__get_term_2(level),
8949 (const char *) duk__debug_buf,
8950 (const char *) duk__get_term_3(level));
8952
8953 va_end(ap);
8954}
8955
8956#endif /* DUK_USE_VARIADIC_MACROS */
8958#else /* DUK_USE_DEBUG */
8959
8960/*
8961 * Debugging disabled
8962 */
8963
8964#endif /* DUK_USE_DEBUG */
8965/*
8966 * Automatically generated by genbuiltins.py, do not edit!
8967 */
8968
8969/* include removed: duk_internal.h */
8970
8971#if defined(DUK_USE_ROM_STRINGS)
8972#error ROM support not enabled, rerun make_dist.py with --rom-support
8973#else /* DUK_USE_ROM_STRINGS */
8974DUK_INTERNAL const duk_uint8_t duk_strings_data[1049] = {
897579,104,209,144,168,105,6,78,182,139,90,122,8,154,140,35,103,35,117,193,73,
89765,52,116,180,104,166,135,52,189,4,98,12,27,178,156,80,211,31,161,115,150,
897764,52,221,109,24,18,68,157,24,38,67,118,36,55,73,119,151,164,140,93,18,117,
8978128,153,201,228,201,205,2,250,8,196,24,232,104,82,146,40,232,193,48,118,
8979168,37,147,212,54,127,113,208,70,32,194,187,68,54,127,113,208,70,32,196,
8980123,68,54,127,113,209,44,12,121,7,208,70,32,194,186,134,207,236,126,219,
8981160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253,159,217,
8982116,17,136,48,190,209,13,159,217,253,151,65,24,131,12,233,86,224,79,236,
8983254,203,160,140,65,134,116,171,112,39,246,223,105,208,70,32,193,140,183,4,
898411,55,92,20,244,141,169,186,50,11,164,109,77,208,208,165,36,79,215,185,13,
8985153,34,110,204,241,32,6,66,84,11,112,200,84,52,157,124,92,242,70,120,45,64,
8986186,17,22,138,38,0,172,140,19,154,84,26,145,0,86,69,17,180,97,34,0,172,132,
898775,144,215,77,221,91,132,5,147,178,156,80,211,30,160,93,9,215,21,115,119,
8988169,49,75,211,138,26,101,205,222,68,157,47,78,40,105,151,55,120,204,156,
8989189,56,161,166,52,157,72,136,138,65,154,232,147,162,4,136,150,81,115,66,
8990208,210,37,96,148,250,134,140,151,39,212,125,255,221,125,73,80,209,146,233,
8991124,93,55,79,15,34,196,230,202,113,160,166,232,157,132,148,128,98,28,46,
8992114,200,6,153,180,96,73,19,74,113,67,76,103,5,36,20,211,70,140,133,67,72,
899349,245,160,235,81,212,52,168,106,39,132,253,111,80,210,161,168,158,5,245,
8994191,96,31,172,15,208,23,226,190,131,232,62,131,232,11,251,127,93,245,223,
899593,251,172,234,27,80,45,3,250,14,140,19,34,65,19,81,132,108,228,97,1,107,
899633,12,32,45,100,136,206,9,12,196,155,134,69,146,100,235,226,231,146,51,194,
899772,218,48,145,4,200,119,89,189,81,49,39,72,147,235,226,233,186,120,121,58,
8998226,167,90,124,93,55,107,71,137,33,68,68,130,64,206,75,189,209,156,144,84,
899944,141,3,8,137,187,178,156,80,211,26,110,242,100,230,146,120,121,8,48,76,6,
900089,26,105,157,65,196,201,213,145,166,153,212,28,76,157,113,75,34,78,62,14,
900138,73,105,228,142,136,178,48,141,152,228,73,150,83,0,148,39,137,75,67,73,
9002214,209,129,36,85,190,206,32,17,6,9,128,141,3,8,130,161,100,235,64,194,24,
900352,41,73,19,189,200,108,201,19,111,181,2,232,66,239,173,37,230,157,244,56,
9004153,4,225,145,27,233,93,22,1,114,62,251,80,69,128,121,247,213,146,228,109,
900579,190,212,17,35,106,125,246,78,164,68,68,111,175,23,217,45,13,33,119,208,
900668,210,38,250,192,61,91,233,80,208,45,25,36,81,190,156,13,26,201,19,239,
9007162,2,214,66,31,125,153,226,64,13,27,236,72,96,130,68,62,251,48,68,196,153,
9008119,217,157,18,56,156,199,161,100,42,26,250,77,36,140,122,40,144,19,34,9,
900924,246,103,139,172,150,56,125,145,1,17,29,44,112,250,183,0,100,24,200,218,
9010140,228,185,130,9,19,237,190,208,73,184,146,35,68,146,163,8,50,178,99,136,
901144,89,196,2,33,70,64,208,196,67,74,226,88,17,105,73,24,186,37,40,38,5,133,
9012161,89,4,183,25,115,119,86,227,118,83,138,26,103,255,223,209,106,141,25,11,
9013244,95,117,56,208,159,250,223,251,250,45,52,13,250,47,186,156,104,79,253,
9014111,253,253,22,144,210,253,23,221,78,52,39,254,187,254,254,139,77,67,75,
9015244,95,117,56,208,159,250,239,251,250,45,22,141,23,209,125,212,227,66,127,
9016235,63,239,69,163,69,247,83,141,9,255,165,12,72,5,16,64,145,10,32,76,71,64,
9017156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,147,32,134,226,
901817,114,33,202,134,129,107,192,202,232,160,180,104,166,135,52,72,40,144,213,
901933,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,98,57,38,116,72,
9020179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,42,228,12,182,
902158,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,94,100,104,
9022228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,46,68,82,24,
9023245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,33,223,20,
902484,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,130,44,96,
9025};
9026#endif /* DUK_USE_ROM_STRINGS */
9027
9028#if defined(DUK_USE_ROM_OBJECTS)
9029#error ROM support not enabled, rerun make_dist.py with --rom-support
9030#else /* DUK_USE_ROM_OBJECTS */
9031/* native functions: 149 */
9182};
9183#if defined(DUK_USE_BUILTIN_INITJS)
9184DUK_INTERNAL const duk_uint8_t duk_initjs_data[204] = {
918540,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
9186105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
9187102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
9188108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
9189109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
9190108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
9191108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
919241,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,79,98,106,
9193101,99,116,46,99,114,101,97,116,101,40,110,117,108,108,41,41,125,41,40,116,
9194104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
9195};
9196#endif /* DUK_USE_BUILTIN_INITJS */
9197#if defined(DUK_USE_DOUBLE_LE)
9198DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9199105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9200152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9201240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
920214,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9203203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9204176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9205148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9206243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
920721,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9208145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9209158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9210228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9211202,3,255,254,32,234,0,0,0,0,0,0,7,195,248,119,0,0,0,0,0,0,3,193,252,57,
9212136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
921340,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9214200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9215119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9216138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9217166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
921819,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
921917,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9220100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
922130,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9222240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9223236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9224135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9225208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9226240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
922782,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9228158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9229135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9230217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
923146,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9232230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9233205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9234230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9235237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9236223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9237119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9238195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9239135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9240128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
924161,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9242123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9243250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9244102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9245105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9246183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
924715,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9248195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9249202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9250131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9251133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9252195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9253121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9254179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9255242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9256148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9257122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9258150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
925948,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,31,
9260255,255,255,255,255,253,239,240,153,178,103,95,173,6,101,88,176,0,64,0,0,0,
92610,0,0,3,168,0,0,0,0,0,0,31,15,241,26,19,233,201,169,38,180,91,242,103,70,
9262147,58,77,75,48,0,0,0,0,0,0,60,31,226,51,162,199,131,82,77,104,183,228,206,
9263141,38,116,154,150,96,0,0,0,0,0,0,120,127,128,15,248,192,70,40,0,0,0,0,0,0,
92640,0,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,248,
9265190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,167,
9266126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,64,
9267247,111,238,56,0,127,199,2,49,72,0,0,0,0,0,0,248,127,180,81,36,4,51,166,
9268248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9269244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9270195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
927159,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
927280,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9273184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
92740,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9275238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9276196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9277171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
927894,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9279101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
928043,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9281113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9282187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9283251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9284151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9285121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9286167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
928743,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9288231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9289211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9290208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
929115,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9292189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9293224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9294233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9295200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
929624,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
92970,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9298240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9299115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9300252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9301111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9302143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9303238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
930460,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9305165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,105,87,20,139,10,191,5,
930664,130,76,156,197,132,1,101,91,91,187,22,176,36,8,28,201,204,160,119,156,
9307253,127,33,23,115,31,193,102,79,142,202,44,15,232,34,182,84,113,95,115,248,
930852,201,241,216,176,139,0,59,148,152,85,239,47,108,254,5,66,76,1,130,212,69,
930979,178,16,148,8,61,58,52,170,49,190,202,6,105,219,251,52,245,7,49,252,22,
9310157,26,85,25,64,205,59,127,102,158,160,246,63,74,7,135,23,53,2,65,48,227,
9311223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,195,
9312211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,15,
931347,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9314136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
931588,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
931621,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9317134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9318191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,0,0,0,0,0,65,226,
931932,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,
932060,56,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9321147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9322252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9323167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9324184,2,172,254,0,0,255,171,8,137,144,0,0,0,0,0,0,0,128,68,73,4,195,187,126,
9325226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
93260,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9327153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9328163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9329245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9330244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9331207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9332186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9333221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9334179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9335208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9336195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9337119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9338115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9339102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
93400,4,43,79,224,139,16,0,0,0,0,0,0,60,15,192,101,253,152,0,5,109,252,17,98,0,
93410,0,0,0,0,7,129,248,12,191,181,0,0,174,63,130,44,64,0,0,0,0,0,0,240,63,1,
9342151,246,224,0,21,215,240,69,136,0,0,0,0,0,0,0,8,0,50,254,228,0,2,188,254,8,
9343177,0,0,0,0,0,0,0,1,0,6,95,221,128,0,87,223,193,22,32,0,0,0,0,0,0,8,32,0,
9344203,251,208,0,11,3,248,34,196,0,0,0,0,0,0,1,4,0,25,127,126,0,1,97,127,4,88,
9345128,0,0,0,0,0,0,32,128,3,47,240,64,0,44,79,224,139,16,0,0,0,0,0,0,8,16,0,
9346101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9347143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9348124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
934939,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9350100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
935140,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
935257,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
935350,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
935495,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9355101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9356150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9357108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9358200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9359186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9360101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9361209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9362181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
936398,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
93642,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9365213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9366155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
936767,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9368203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
936970,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9370229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
937189,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
937210,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9373119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
937429,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9375243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9376};
9377#elif defined(DUK_USE_DOUBLE_BE)
9378DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9379105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9380152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9381240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
938214,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9383203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9384176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9385148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9386243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
938721,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9388145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9389158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9390228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9391202,3,255,254,32,234,3,255,192,0,0,0,0,0,0,119,1,255,192,0,0,0,0,0,0,57,
9392136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
939340,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9394200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9395119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9396138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9397166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
939819,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
939917,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9400100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
940130,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9402240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9403236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9404135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9405208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9406240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
940782,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9408158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9409135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9410217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
941146,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9412230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9413205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9414230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9415237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9416223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9417119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9418195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9419135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9420128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
942161,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9422123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9423250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9424102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9425105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9426183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
942715,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9428195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9429202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9430131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9431133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9432195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9433121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9434179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9435242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9436148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9437122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9438150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
943948,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,15,
9440253,255,255,255,255,255,255,240,153,178,103,95,173,6,101,88,176,0,0,0,0,0,
94410,0,0,67,168,15,255,0,0,0,0,0,0,17,26,19,233,201,169,38,180,91,242,103,70,
9442147,58,77,75,48,31,252,0,0,0,0,0,0,34,51,162,199,131,82,77,104,183,228,206,
9443141,38,116,154,150,96,127,248,0,0,0,0,0,0,0,15,248,192,70,40,0,0,0,0,0,0,0,
94440,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,248,
9445190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,167,
9446126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,64,
9447247,111,238,56,0,127,199,2,49,72,127,248,0,0,0,0,0,0,180,81,36,4,51,166,
9448248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9449244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9450195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
945159,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
945280,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9453184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
94540,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9455238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9456196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9457171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
945894,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9459101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
946043,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9461113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9462187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9463251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9464151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9465121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9466167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
946743,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9468231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9469211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9470208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
947115,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9472189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9473224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9474233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9475200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
947624,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
94770,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9478240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9479115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9480252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9481111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9482143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9483238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
948460,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9485165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,64,5,191,10,139,20,87,
9486105,130,76,156,197,132,4,0,38,187,27,187,85,81,104,28,201,204,160,31,243,
948723,33,127,125,28,247,193,102,79,142,202,44,3,255,113,84,118,82,184,47,232,
948852,201,241,216,176,139,0,255,111,45,236,84,155,148,58,5,66,76,4,0,146,31,
9489181,68,66,209,136,61,58,52,170,49,190,202,1,255,53,4,243,51,249,222,108,22,
9490157,26,85,25,64,63,246,160,158,102,127,59,205,74,7,135,23,53,2,65,48,227,
9491223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,195,
9492211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,15,
949347,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9494136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
949588,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
949621,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9497134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9498191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,32,98,65,128,0,0,
94990,0,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,
950060,56,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9501147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9502252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9503167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9504184,2,172,254,0,0,255,171,8,137,144,128,0,0,0,0,0,0,0,68,73,4,195,187,126,
9505226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
95060,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9507153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9508163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9509245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9510244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9511207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9512186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9513221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9514179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9515208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9516195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9517119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9518115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9519102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
95200,4,43,79,224,139,16,15,252,0,0,0,0,0,0,0,101,253,152,0,5,109,252,17,98,1,
9521255,128,0,0,0,0,0,0,12,191,181,0,0,174,63,130,44,64,63,240,0,0,0,0,0,0,1,
9522151,246,224,0,21,215,240,69,136,8,0,0,0,0,0,0,0,0,50,254,228,0,2,188,254,8,
9523177,1,0,0,0,0,0,0,0,0,6,95,221,128,0,87,223,193,22,32,32,8,0,0,0,0,0,0,0,
9524203,251,208,0,11,3,248,34,196,4,1,0,0,0,0,0,0,0,25,127,126,0,1,97,127,4,88,
9525128,128,32,0,0,0,0,0,0,3,47,240,64,0,44,79,224,139,16,16,8,0,0,0,0,0,0,0,
9526101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9527143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9528124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
952939,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9530100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
953140,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
953257,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
953350,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
953495,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9535101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9536150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9537108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9538200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9539186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9540101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9541209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9542181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
954398,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
95442,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9545213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9546155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
954767,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9548203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
954970,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9550229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
955189,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
955210,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9553119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
955429,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9555243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9556};
9557#elif defined(DUK_USE_DOUBLE_ME)
9558DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9559105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9560152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9561240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
956214,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9563203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9564176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9565148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9566243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
956721,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9568145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9569158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9570228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9571202,3,255,254,32,234,0,0,7,195,248,0,0,0,0,119,0,0,3,193,252,0,0,0,0,57,
9572136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
957340,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9574200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9575119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9576138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9577166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
957819,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
957917,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9580100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
958130,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9582240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9583236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9584135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9585208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9586240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
958782,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9588158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9589135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9590217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
959146,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9592230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9593205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9594230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9595237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9596223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9597119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9598195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9599135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9600128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
960161,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9602123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9603250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9604102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9605105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9606183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
960715,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9608195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9609202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9610131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9611133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9612195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9613121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9614179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9615242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9616148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9617122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9618150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
961948,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,31,
9620255,253,239,255,255,255,255,240,153,178,103,95,173,6,101,88,176,0,0,0,0,0,
962164,0,0,3,168,0,0,31,15,224,0,0,0,17,26,19,233,201,169,38,180,91,242,103,70,
9622147,58,77,75,48,0,0,60,31,192,0,0,0,34,51,162,199,131,82,77,104,183,228,
9623206,141,38,116,154,150,96,0,0,120,127,128,0,0,0,0,15,248,192,70,40,0,0,0,0,
96240,0,0,0,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,
9625248,190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,
9626167,126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,
962764,247,111,238,56,0,127,199,2,49,72,0,0,248,127,0,0,0,0,180,81,36,4,51,166,
9628248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9629244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9630195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
963159,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
963280,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9633184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
96340,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9635238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9636196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9637171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
963894,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9639101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
964043,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9641113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9642187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9643251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9644151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9645121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9646167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
964743,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9648231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9649211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9650208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
965115,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9652189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9653224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9654233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9655200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
965624,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
96570,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9658240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9659115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9660252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9661111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9662143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9663238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
966460,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9665165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,10,191,5,64,105,87,20,
9666139,130,76,156,197,132,11,22,176,36,1,101,91,91,184,28,201,204,160,33,23,
9667115,31,247,156,253,127,65,102,79,142,202,44,4,113,95,115,255,232,34,182,88,
966852,201,241,216,176,139,1,239,47,108,252,59,148,152,86,5,66,76,15,178,16,
9669148,1,130,212,69,72,61,58,52,170,49,190,202,4,245,7,49,254,105,219,251,52,
967022,157,26,85,25,64,158,160,246,63,205,59,127,102,74,7,135,23,53,2,65,48,
9671227,223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,
9672195,211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,
967315,47,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9674136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
967588,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
967621,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9677134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9678191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,0,65,226,32,0,0,0,
96790,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,60,
968056,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9681147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9682252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9683167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9684184,2,172,254,0,0,255,171,8,137,144,0,0,0,128,0,0,0,0,68,73,4,195,187,126,
9685226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
96860,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9687153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9688163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9689245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9690244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9691207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9692186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9693221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9694179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9695208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9696195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9697119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9698115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9699102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
97000,4,43,79,224,139,16,0,0,60,15,192,0,0,0,0,101,253,152,0,5,109,252,17,98,0,
97010,7,129,248,0,0,0,0,12,191,181,0,0,174,63,130,44,64,0,0,240,63,0,0,0,0,1,
9702151,246,224,0,21,215,240,69,136,0,0,0,8,0,0,0,0,0,50,254,228,0,2,188,254,8,
9703177,0,0,0,1,0,0,0,0,0,6,95,221,128,0,87,223,193,22,32,0,0,8,32,0,0,0,0,0,
9704203,251,208,0,11,3,248,34,196,0,0,1,4,0,0,0,0,0,25,127,126,0,1,97,127,4,88,
9705128,0,0,32,128,0,0,0,0,3,47,240,64,0,44,79,224,139,16,0,0,8,16,0,0,0,0,0,
9706101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9707143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9708124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
970939,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9710100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
971140,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
971257,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
971350,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
971495,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9715101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9716150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9717108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9718200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9719186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9720101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9721209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9722181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
972398,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
97242,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9725213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9726155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
972767,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9728203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
972970,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9730229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
973189,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
973210,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9733119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
973429,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9735243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9736};
9737#else
9738#error invalid endianness defines
9739#endif
9740#endif /* DUK_USE_ROM_OBJECTS */
9741/*
9742 * Error, fatal, and panic handling.
9743 */
9745/* include removed: duk_internal.h */
9746
9747#define DUK__ERRFMT_BUFSIZE 256 /* size for formatting buffers */
9748
9749#if defined(DUK_USE_VERBOSE_ERRORS)
9750
9751DUK_INTERNAL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
9752 va_list ap;
9753 char msg[DUK__ERRFMT_BUFSIZE];
9754 va_start(ap, fmt);
9755 (void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
9756 msg[sizeof(msg) - 1] = (char) 0;
9757 duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
9758 va_end(ap); /* dead code, but ensures portability (see Linux man page notes) */
9759}
9760
9761DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
9762 duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
9763}
9764
9765#else /* DUK_USE_VERBOSE_ERRORS */
9766
9771#endif /* DUK_USE_VERBOSE_ERRORS */
9773/*
9774 * Error throwing helpers
9776
9777#if defined(DUK_USE_VERBOSE_ERRORS)
9778#if defined(DUK_USE_PARANOID_ERRORS)
9779DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name) {
9780 DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
9781 expect_name, duk_get_type_name((duk_context *) thr, index), (long) index);
9782}
9783#else
9784DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name) {
9785 DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
9786 expect_name, duk_push_string_readable((duk_context *) thr, index), (long) index);
9787}
9788#endif
9789DUK_INTERNAL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9790 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
9791}
9792DUK_INTERNAL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index) {
9793 DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_API_ERROR, "invalid stack index %ld", (long) (index));
9794}
9795DUK_INTERNAL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9796 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_API_ERROR, message);
9797}
9798DUK_INTERNAL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9800}
9801#if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
9802DUK_INTERNAL void duk_err_unsupported_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9803 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_UNSUPPORTED_ERROR, DUK_STR_UNSUPPORTED);
9804}
9805#endif
9806DUK_INTERNAL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9807 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
9808}
9809DUK_INTERNAL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9810 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, message);
9811}
9812DUK_INTERNAL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9813 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ALLOC_ERROR, message);
9814}
9815#else
9816/* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
9817 * when non-verbose errors are used.
9818 */
9819DUK_INTERNAL void duk_err_type(duk_hthread *thr) {
9821}
9824}
9827}
9828DUK_INTERNAL void duk_err_syntax(duk_hthread *thr) {
9830}
9831DUK_INTERNAL void duk_err_unimplemented(duk_hthread *thr) {
9833}
9834DUK_INTERNAL void duk_err_unsupported(duk_hthread *thr) {
9836}
9839}
9842}
9843#endif
9844
9845/*
9846 * Default fatal error handler
9847 */
9848
9849DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) {
9851#if defined(DUK_USE_FILE_IO)
9852 DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null"));
9854#else
9855 /* omit print */
9856#endif
9857 DUK_D(DUK_DPRINT("default fatal handler called, code %ld -> calling DUK_PANIC()", (long) code));
9858 DUK_PANIC(code, msg);
9860}
9861
9862/*
9863 * Default panic handler
9864 */
9865
9866#if !defined(DUK_USE_PANIC_HANDLER)
9867DUK_INTERNAL void duk_default_panic_handler(duk_errcode_t code, const char *msg) {
9868#if defined(DUK_USE_FILE_IO)
9869 DUK_FPRINTF(DUK_STDERR, "PANIC %ld: %s ("
9870#if defined(DUK_USE_PANIC_ABORT)
9871 "calling abort"
9872#elif defined(DUK_USE_PANIC_EXIT)
9873 "calling exit"
9874#elif defined(DUK_USE_PANIC_SEGFAULT)
9875 "segfaulting on purpose"
9876#else
9877#error no DUK_USE_PANIC_xxx macro defined
9878#endif
9879 ")\n", (long) code, (const char *) (msg ? msg : "null"));
9881#else
9882 /* omit print */
9883 DUK_UNREF(code);
9884 DUK_UNREF(msg);
9885#endif
9886
9887#if defined(DUK_USE_PANIC_ABORT)
9888 DUK_ABORT();
9889#elif defined(DUK_USE_PANIC_EXIT)
9890 DUK_EXIT(-1);
9891#elif defined(DUK_USE_PANIC_SEGFAULT)
9892 /* exit() afterwards to satisfy "noreturn" */
9893 DUK_CAUSE_SEGFAULT(); /* SCANBUILD: "Dereference of null pointer", normal */
9894 DUK_EXIT(-1);
9895#else
9896#error no DUK_USE_PANIC_xxx macro defined
9897#endif
9898
9900}
9901#endif /* !DUK_USE_PANIC_HANDLER */
9902
9903#undef DUK__ERRFMT_BUFSIZE
9904/*
9905 * Various Unicode help functions for character classification predicates,
9906 * case conversion, decoding, etc.
9907 */
9908
9909/* include removed: duk_internal.h */
9910
9911/*
9912 * Fast path tables
9913 */
9914
9915#if defined(DUK_USE_IDCHAR_FASTPATH)
9916DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
9917 /* 0: not IdentifierStart or IdentifierPart
9918 * 1: IdentifierStart and IdentifierPart
9919 * -1: IdentifierPart only
9920 */
9921 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00...0x0f */
9922 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10...0x1f */
9923 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20...0x2f */
9924 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, /* 0x30...0x3f */
9925 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40...0x4f */
9926 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50...0x5f */
9927 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60...0x6f */
9928 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70...0x7f */
9929};
9930#endif
9931
9932/*
9933 * XUTF-8 and CESU-8 encoding/decoding
9934 */
9935
9938 if (x < 0x80UL) {
9939 /* 7 bits */
9940 return 1;
9941 } else if (x < 0x800UL) {
9942 /* 11 bits */
9943 return 2;
9944 } else if (x < 0x10000UL) {
9945 /* 16 bits */
9946 return 3;
9947 } else if (x < 0x200000UL) {
9948 /* 21 bits */
9949 return 4;
9950 } else if (x < 0x4000000UL) {
9951 /* 26 bits */
9952 return 5;
9953 } else if (x < (duk_ucodepoint_t) 0x80000000UL) {
9954 /* 31 bits */
9955 return 6;
9956 } else {
9957 /* 36 bits */
9958 return 7;
9959 }
9960}
9961
9962#if defined(DUK_USE_ASSERTIONS)
9963DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
9965 if (x < 0x80UL) {
9966 /* 7 bits */
9967 return 1;
9968 } else if (x < 0x800UL) {
9969 /* 11 bits */
9970 return 2;
9971 } else if (x < 0x10000UL) {
9972 /* 16 bits */
9973 return 3;
9974 } else {
9975 /* Encoded as surrogate pair, each encoding to 3 bytes for
9976 * 6 bytes total. Codepoints above U+10FFFF encode as 6 bytes
9977 * too, see duk_unicode_encode_cesu8().
9978 */
9979 return 3 + 3;
9980 }
9981}
9982#endif /* DUK_USE_ASSERTIONS */
9983
9984DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
9985 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
9986};
9987
9988/* Encode to extended UTF-8; 'out' must have space for at least
9989 * DUK_UNICODE_MAX_XUTF8_LENGTH bytes. Allows encoding of any
9990 * 32-bit (unsigned) codepoint.
9991 */
9994 duk_small_int_t len;
9995 duk_uint8_t marker;
9997
9999 DUK_ASSERT(len > 0);
10000
10001 marker = duk_unicode_xutf8_markers[len - 1]; /* 64-bit OK because always >= 0 */
10002
10003 i = len;
10004 DUK_ASSERT(i > 0);
10005 do {
10006 i--;
10007 if (i > 0) {
10008 out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
10009 x >>= 6;
10010 } else {
10011 /* Note: masking of 'x' is not necessary because of
10012 * range check and shifting -> no bits overlapping
10013 * the marker should be set.
10014 */
10015 out[0] = (duk_uint8_t) (marker + x);
10016 }
10017 } while (i > 0);
10018
10019 return len;
10020}
10021
10022/* Encode to CESU-8; 'out' must have space for at least
10023 * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
10024 * will encode to garbage but won't overwrite the output buffer.
10025 */
10028 duk_small_int_t len;
10029
10030 if (x < 0x80UL) {
10031 out[0] = (duk_uint8_t) x;
10032 len = 1;
10033 } else if (x < 0x800UL) {
10034 out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
10035 out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
10036 len = 2;
10037 } else if (x < 0x10000UL) {
10038 /* surrogate pairs get encoded here */
10039 out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
10040 out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
10041 out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
10042 len = 3;
10043 } else {
10044 /*
10045 * Unicode codepoints above U+FFFF are encoded as surrogate
10046 * pairs here. This ensures that all CESU-8 codepoints are
10047 * 16-bit values as expected in Ecmascript. The surrogate
10048 * pairs always get a 3-byte encoding (each) in CESU-8.
10049 * See: http://en.wikipedia.org/wiki/Surrogate_pair
10050 *
10051 * 20-bit codepoint, 10 bits (A and B) per surrogate pair:
10052 *
10053 * x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
10054 * sp1 = 0b110110AA AAAAAAAA (0xd800 + ((x >> 10) & 0x3ff))
10055 * sp2 = 0b110111BB BBBBBBBB (0xdc00 + (x & 0x3ff))
10056 *
10057 * Encoded into CESU-8:
10058 *
10059 * sp1 -> 0b11101101 (0xe0 + ((sp1 >> 12) & 0x0f))
10060 * -> 0b1010AAAA (0x80 + ((sp1 >> 6) & 0x3f))
10061 * -> 0b10AAAAAA (0x80 + (sp1 & 0x3f))
10062 * sp2 -> 0b11101101 (0xe0 + ((sp2 >> 12) & 0x0f))
10063 * -> 0b1011BBBB (0x80 + ((sp2 >> 6) & 0x3f))
10064 * -> 0b10BBBBBB (0x80 + (sp2 & 0x3f))
10065 *
10066 * Note that 0x10000 must be subtracted first. The code below
10067 * avoids the sp1, sp2 temporaries which saves around 20 bytes
10068 * of code.
10070
10071 x -= 0x10000UL;
10072
10073 out[0] = (duk_uint8_t) (0xed);
10074 out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
10075 out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
10076 out[3] = (duk_uint8_t) (0xed);
10077 out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
10078 out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
10079 len = 6;
10080 }
10081
10082 return len;
10083}
10084
10085/* Decode helper. Return zero on error. */
10086DUK_INTERNAL 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) {
10087 const duk_uint8_t *p;
10088 duk_uint32_t res;
10091
10092 DUK_UNREF(thr);
10093
10094 p = *ptr;
10095 if (p < ptr_start || p >= ptr_end) {
10096 goto fail;
10097 }
10098
10099 /*
10100 * UTF-8 decoder which accepts longer than standard byte sequences.
10101 * This allows full 32-bit code points to be used.
10102 */
10103
10104 ch = (duk_uint_fast8_t) (*p++);
10105 if (ch < 0x80) {
10106 /* 0xxx xxxx [7 bits] */
10107 res = (duk_uint32_t) (ch & 0x7f);
10108 n = 0;
10109 } else if (ch < 0xc0) {
10110 /* 10xx xxxx -> invalid */
10111 goto fail;
10112 } else if (ch < 0xe0) {
10113 /* 110x xxxx 10xx xxxx [11 bits] */
10114 res = (duk_uint32_t) (ch & 0x1f);
10115 n = 1;
10116 } else if (ch < 0xf0) {
10117 /* 1110 xxxx 10xx xxxx 10xx xxxx [16 bits] */
10118 res = (duk_uint32_t) (ch & 0x0f);
10119 n = 2;
10120 } else if (ch < 0xf8) {
10121 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx [21 bits] */
10122 res = (duk_uint32_t) (ch & 0x07);
10123 n = 3;
10124 } else if (ch < 0xfc) {
10125 /* 1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [26 bits] */
10126 res = (duk_uint32_t) (ch & 0x03);
10127 n = 4;
10128 } else if (ch < 0xfe) {
10129 /* 1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [31 bits] */
10130 res = (duk_uint32_t) (ch & 0x01);
10131 n = 5;
10132 } else if (ch < 0xff) {
10133 /* 1111 1110 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [36 bits] */
10134 res = (duk_uint32_t) (0);
10135 n = 6;
10136 } else {
10137 /* 8-byte format could be:
10138 * 1111 1111 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [41 bits]
10139 *
10140 * However, this format would not have a zero bit following the
10141 * leading one bits and would not allow 0xFF to be used as an
10142 * "invalid xutf-8" marker for internal keys. Further, 8-byte
10143 * encodings (up to 41 bit code points) are not currently needed.
10144 */
10145 goto fail;
10146 }
10147
10148 DUK_ASSERT(p >= ptr_start); /* verified at beginning */
10149 if (p + n > ptr_end) {
10150 /* check pointer at end */
10151 goto fail;
10152 }
10154 while (n > 0) {
10155 DUK_ASSERT(p >= ptr_start && p < ptr_end);
10156 res = res << 6;
10157 res += (duk_uint32_t) ((*p++) & 0x3f);
10158 n--;
10159 }
10160
10161 *ptr = p;
10162 *out_cp = res;
10163 return 1;
10164
10165 fail:
10166 return 0;
10167}
10168
10169/* used by e.g. duk_regexp_executor.c, string built-ins */
10170DUK_INTERNAL 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) {
10172
10173 if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
10174 return cp;
10175 }
10176 DUK_ERROR_INTERNAL(thr, "utf-8 decode failed"); /* XXX: 'internal error' is a bit of a misnomer */
10178 return 0;
10179}
10180
10181/* Compute (extended) utf-8 length without codepoint encoding validation,
10182 * used for string interning.
10183 *
10184 * NOTE: This algorithm is performance critical, more so than string hashing
10185 * in some cases. It is needed when interning a string and needs to scan
10186 * every byte of the string with no skipping. Having an ASCII fast path
10187 * is useful if possible in the algorithm. The current algorithms were
10188 * chosen from several variants, based on x64 gcc -O2 testing. See:
10189 * https://github.com/svaarala/duktape/pull/422
10190 *
10191 * NOTE: must match src/dukutil.py:duk_unicode_unvalidated_utf8_length().
10192 */
10193
10194#if defined(DUK_USE_PREFER_SIZE)
10195/* Small variant; roughly 150 bytes smaller than the fast variant. */
10197 const duk_uint8_t *p;
10198 const duk_uint8_t *p_end;
10199 duk_size_t ncont;
10200 duk_size_t clen;
10201
10202 p = data;
10203 p_end = data + blen;
10204 ncont = 0;
10205 while (p != p_end) {
10206 duk_uint8_t x;
10207 x = *p++;
10208 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10209 ncont++;
10210 }
10211 }
10212
10213 DUK_ASSERT(ncont <= blen);
10214 clen = blen - ncont;
10215 DUK_ASSERT(clen <= blen);
10216 return clen;
10217}
10218#else /* DUK_USE_PREFER_SIZE */
10219/* This seems like a good overall approach. Fast path for ASCII in 4 byte
10220 * blocks.
10221 */
10223 const duk_uint8_t *p;
10224 const duk_uint8_t *p_end;
10225 const duk_uint32_t *p32_end;
10226 const duk_uint32_t *p32;
10227 duk_size_t ncont;
10228 duk_size_t clen;
10229
10230 ncont = 0; /* number of continuation (non-initial) bytes in [0x80,0xbf] */
10231 p = data;
10232 p_end = data + blen;
10233 if (blen < 16) {
10234 goto skip_fastpath;
10235 }
10236
10237 /* Align 'p' to 4; the input data may have arbitrary alignment.
10238 * End of string check not needed because blen >= 16.
10239 */
10240 while (((duk_size_t) (const void *) p) & 0x03U) {
10241 duk_uint8_t x;
10242 x = *p++;
10243 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10244 ncont++;
10245 }
10246 }
10247
10248 /* Full, aligned 4-byte reads. */
10249 p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
10250 p32 = (const duk_uint32_t *) (const void *) p;
10251 while (p32 != (const duk_uint32_t *) p32_end) {
10252 duk_uint32_t x;
10253 x = *p32++;
10254 if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
10255 ; /* ASCII fast path */
10256 } else {
10257 /* Flip highest bit of each byte which changes
10258 * the bit pattern 10xxxxxx into 00xxxxxx which
10259 * allows an easy bit mask test.
10260 */
10261 x ^= 0x80808080UL;
10262 if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
10263 ncont++;
10264 }
10265 if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
10266 ncont++;
10267 }
10268 if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
10269 ncont++;
10270 }
10271 if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
10272 ncont++;
10273 }
10274 }
10275 }
10276 p = (const duk_uint8_t *) p32;
10277 /* Fall through to handle the rest. */
10278
10279 skip_fastpath:
10280 while (p != p_end) {
10281 duk_uint8_t x;
10282 x = *p++;
10283 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10284 ncont++;
10285 }
10287
10288 DUK_ASSERT(ncont <= blen);
10289 clen = blen - ncont;
10290 DUK_ASSERT(clen <= blen);
10291 return clen;
10292}
10293#endif /* DUK_USE_PREFER_SIZE */
10294
10295/*
10296 * Unicode range matcher
10297 *
10298 * Matches a codepoint against a packed bitstream of character ranges.
10299 * Used for slow path Unicode matching.
10300 */
10301
10302/* Must match src/extract_chars.py, generate_match_table3(). */
10304 duk_uint32_t t;
10305
10306 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
10307 if (t <= 0x0eU) {
10308 return t;
10309 }
10310 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
10311 if (t <= 0xfdU) {
10312 return t + 0x0f;
10313 }
10314 if (t == 0xfeU) {
10315 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
10316 return t + 0x0fU + 0xfeU;
10317 } else {
10318 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
10319 return t + 0x0fU + 0xfeU + 0x1000UL;
10320 }
10321}
10322
10323DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
10324 duk_bitdecoder_ctx bd_ctx;
10325 duk_codepoint_t prev_re;
10326
10327 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
10328 bd_ctx.data = (const duk_uint8_t *) unitab;
10329 bd_ctx.length = (duk_size_t) unilen;
10330
10331 prev_re = 0;
10332 for (;;) {
10333 duk_codepoint_t r1, r2;
10334 r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10335 if (r1 == 0) {
10336 break;
10337 }
10338 r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10339
10340 r1 = prev_re + r1;
10341 r2 = r1 + r2;
10342 prev_re = r2;
10344 /* [r1,r2] is the range */
10345
10346 DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
10347 (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
10348 if (cp >= r1 && cp <= r2) {
10349 return 1;
10350 }
10351 }
10352
10353 return 0;
10354}
10355
10356/*
10357 * "WhiteSpace" production check.
10358 */
10359
10361 /*
10362 * E5 Section 7.2 specifies six characters specifically as
10363 * white space:
10364 *
10365 * 0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
10366 * 000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
10367 * 000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
10368 * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
10369 * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
10370 * FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
10371 *
10372 * It also specifies any Unicode category 'Zs' characters as white
10373 * space. These can be extracted with the "src/extract_chars.py" script.
10374 * Current result:
10375 *
10376 * RAW OUTPUT:
10377 * ===========
10378 * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
10379 * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
10380 * 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
10381 * 180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
10382 * 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
10383 * 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
10384 * 2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10385 * 2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10386 * 2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10387 * 2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10388 * 2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10389 * 2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
10390 * 2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10391 * 2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10392 * 200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10393 * 202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
10394 * 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10395 * 3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
10396 *
10397 * RANGES:
10398 * =======
10399 * 0x0020
10400 * 0x00a0
10401 * 0x1680
10402 * 0x180e
10403 * 0x2000 ... 0x200a
10404 * 0x202f
10405 * 0x205f
10406 * 0x3000
10407 *
10408 * A manual decoder (below) is probably most compact for this.
10409 */
10410
10413
10414 /* cp == -1 (EOF) never matches and causes return value 0 */
10415
10416 lo = (duk_uint_fast8_t) (cp & 0xff);
10417 hi = (duk_uint_fast32_t) (cp >> 8); /* does not fit into an uchar */
10418
10419 if (hi == 0x0000UL) {
10420 if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
10421 lo == 0x20U || lo == 0xa0U) {
10422 return 1;
10424 } else if (hi == 0x0020UL) {
10425 if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
10426 return 1;
10427 }
10428 } else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
10429 cp == 0xfeffL) {
10430 return 1;
10431 }
10432
10433 return 0;
10434}
10435
10436/*
10437 * "LineTerminator" production check.
10438 */
10439
10441 /*
10442 * E5 Section 7.3
10444 * A LineTerminatorSequence essentially merges <CR> <LF> sequences
10445 * into a single line terminator. This must be handled by the caller.
10446 */
10447
10448 if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
10449 cp == 0x2029L) {
10450 return 1;
10451 }
10452
10453 return 0;
10454}
10455
10456/*
10457 * "IdentifierStart" production check.
10458 */
10459
10461 /*
10462 * E5 Section 7.6:
10463 *
10464 * IdentifierStart:
10465 * UnicodeLetter
10466 * $
10467 * _
10468 * \ UnicodeEscapeSequence
10469 *
10470 * IdentifierStart production has one multi-character production:
10471 *
10472 * \ UnicodeEscapeSequence
10473 *
10474 * The '\' character is -not- matched by this function. Rather, the caller
10475 * should decode the escape and then call this function to check whether the
10476 * decoded character is acceptable (see discussion in E5 Section 7.6).
10477 *
10478 * The "UnicodeLetter" alternative of the production allows letters
10479 * from various Unicode categories. These can be extracted with the
10480 * "src/extract_chars.py" script.
10481 *
10482 * Because the result has hundreds of Unicode codepoint ranges, matching
10483 * for any values >= 0x80 are done using a very slow range-by-range scan
10484 * and a packed range format.
10485 *
10486 * The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
10487 * it matters the most. The ASCII related ranges of IdentifierStart are:
10488 *
10489 * 0x0041 ... 0x005a ['A' ... 'Z']
10490 * 0x0061 ... 0x007a ['a' ... 'z']
10491 * 0x0024 ['$']
10492 * 0x005f ['_']
10493 */
10494
10495 /* ASCII (and EOF) fast path -- quick accept and reject */
10496 if (cp <= 0x7fL) {
10497#if defined(DUK_USE_IDCHAR_FASTPATH)
10498 return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
10499#else
10500 if ((cp >= 'a' && cp <= 'z') ||
10501 (cp >= 'A' && cp <= 'Z') ||
10502 cp == '_' || cp == '$') {
10503 return 1;
10504 }
10505 return 0;
10506#endif
10507 }
10508
10509 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
10510
10511#ifdef DUK_USE_SOURCE_NONBMP
10514 (duk_codepoint_t) cp)) {
10515 return 1;
10516 }
10517 return 0;
10518#else
10519 if (cp < 0x10000L) {
10521 sizeof(duk_unicode_ids_noabmp),
10523 return 1;
10524 }
10525 return 0;
10526 } else {
10527 /* without explicit non-BMP support, assume non-BMP characters
10528 * are always accepted as identifier characters.
10529 */
10530 return 1;
10531 }
10532#endif
10533}
10534
10535/*
10536 * "IdentifierPart" production check.
10537 */
10538
10540 /*
10541 * E5 Section 7.6:
10542 *
10543 * IdentifierPart:
10544 * IdentifierStart
10545 * UnicodeCombiningMark
10546 * UnicodeDigit
10547 * UnicodeConnectorPunctuation
10548 * <ZWNJ> [U+200C]
10549 * <ZWJ> [U+200D]
10550 *
10551 * IdentifierPart production has one multi-character production
10552 * as part of its IdentifierStart alternative. The '\' character
10553 * of an escape sequence is not matched here, see discussion in
10554 * duk_unicode_is_identifier_start().
10555 *
10556 * To match non-ASCII characters (codepoints >= 0x80), a very slow
10557 * linear range-by-range scan is used. The codepoint is first compared
10558 * to the IdentifierStart ranges, and if it doesn't match, then to a
10559 * set consisting of code points in IdentifierPart but not in
10560 * IdentifierStart. This is done to keep the unicode range data small,
10561 * at the expense of speed.
10562 *
10563 * The ASCII fast path consists of:
10564 *
10565 * 0x0030 ... 0x0039 ['0' ... '9', UnicodeDigit]
10566 * 0x0041 ... 0x005a ['A' ... 'Z', IdentifierStart]
10567 * 0x0061 ... 0x007a ['a' ... 'z', IdentifierStart]
10568 * 0x0024 ['$', IdentifierStart]
10569 * 0x005f ['_', IdentifierStart and
10570 * UnicodeConnectorPunctuation]
10571 *
10572 * UnicodeCombiningMark has no code points <= 0x7f.
10573 *
10574 * The matching code reuses the "identifier start" tables, and then
10575 * consults a separate range set for characters in "identifier part"
10576 * but not in "identifier start". These can be extracted with the
10577 * "src/extract_chars.py" script.
10578 *
10579 * UnicodeCombiningMark -> categories Mn, Mc
10580 * UnicodeDigit -> categories Nd
10581 * UnicodeConnectorPunctuation -> categories Pc
10582 */
10583
10584 /* ASCII (and EOF) fast path -- quick accept and reject */
10585 if (cp <= 0x7fL) {
10586#if defined(DUK_USE_IDCHAR_FASTPATH)
10587 return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
10588#else
10589 if ((cp >= 'a' && cp <= 'z') ||
10590 (cp >= 'A' && cp <= 'Z') ||
10591 (cp >= '0' && cp <= '9') ||
10592 cp == '_' || cp == '$') {
10593 return 1;
10594 }
10595 return 0;
10596#endif
10597 }
10598
10599 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
10600
10601#ifdef DUK_USE_SOURCE_NONBMP
10603 sizeof(duk_unicode_ids_noa),
10604 (duk_codepoint_t) cp) ||
10607 (duk_codepoint_t) cp)) {
10608 return 1;
10609 }
10610 return 0;
10611#else
10612 if (cp < 0x10000L) {
10614 sizeof(duk_unicode_ids_noabmp),
10615 (duk_codepoint_t) cp) ||
10619 return 1;
10620 }
10621 return 0;
10622 } else {
10623 /* without explicit non-BMP support, assume non-BMP characters
10624 * are always accepted as identifier characters.
10625 */
10626 return 1;
10627 }
10628#endif
10629}
10630
10631/*
10632 * Unicode letter check.
10633 */
10634
10636 /*
10637 * Unicode letter is now taken to be the categories:
10638 *
10639 * Lu, Ll, Lt, Lm, Lo
10640 *
10641 * (Not sure if this is exactly correct.)
10642 *
10643 * The ASCII fast path consists of:
10644 *
10645 * 0x0041 ... 0x005a ['A' ... 'Z']
10646 * 0x0061 ... 0x007a ['a' ... 'z']
10647 */
10648
10649 /* ASCII (and EOF) fast path -- quick accept and reject */
10650 if (cp <= 0x7fL) {
10651 if ((cp >= 'a' && cp <= 'z') ||
10652 (cp >= 'A' && cp <= 'Z')) {
10653 return 1;
10654 }
10655 return 0;
10656 }
10657
10658 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
10659
10660#ifdef DUK_USE_SOURCE_NONBMP
10662 sizeof(duk_unicode_ids_noa),
10663 (duk_codepoint_t) cp) &&
10666 (duk_codepoint_t) cp)) {
10667 return 1;
10668 }
10669 return 0;
10670#else
10671 if (cp < 0x10000L) {
10673 sizeof(duk_unicode_ids_noabmp),
10674 (duk_codepoint_t) cp) &&
10677 (duk_codepoint_t) cp)) {
10678 return 1;
10679 }
10680 return 0;
10681 } else {
10682 /* without explicit non-BMP support, assume non-BMP characters
10683 * are always accepted as letters.
10684 */
10685 return 1;
10686 }
10687#endif
10688}
10689
10690/*
10691 * Complex case conversion helper which decodes a bit-packed conversion
10692 * control stream generated by unicode/extract_caseconv.py. The conversion
10693 * is very slow because it runs through the conversion data in a linear
10694 * fashion to save space (which is why ASCII characters have a special
10695 * fast path before arriving here).
10696 *
10697 * The particular bit counts etc have been determined experimentally to
10698 * be small but still sufficient, and must match the Python script
10699 * (src/extract_caseconv.py).
10700 *
10701 * The return value is the case converted codepoint or -1 if the conversion
10702 * results in multiple characters (this is useful for regexp Canonicalization
10703 * operation). If 'buf' is not NULL, the result codepoint(s) are also
10704 * appended to the hbuffer.
10705 *
10706 * Context and locale specific rules must be checked before consulting
10707 * this function.
10708 */
10709
10713 duk_codepoint_t cp,
10714 duk_bitdecoder_ctx *bd_ctx) {
10715 duk_small_int_t skip = 0;
10718 duk_small_int_t count;
10719 duk_codepoint_t tmp_cp;
10720 duk_codepoint_t start_i;
10721 duk_codepoint_t start_o;
10722
10723 DUK_UNREF(thr);
10724 DUK_ASSERT(bd_ctx != NULL);
10725
10726 DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
10727
10728 /* range conversion with a "skip" */
10729 DUK_DDD(DUK_DDDPRINT("checking ranges"));
10730 for (;;) {
10731 skip++;
10732 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
10733 if (n == 0x3f) {
10734 /* end marker */
10735 break;
10736 }
10737 DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
10738
10739 while (n--) {
10740 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10741 start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10742 count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
10743 DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
10744 (long) start_i, (long) start_o, (long) count, (long) skip));
10745
10746 if (cp >= start_i) {
10747 tmp_cp = cp - start_i; /* always >= 0 */
10748 if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
10749 (tmp_cp % (duk_codepoint_t) skip) == 0) {
10750 DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
10751 cp = start_o + tmp_cp;
10752 goto single;
10753 }
10754 }
10755 }
10756 }
10757
10758 /* 1:1 conversion */
10759 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
10760 DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
10761 while (n--) {
10762 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10763 start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10764 DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
10765 if (cp == start_i) {
10766 DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
10767 cp = start_o;
10768 goto single;
10769 }
10770 }
10771
10772 /* complex, multicharacter conversion */
10773 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
10774 DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
10775 while (n--) {
10776 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10777 t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
10778 DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
10779 if (cp == start_i) {
10780 DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
10781 if (bw != NULL) {
10782 while (t--) {
10783 tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10784 DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
10785 }
10786 }
10787 return -1;
10788 } else {
10789 while (t--) {
10790 (void) duk_bd_decode(bd_ctx, 16);
10791 }
10792 }
10793 }
10794
10795 /* default: no change */
10796 DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
10797 /* fall through */
10798
10799 single:
10800 if (bw != NULL) {
10802 }
10803 return cp;
10804}
10805
10806/*
10807 * Case conversion helper, with context/local sensitivity.
10808 * For proper case conversion, one needs to know the character
10809 * and the preceding and following characters, as well as
10810 * locale/language.
10811 */
10812
10813/* XXX: add 'language' argument when locale/language sensitive rule
10814 * support added.
10815 */
10819 duk_codepoint_t cp,
10820 duk_codepoint_t prev,
10822 duk_bool_t uppercase) {
10823 duk_bitdecoder_ctx bd_ctx;
10824
10825 /* fast path for ASCII */
10826 if (cp < 0x80L) {
10827 /* XXX: there are language sensitive rules for the ASCII range.
10828 * If/when language/locale support is implemented, they need to
10829 * be implemented here for the fast path. There are no context
10830 * sensitive rules for ASCII range.
10831 */
10832
10833 if (uppercase) {
10834 if (cp >= 'a' && cp <= 'z') {
10835 cp = cp - 'a' + 'A';
10836 }
10837 } else {
10838 if (cp >= 'A' && cp <= 'Z') {
10839 cp = cp - 'A' + 'a';
10840 }
10841 }
10842
10843 if (bw != NULL) {
10844 DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
10845 }
10846 return cp;
10847 }
10848
10849 /* context and locale specific rules which cannot currently be represented
10850 * in the caseconv bitstream: hardcoded rules in C
10851 */
10852 if (uppercase) {
10853 /* XXX: turkish / azeri */
10854 } else {
10855 /*
10856 * Final sigma context specific rule. This is a rather tricky
10857 * rule and this handling is probably not 100% correct now.
10858 * The rule is not locale/language specific so it is supported.
10859 */
10860
10861 if (cp == 0x03a3L && /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
10862 duk_unicode_is_letter(prev) && /* prev exists and is not a letter */
10863 !duk_unicode_is_letter(next)) { /* next does not exist or next is not a letter */
10864 /* Capital sigma occurred at "end of word", lowercase to
10865 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA. Otherwise
10866 * fall through and let the normal rules lowercase it to
10867 * U+03C3 = GREEK SMALL LETTER SIGMA.
10868 */
10869 cp = 0x03c2L;
10870 goto singlechar;
10871 }
10872
10873 /* XXX: lithuanian not implemented */
10874 /* XXX: lithuanian, explicit dot rules */
10875 /* XXX: turkish / azeri, lowercase rules */
10876 }
10877
10878 /* 1:1 or special conversions, but not locale/context specific: script generated rules */
10879 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
10880 if (uppercase) {
10881 bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
10882 bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
10883 } else {
10884 bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
10885 bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
10886 }
10887 return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
10888
10889 singlechar:
10890 if (bw != NULL) {
10892 }
10893 return cp;
10894
10895 /* unused now, not needed until Turkish/Azeri */
10896#if 0
10897 nochar:
10898 return -1;
10899#endif
10900}
10901
10902/*
10903 * Replace valstack top with case converted version.
10904 */
10905
10907 duk_context *ctx = (duk_context *) thr;
10908 duk_hstring *h_input;
10909 duk_bufwriter_ctx bw_alloc;
10911 const duk_uint8_t *p, *p_start, *p_end;
10912 duk_codepoint_t prev, curr, next;
10913
10914 h_input = duk_require_hstring(ctx, -1);
10915 DUK_ASSERT(h_input != NULL);
10916
10917 bw = &bw_alloc;
10919
10920 /* [ ... input buffer ] */
10921
10922 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
10923 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
10924 p = p_start;
10925
10926 prev = -1; DUK_UNREF(prev);
10927 curr = -1;
10928 next = -1;
10929 for (;;) {
10930 prev = curr;
10931 curr = next;
10932 next = -1;
10933 if (p < p_end) {
10934 next = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
10935 } else {
10936 /* end of input and last char has been processed */
10937 if (curr < 0) {
10938 break;
10939 }
10940 }
10941
10942 /* on first round, skip */
10943 if (curr >= 0) {
10944 /* XXX: could add a fast path to process chunks of input codepoints,
10945 * but relative benefit would be quite small.
10946 */
10947
10948 /* Ensure space for maximum multi-character result; estimate is overkill. */
10950
10952 bw,
10953 (duk_codepoint_t) curr,
10954 prev,
10955 next,
10956 uppercase);
10958 }
10959
10960 DUK_BW_COMPACT(thr, bw);
10961 duk_to_string(ctx, -1); /* invalidates h_buf pointer */
10962 duk_remove(ctx, -2);
10963}
10964
10965#ifdef DUK_USE_REGEXP_SUPPORT
10966
10967/*
10968 * Canonicalize() abstract operation needed for canonicalization of individual
10969 * codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
10970 * Note that codepoints are canonicalized one character at a time, so no context
10971 * specific rules can apply. Locale specific rules can apply, though.
10972 */
10973
10975#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10976 /* Fast canonicalization lookup at the cost of 128kB footprint. */
10977 DUK_ASSERT(cp >= 0);
10978 DUK_UNREF(thr);
10979 if (DUK_LIKELY(cp < 0x10000L)) {
10980 return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
10981 }
10982 return cp;
10983#else /* DUK_USE_REGEXP_CANON_WORKAROUND */
10985
10987 NULL, /* NULL is allowed, no output */
10988 cp, /* curr char */
10989 -1, /* prev char */
10990 -1, /* next char */
10991 1); /* uppercase */
10993 if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
10994 /* multiple codepoint conversion or non-ASCII mapped to ASCII
10995 * --> leave as is.
10996 */
10997 return cp;
10998 }
10999
11000 return y;
11001#endif /* DUK_USE_REGEXP_CANON_WORKAROUND */
11002}
11003
11004/*
11005 * E5 Section 15.10.2.6 "IsWordChar" abstract operation. Assume
11006 * x < 0 for characters read outside the string.
11007 */
11008
11010 /*
11011 * Note: the description in E5 Section 15.10.2.6 has a typo, it
11012 * contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
11013 */
11014 if ((x >= '0' && x <= '9') ||
11015 (x >= 'a' && x <= 'z') ||
11016 (x >= 'A' && x <= 'Z') ||
11017 (x == '_')) {
11018 return 1;
11019 }
11020 return 0;
11021}
11022
11023/*
11024 * Regexp range tables
11025 */
11026
11027/* exposed because lexer needs these too */
11028DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
11029 (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11030};
11031DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
11032 (duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
11033 (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
11034 (duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
11035 (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
11036 (duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
11037 (duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
11038 (duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
11039 (duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
11040 (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
11041 (duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
11042 (duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
11043};
11044DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
11045 (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11046 (duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
11047 (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
11048 (duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
11049};
11050DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
11051 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11052 (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
11053};
11054DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
11055 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
11056 (duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
11057 (duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
11058 (duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
11059 (duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
11060 (duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
11061 (duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
11062 (duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
11063 (duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
11064 (duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
11065 (duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
11066 (duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
11067};
11068DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
11069 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11070 (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
11071 (duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
11072 (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
11073 (duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
11074};
11075
11076#endif /* DUK_USE_REGEXP_SUPPORT */
11077/*
11078 * Misc util stuff
11079 */
11080
11081/* include removed: duk_internal.h */
11082
11084 * Lowercase digits for radix values 2 to 36. Also doubles as lowercase
11085 * hex nybble table.
11086 */
11087
11088DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
11098};
11099
11100DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
11105};
11106
11107/*
11108 * Table for hex decoding ASCII hex digits
11109 */
11110
11111DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
11112 /* -1 if invalid */
11113 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
11114 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
11115 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
11116 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
11117 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
11118 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
11119 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
11120 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
11121 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
11122 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
11123 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
11124 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
11125 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
11126 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
11127 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
11128 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
11129};
11130
11131#if defined(DUK_USE_HEX_FASTPATH)
11132/* Preshifted << 4. Must use 16-bit entry to allow negative value signaling. */
11133DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
11134 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
11135 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
11136 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
11137 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
11138 -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
11139 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
11140 -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
11141 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
11142 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
11143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
11144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
11145 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
11146 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
11147 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
11148 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
11149 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
11150};
11151#endif
11153/*
11154 * Table for hex encoding bytes
11155 */
11156
11157#if defined(DUK_USE_HEX_FASTPATH)
11158/* Lookup to encode one byte directly into 2 characters:
11159 *
11160 * def genhextab(bswap):
11161 * for i in xrange(256):
11162 * t = chr(i).encode('hex')
11163 * if bswap:
11164 * t = t[1] + t[0]
11165 * print('0x' + t.encode('hex') + 'U')
11166 * print('big endian'); genhextab(False)
11167 * print('little endian'); genhextab(True)
11168*/
11169DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
11170#if defined(DUK_USE_INTEGER_BE)
11171 0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
11172 0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
11173 0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
11174 0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
11175 0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
11176 0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
11177 0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
11178 0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
11179 0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
11180 0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
11181 0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
11182 0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
11183 0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
11184 0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
11185 0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
11186 0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
11187 0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
11188 0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
11189 0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
11190 0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
11191 0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
11192 0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
11193 0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
11194 0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
11195 0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
11196 0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
11197 0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
11198 0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
11199 0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
11200 0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
11201 0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
11202 0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
11203#else /* DUK_USE_INTEGER_BE */
11204 0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
11205 0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
11206 0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
11207 0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
11208 0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
11209 0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
11210 0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
11211 0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
11212 0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
11213 0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
11214 0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
11215 0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
11216 0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
11217 0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
11218 0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
11219 0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
11220 0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
11221 0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
11222 0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
11223 0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
11224 0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
11225 0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
11226 0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
11227 0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
11228 0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
11229 0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
11230 0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
11231 0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
11232 0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
11233 0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
11234 0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
11235 0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
11236#endif /* DUK_USE_INTEGER_BE */
11237};
11238#endif /* DUK_USE_HEX_FASTPATH */
11239
11240/*
11241 * Table for base-64 encoding
11242 */
11243
11244#if defined(DUK_USE_BASE64_FASTPATH)
11245DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {
11246 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* A...P */
11247 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, /* Q...f */
11248 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, /* g...v */
11249 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f /* w.../ */
11250};
11251#endif /* DUK_USE_BASE64_FASTPATH */
11252
11253/*
11254 * Table for base-64 decoding
11255 */
11256
11257#if defined(DUK_USE_BASE64_FASTPATH)
11258DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
11259 /* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */
11260 -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, /* 0x00...0x0f */
11261 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10...0x1f */
11262 -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20...0x2f */
11263 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, /* 0x30...0x3f */
11264 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */
11265 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50...0x5f */
11266 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */
11267 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70...0x7f */
11268 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80...0x8f */
11269 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90...0x9f */
11270 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0...0xaf */
11271 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0...0xbf */
11272 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0...0xcf */
11273 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0...0xdf */
11274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0...0xef */
11275 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0...0xff */
11276};
11277#endif /* DUK_USE_BASE64_FASTPATH */
11278
11279/*
11280 * Arbitrary byteswap for potentially unaligned values
11281 *
11282 * Used to byteswap pointers e.g. in debugger code.
11283 */
11284
11285#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
11286DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
11287 duk_uint8_t tmp;
11288 duk_uint8_t *q = p + len - 1;
11289
11290 while (p - q < 0) {
11291 tmp = *p;
11292 *p = *q;
11293 *q = tmp;
11294 p++;
11295 q--;
11296 }
11297}
11298#endif
11299/*
11300 * Round a number upwards to a prime (not usually the nearest one).
11301 *
11302 * Uses a table of successive 32-bit primes whose ratio is roughly
11303 * constant. This keeps the relative upwards 'rounding error' bounded
11304 * and the data size small. A simple 'predict-correct' compression is
11305 * used to compress primes to one byte per prime. See genhashsizes.py
11306 * for details.
11307 *
11308 * The minimum prime returned here must be coordinated with the possible
11309 * probe sequence steps in duk_hobject and duk_heap stringtable.
11310 */
11311
11312/* include removed: duk_internal.h */
11313
11314/* Awkward inclusion condition: drop out of compilation if not needed by any
11315 * call site: object hash part or probing stringtable.
11316 */
11317#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
11318
11319/* hash size ratio goal, must match genhashsizes.py */
11320#define DUK__HASH_SIZE_RATIO 1177 /* floor(1.15 * (1 << 10)) */
11322/* prediction corrections for prime list (see genhashsizes.py) */
11323DUK_LOCAL const duk_int8_t duk__hash_size_corrections[] = {
11324 17, /* minimum prime */
11325 4, 3, 4, 1, 4, 1, 1, 2, 2, 2, 2, 1, 6, 6, 9, 5, 1, 2, 2, 5, 1, 3, 3, 3,
11326 5, 4, 4, 2, 4, 8, 3, 4, 23, 2, 4, 7, 8, 11, 2, 12, 15, 10, 1, 1, 5, 1, 5,
11327 8, 9, 17, 14, 10, 7, 5, 2, 46, 21, 1, 9, 9, 4, 4, 10, 23, 36, 6, 20, 29,
11328 18, 6, 19, 21, 16, 11, 5, 5, 48, 9, 1, 39, 14, 8, 4, 29, 9, 1, 15, 48, 12,
11329 22, 6, 15, 27, 4, 2, 17, 28, 8, 9, 4, 5, 8, 3, 3, 8, 37, 11, 15, 8, 30,
11330 43, 6, 33, 41, 5, 20, 32, 41, 38, 24, 77, 14, 19, 11, 4, 35, 18, 19, 41,
11331 10, 23, 16, 9, 2,
11332 -1
11333};
11334
11335/* probe steps (see genhashsizes.py), currently assumed to be 32 entries long
11336 * (DUK_UTIL_GET_HASH_PROBE_STEP macro).
11337 */
11338DUK_INTERNAL duk_uint8_t duk_util_probe_steps[32] = {
11339 2, 3, 5, 7, 11, 13, 19, 31, 41, 47, 59, 67, 73, 79, 89, 101, 103, 107,
11340 109, 127, 137, 139, 149, 157, 163, 167, 173, 181, 191, 193, 197, 199
11341};
11342
11343DUK_INTERNAL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) {
11344 const duk_int8_t *p = duk__hash_size_corrections;
11345 duk_uint32_t curr;
11346
11347 curr = (duk_uint32_t) *p++;
11348 for (;;) {
11350 if (t < 0) {
11351 /* may happen if size is very close to 2^32-1 */
11352 break;
11353 }
11354
11355 /* prediction: portable variant using doubles if 64-bit values not available */
11356#ifdef DUK_USE_64BIT_OPS
11357 curr = (duk_uint32_t) ((((duk_uint64_t) curr) * ((duk_uint64_t) DUK__HASH_SIZE_RATIO)) >> 10);
11358#else
11359 /* 32-bit x 11-bit = 43-bit, fits accurately into a double */
11360 curr = (duk_uint32_t) DUK_FLOOR(((double) curr) * ((double) DUK__HASH_SIZE_RATIO) / 1024.0);
11361#endif
11362
11363 /* correction */
11364 curr += t;
11365
11366 DUK_DDD(DUK_DDDPRINT("size=%ld, curr=%ld", (long) size, (long) curr));
11367
11368 if (curr >= size) {
11369 return curr;
11370 }
11371 }
11372 return 0;
11373}
11374
11375#endif /* DUK_USE_HOBJECT_HASH_PART || DUK_USE_STRTAB_PROBE */
11376/*
11377 * Hobject Ecmascript [[Class]].
11378 */
11379
11380/* include removed: duk_internal.h */
11381
11382#if (DUK_STRIDX_UC_ARGUMENTS > 255)
11383#error constant too large
11384#endif
11385#if (DUK_STRIDX_ARRAY > 255)
11386#error constant too large
11387#endif
11388#if (DUK_STRIDX_UC_BOOLEAN > 255)
11389#error constant too large
11390#endif
11391#if (DUK_STRIDX_DATE > 255)
11392#error constant too large
11393#endif
11394#if (DUK_STRIDX_UC_ERROR > 255)
11395#error constant too large
11396#endif
11397#if (DUK_STRIDX_UC_FUNCTION > 255)
11398#error constant too large
11399#endif
11400#if (DUK_STRIDX_JSON > 255)
11401#error constant too large
11402#endif
11403#if (DUK_STRIDX_MATH > 255)
11404#error constant too large
11405#endif
11406#if (DUK_STRIDX_UC_NUMBER > 255)
11407#error constant too large
11408#endif
11409#if (DUK_STRIDX_UC_OBJECT > 255)
11410#error constant too large
11411#endif
11412#if (DUK_STRIDX_REG_EXP > 255)
11413#error constant too large
11414#endif
11415#if (DUK_STRIDX_UC_STRING > 255)
11416#error constant too large
11417#endif
11418#if (DUK_STRIDX_GLOBAL > 255)
11419#error constant too large
11420#endif
11421#if (DUK_STRIDX_OBJ_ENV > 255)
11422#error constant too large
11423#endif
11424#if (DUK_STRIDX_DEC_ENV > 255)
11425#error constant too large
11426#endif
11427#if (DUK_STRIDX_UC_BUFFER > 255)
11428#error constant too large
11429#endif
11430#if (DUK_STRIDX_UC_POINTER > 255)
11431#error constant too large
11432#endif
11433#if (DUK_STRIDX_UC_THREAD > 255)
11434#error constant too large
11435#endif
11436#if (DUK_STRIDX_ARRAY_BUFFER > 255)
11437#error constant too large
11438#endif
11439#if (DUK_STRIDX_DATA_VIEW > 255)
11440#error constant too large
11441#endif
11442#if (DUK_STRIDX_INT8_ARRAY > 255)
11443#error constant too large
11444#endif
11445#if (DUK_STRIDX_UINT8_ARRAY > 255)
11446#error constant too large
11447#endif
11448#if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
11449#error constant too large
11450#endif
11451#if (DUK_STRIDX_INT16_ARRAY > 255)
11452#error constant too large
11453#endif
11454#if (DUK_STRIDX_UINT16_ARRAY > 255)
11455#error constant too large
11456#endif
11457#if (DUK_STRIDX_INT32_ARRAY > 255)
11458#error constant too large
11459#endif
11460#if (DUK_STRIDX_UINT32_ARRAY > 255)
11461#error constant too large
11462#endif
11463#if (DUK_STRIDX_FLOAT32_ARRAY > 255)
11464#error constant too large
11465#endif
11466#if (DUK_STRIDX_FLOAT64_ARRAY > 255)
11467#error constant too large
11468#endif
11469#if (DUK_STRIDX_EMPTY_STRING > 255)
11470#error constant too large
11471#endif
11472
11473/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
11474DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
11475 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
11505 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
11506 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
11507};
11508/*
11509 * Default allocation functions.
11511 * Assumes behavior such as malloc allowing zero size, yielding
11512 * a NULL or a unique pointer which is a no-op for free.
11513 */
11514
11515/* include removed: duk_internal.h */
11516
11517#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
11518DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
11519 void *res;
11520 DUK_UNREF(udata);
11521 res = DUK_ANSI_MALLOC(size);
11522 DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
11523 (unsigned long) size, (void *) res));
11524 return res;
11525}
11526
11527DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
11528 void *res;
11529 DUK_UNREF(udata);
11530 res = DUK_ANSI_REALLOC(ptr, newsize);
11531 DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
11532 (void *) ptr, (unsigned long) newsize, (void *) res));
11533 return res;
11534}
11535
11536DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
11537 DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
11538 DUK_UNREF(udata);
11539 DUK_ANSI_FREE(ptr);
11540}
11541#endif /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
11542/*
11543 * Buffer
11544 */
11545
11546/* include removed: duk_internal.h */
11547
11549 duk_hthread *thr = (duk_hthread *) ctx;
11551
11553
11555 DUK_ASSERT(h != NULL);
11556
11559 }
11560
11561 /* maximum size check is handled by callee */
11562 duk_hbuffer_resize(thr, h, new_size);
11563
11564 return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
11565}
11566
11568 duk_hthread *thr = (duk_hthread *) ctx;
11570 void *ptr;
11571 duk_size_t sz;
11572
11573 DUK_ASSERT(ctx != NULL);
11574
11576 DUK_ASSERT(h != NULL);
11577
11580 }
11582 /* Forget the previous allocation, setting size to 0 and alloc to
11583 * NULL. Caller is responsible for freeing the previous allocation.
11584 * Getting the allocation and clearing it is done in the same API
11585 * call to avoid any chance of a realloc.
11586 */
11589 if (out_size) {
11590 *out_size = sz;
11591 }
11594
11595 return ptr;
11596}
11597
11599 duk_hthread *thr = (duk_hthread *) ctx;
11601
11602 DUK_ASSERT(ctx != NULL);
11603
11605 DUK_ASSERT(h != NULL);
11606
11607 if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
11609 }
11611
11616 * Bytecode dump/load
11618 * The bytecode load primitive is more important performance-wise than the
11619 * dump primitive.
11620 *
11621 * Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
11622 * memory safe for invalid arguments - caller beware! There's little point
11623 * in trying to achieve memory safety unless bytecode instructions are also
11624 * validated which is not easy to do with indirect register references etc.
11625 */
11626
11627/* include removed: duk_internal.h */
11628
11629#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
11630
11631#define DUK__SER_MARKER 0xff
11632#define DUK__SER_VERSION 0x00
11633#define DUK__SER_STRING 0x00
11634#define DUK__SER_NUMBER 0x01
11635#define DUK__BYTECODE_INITIAL_ALLOC 256
11636
11637/*
11638 * Dump/load helpers, xxx_raw() helpers do no buffer checks
11639 */
11640
11641DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) {
11642 duk_uint32_t len;
11643
11644 len = DUK_RAW_READ_U32_BE(p);
11645 duk_push_lstring(ctx, (const char *) p, len);
11646 p += len;
11647 return p;
11648}
11649
11650DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) {
11651 duk_uint32_t len;
11652 duk_uint8_t *buf;
11653
11654 len = DUK_RAW_READ_U32_BE(p);
11655 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
11656 DUK_ASSERT(buf != NULL);
11657 DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);
11658 p += len;
11659 return p;
11660}
11661
11662DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
11663 duk_size_t len;
11664 duk_uint32_t tmp32;
11665
11666 DUK_ASSERT(h != NULL);
11667
11668 len = DUK_HSTRING_GET_BYTELEN(h);
11669 DUK_ASSERT(len <= 0xffffffffUL); /* string limits */
11670 tmp32 = (duk_uint32_t) len;
11671 DUK_RAW_WRITE_U32_BE(p, tmp32);
11672 DUK_MEMCPY((void *) p,
11673 (const void *) DUK_HSTRING_GET_DATA(h),
11674 len);
11675 p += len;
11676 return p;
11677}
11678
11679DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
11680 duk_size_t len;
11681 duk_uint32_t tmp32;
11682
11683 DUK_ASSERT(thr != NULL);
11684 DUK_ASSERT(h != NULL);
11685 DUK_UNREF(thr);
11686
11687 len = DUK_HBUFFER_GET_SIZE(h);
11688 DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */
11689 tmp32 = (duk_uint32_t) len;
11690 DUK_RAW_WRITE_U32_BE(p, tmp32);
11691 DUK_MEMCPY((void *) p,
11692 (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
11693 len);
11694 p += len;
11695 return p;
11696}
11697
11698DUK_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) {
11700 duk_tval *tv;
11701
11703 if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
11704 h_str = DUK_TVAL_GET_STRING(tv);
11705 DUK_ASSERT(h_str != NULL);
11706 } else {
11708 DUK_ASSERT(h_str != NULL);
11709 }
11710 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11711 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), p);
11712 p = duk__dump_hstring_raw(p, h_str);
11713 return p;
11714}
11715
11716DUK_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) {
11718
11720 if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
11721 duk_hbuffer *h_buf;
11722 h_buf = DUK_TVAL_GET_BUFFER(tv);
11723 DUK_ASSERT(h_buf != NULL);
11724 DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11725 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HBUFFER_GET_SIZE(h_buf), p);
11726 p = duk__dump_hbuffer_raw(thr, p, h_buf);
11727 } else {
11728 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11730 }
11731 return p;
11733
11734DUK_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) {
11735 duk_tval *tv;
11736 duk_uint32_t val;
11737
11739 if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
11740 val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
11741 } else {
11742 val = def_value;
11743 }
11744 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11745 DUK_RAW_WRITE_U32_BE(p, val);
11746 return p;
11747}
11748
11749DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
11750 duk_tval *tv;
11751
11753 if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
11754 duk_hobject *h;
11756
11757 h = DUK_TVAL_GET_OBJECT(tv);
11758 DUK_ASSERT(h != NULL);
11759
11760 /* We know _Varmap only has own properties so walk property
11761 * table directly. We also know _Varmap is dense and all
11762 * values are numbers; assert for these. GC and finalizers
11763 * shouldn't affect _Varmap so side effects should be fine.
11764 */
11765 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
11766 duk_hstring *key;
11767 duk_tval *tv_val;
11768 duk_uint32_t val;
11769
11770 key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
11771 DUK_ASSERT(key != NULL); /* _Varmap is dense */
11773 tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
11774 DUK_ASSERT(tv_val != NULL);
11775 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */
11776#if defined(DUK_USE_FASTINT)
11777 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
11778 DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */
11779 val = DUK_TVAL_GET_FASTINT_U32(tv_val);
11780#else
11781 val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
11782#endif
11783
11784 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11785 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(key) + 4, p);
11786 p = duk__dump_hstring_raw(p, key);
11787 DUK_RAW_WRITE_U32_BE(p, val);
11788 }
11789 }
11790 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11791 DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Varmap */
11792 return p;
11793}
11794
11795DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
11796 duk_tval *tv;
11797
11799 if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
11800 duk_hobject *h;
11802
11803 h = DUK_TVAL_GET_OBJECT(tv);
11804 DUK_ASSERT(h != NULL);
11805
11806 /* We know _Formals is dense and all entries will be in the
11807 * array part. GC and finalizers shouldn't affect _Formals
11808 * so side effects should be fine.
11809 */
11810 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
11811 duk_tval *tv_val;
11812 duk_hstring *varname;
11813
11814 tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i);
11815 DUK_ASSERT(tv_val != NULL);
11816 if (DUK_TVAL_IS_STRING(tv_val)) {
11817 /* Array is dense and contains only strings, but ASIZE may
11818 * be larger than used part and there are UNUSED entries.
11819 */
11820 varname = DUK_TVAL_GET_STRING(tv_val);
11821 DUK_ASSERT(varname != NULL);
11822
11823 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11824 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p);
11825 p = duk__dump_hstring_raw(p, varname);
11826 }
11827 }
11828 }
11829 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11830 DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Formals */
11831 return p;
11832}
11833
11834static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
11835 duk_hthread *thr;
11836 duk_tval *tv, *tv_end;
11837 duk_instr_t *ins, *ins_end;
11838 duk_hobject **fn, **fn_end;
11839 duk_hstring *h_str;
11840 duk_uint32_t count_instr;
11841 duk_uint32_t tmp32;
11842 duk_uint16_t tmp16;
11843 duk_double_t d;
11844
11845 thr = (duk_hthread *) ctx;
11846 DUK_UNREF(ctx);
11847 DUK_UNREF(thr);
11848
11849 DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
11850 "consts=[%p,%p[ (%ld bytes, %ld items), "
11851 "funcs=[%p,%p[ (%ld bytes, %ld items), "
11852 "code=[%p,%p[ (%ld bytes, %ld items)",
11853 (void *) func,
11854 (void *) p,
11855 (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func),
11856 (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func),
11859 (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func),
11860 (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func),
11861 (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(thr->heap, func),
11863 (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func),
11864 (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func),
11865 (long) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(thr->heap, func),
11866 (long) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func)));
11867
11868 DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */
11869 count_instr = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func);
11870 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr * 4, p);
11871
11872 /* Fixed header info. */
11873 tmp32 = count_instr;
11874 DUK_RAW_WRITE_U32_BE(p, tmp32);
11875 tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func);
11876 DUK_RAW_WRITE_U32_BE(p, tmp32);
11877 tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func);
11878 DUK_RAW_WRITE_U32_BE(p, tmp32);
11879 tmp16 = func->nregs;
11880 DUK_RAW_WRITE_U16_BE(p, tmp16);
11881 tmp16 = func->nargs;
11882 DUK_RAW_WRITE_U16_BE(p, tmp16);
11883#if defined(DUK_USE_DEBUGGER_SUPPORT)
11884 tmp32 = func->start_line;
11885 DUK_RAW_WRITE_U32_BE(p, tmp32);
11886 tmp32 = func->end_line;
11887 DUK_RAW_WRITE_U32_BE(p, tmp32);
11888#else
11891#endif
11892 tmp32 = ((duk_heaphdr *) func)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK;
11893 DUK_RAW_WRITE_U32_BE(p, tmp32);
11894
11895 /* Bytecode instructions: endian conversion needed unless
11896 * platform is big endian.
11897 */
11898 ins = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func);
11899 ins_end = DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func);
11900 DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
11901#if defined(DUK_USE_INTEGER_BE)
11902 DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));
11903 p += (size_t) (ins_end - ins);
11904#else
11905 while (ins != ins_end) {
11906 tmp32 = (duk_uint32_t) (*ins);
11907 DUK_RAW_WRITE_U32_BE(p, tmp32);
11908 ins++;
11909 }
11910#endif
11911
11912 /* Constants: variable size encoding. */
11914 tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func);
11915 while (tv != tv_end) {
11916 /* constants are strings or numbers now */
11918 DUK_TVAL_IS_NUMBER(tv));
11919
11920 if (DUK_TVAL_IS_STRING(tv)) {
11921 h_str = DUK_TVAL_GET_STRING(tv);
11922 DUK_ASSERT(h_str != NULL);
11923 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11924 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + DUK_HSTRING_GET_BYTELEN(h_str), p),
11925 *p++ = DUK__SER_STRING;
11926 p = duk__dump_hstring_raw(p, h_str);
11927 } else {
11929 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p);
11930 *p++ = DUK__SER_NUMBER;
11931 d = DUK_TVAL_GET_NUMBER(tv);
11933 }
11934 tv++;
11935 }
11936
11937 /* Inner functions recursively. */
11939 fn_end = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func);
11940 while (fn != fn_end) {
11941 /* XXX: This causes recursion up to inner function depth
11942 * which is normally not an issue, e.g. mark-and-sweep uses
11943 * a recursion limiter to avoid C stack issues. Avoiding
11944 * this would mean some sort of a work list or just refusing
11945 * to serialize deep functions.
11946 */
11948 p = duk__dump_func(ctx, (duk_hcompiledfunction *) *fn, bw_ctx, p);
11949 fn++;
11950 }
11951
11952 /* Object extra properties.
11953 *
11954 * There are some difference between function templates and functions.
11955 * For example, function templates don't have .length and nargs is
11956 * normally used to instantiate the functions.
11957 */
11958
11959 p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
11960 p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
11961 p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
11962 p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
11963 p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
11964 p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
11965
11966 DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
11967
11968 return p;
11969}
11970
11971/* Load a function from bytecode. The function object returned here must
11972 * match what is created by duk_js_push_closure() with respect to its flags,
11973 * properties, etc.
11974 *
11975 * NOTE: there are intentionally no input buffer length / bound checks.
11976 * Adding them would be easy but wouldn't ensure memory safety as untrusted
11977 * or broken bytecode is unsafe during execution unless the opcodes themselves
11978 * are validated (which is quite complex, especially for indirect opcodes).
11979 */
11980
11981#define DUK__ASSERT_LEFT(n) do { \
11982 DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
11983 } while (0)
11984
11985static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end) {
11986 duk_hthread *thr;
11987 duk_hcompiledfunction *h_fun;
11988 duk_hbuffer *h_data;
11989 duk_size_t data_size;
11990 duk_uint32_t count_instr, count_const, count_funcs;
11991 duk_uint32_t n;
11992 duk_uint32_t tmp32;
11993 duk_small_uint_t const_type;
11994 duk_uint8_t *fun_data;
11995 duk_uint8_t *q;
11996 duk_idx_t idx_base;
11997 duk_tval *tv1;
11998 duk_uarridx_t arr_idx;
11999
12000 /* XXX: There's some overlap with duk_js_closure() here, but
12001 * seems difficult to share code. Ensure that the final function
12002 * looks the same as created by duk_js_closure().
12003 */
12004
12005 DUK_ASSERT(ctx != NULL);
12006 thr = (duk_hthread *) ctx;
12007
12008 DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
12009
12010 DUK__ASSERT_LEFT(3 * 4);
12011 count_instr = DUK_RAW_READ_U32_BE(p);
12012 count_const = DUK_RAW_READ_U32_BE(p);
12013 count_funcs = DUK_RAW_READ_U32_BE(p);
12014
12015 data_size = sizeof(duk_tval) * count_const +
12016 sizeof(duk_hobject *) * count_funcs +
12017 sizeof(duk_instr_t) * count_instr;
12018
12019 DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
12020 (long) count_instr, (long) count_const,
12021 (long) count_const, (long) data_size));
12022
12023 /* Value stack is used to ensure reachability of constants and
12024 * inner functions being loaded. Require enough space to handle
12025 * large functions correctly.
12026 */
12027 duk_require_stack(ctx, 2 + count_const + count_funcs);
12028 idx_base = duk_get_top(ctx);
12029
12030 /* Push function object, init flags etc. This must match
12031 * duk_js_push_closure() quite carefully.
12032 */
12034 h_fun = duk_get_hcompiledfunction(ctx, -1);
12035 DUK_ASSERT(h_fun != NULL);
12040
12041 h_fun->nregs = DUK_RAW_READ_U16_BE(p);
12042 h_fun->nargs = DUK_RAW_READ_U16_BE(p);
12043#if defined(DUK_USE_DEBUGGER_SUPPORT)
12044 h_fun->start_line = DUK_RAW_READ_U32_BE(p);
12045 h_fun->end_line = DUK_RAW_READ_U32_BE(p);
12046#else
12047 p += 8; /* skip line info */
12048#endif
12049
12050 /* duk_hcompiledfunction flags; quite version specific */
12051 tmp32 = DUK_RAW_READ_U32_BE(p);
12052 DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);
12053
12054 /* standard prototype */
12056
12057 /* assert just a few critical flags */
12066
12067 /* Create function 'data' buffer but don't attach it yet. */
12068 fun_data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, data_size);
12069 DUK_ASSERT(fun_data != NULL);
12070
12071 /* Load bytecode instructions. */
12072 DUK_ASSERT(sizeof(duk_instr_t) == 4);
12073 DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
12074#if defined(DUK_USE_INTEGER_BE)
12075 q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12076 DUK_MEMCPY((void *) q,
12077 (const void *) p,
12078 sizeof(duk_instr_t) * count_instr);
12079 p += sizeof(duk_instr_t) * count_instr;
12080#else
12081 q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12082 for (n = count_instr; n > 0; n--) {
12083 *((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
12084 q += sizeof(duk_instr_t);
12085 }
12086#endif
12087
12088 /* Load constants onto value stack but don't yet copy to buffer. */
12089 for (n = count_const; n > 0; n--) {
12091 const_type = DUK_RAW_READ_U8(p);
12092 switch (const_type) {
12093 case DUK__SER_STRING: {
12094 p = duk__load_string_raw(ctx, p);
12095 break;
12096 }
12097 case DUK__SER_NUMBER: {
12098 /* Important to do a fastint check so that constants are
12099 * properly read back as fastints.
12100 */
12101 duk_tval tv_tmp;
12102 duk_double_t val;
12104 val = DUK_RAW_READ_DOUBLE_BE(p);
12105 DUK_TVAL_SET_NUMBER_CHKFAST(&tv_tmp, val);
12106 duk_push_tval(ctx, &tv_tmp);
12107 break;
12108 }
12109 default: {
12110 goto format_error;
12111 }
12112 }
12113 }
12114
12115 /* Load inner functions to value stack, but don't yet copy to buffer. */
12116 for (n = count_funcs; n > 0; n--) {
12117 p = duk__load_func(ctx, p, p_end);
12118 if (p == NULL) {
12119 goto format_error;
12120 }
12121 }
12122
12123 /* With constants and inner functions on value stack, we can now
12124 * atomically finish the function 'data' buffer, bump refcounts,
12125 * etc.
12126 *
12127 * Here we take advantage of the value stack being just a duk_tval
12128 * array: we can just memcpy() the constants as long as we incref
12129 * them afterwards.
12130 */
12131
12132 h_data = (duk_hbuffer *) duk_get_hbuffer(ctx, idx_base + 1);
12133 DUK_ASSERT(h_data != NULL);
12135 DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_fun, h_data);
12136 DUK_HBUFFER_INCREF(thr, h_data);
12137
12138 tv1 = duk_get_tval(ctx, idx_base + 2); /* may be NULL if no constants or inner funcs */
12139 DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
12140
12141 q = fun_data;
12142 if (count_const > 0) {
12143 /* Explicit zero size check to avoid NULL 'tv1'. */
12144 DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
12145 for (n = count_const; n > 0; n--) {
12146 DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */
12147 q += sizeof(duk_tval);
12148 }
12149 tv1 += count_const;
12150 }
12151
12152 DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
12153 for (n = count_funcs; n > 0; n--) {
12154 duk_hobject *h_obj;
12155
12157 h_obj = DUK_TVAL_GET_OBJECT(tv1);
12158 DUK_ASSERT(h_obj != NULL);
12159 tv1++;
12160 DUK_HOBJECT_INCREF(thr, h_obj);
12161
12162 *((duk_hobject **) (void *) q) = h_obj;
12163 q += sizeof(duk_hobject *);
12164 }
12165
12166 DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
12167
12168 /* The function object is now reachable and refcounts are fine,
12169 * so we can pop off all the temporaries.
12170 */
12171 DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(ctx, idx_base)));
12172 duk_set_top(ctx, idx_base + 1);
12173
12174 /* Setup function properties. */
12175 tmp32 = DUK_RAW_READ_U32_BE(p);
12176 duk_push_u32(ctx, tmp32);
12178
12179 p = duk__load_string_raw(ctx, p);
12181 /* Original function instance/template had NAMEBINDING.
12182 * Must create a lexical environment on loading to allow
12183 * recursive functions like 'function foo() { foo(); }'.
12184 */
12186
12191 proto);
12192 duk_dup(ctx, -2); /* -> [ func funcname env funcname ] */
12193 duk_dup(ctx, idx_base); /* -> [ func funcname env funcname func ] */
12194 duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */
12196 /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
12197 * will be ignored anyway
12198 */
12199 }
12201
12202 p = duk__load_string_raw(ctx, p);
12204
12205 duk_push_object(ctx);
12206 duk_dup(ctx, -2);
12207 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */
12208 duk_compact(ctx, -1);
12210
12211 p = duk__load_buffer_raw(ctx, p);
12213
12214 duk_push_object(ctx); /* _Varmap */
12215 for (;;) {
12216 /* XXX: awkward */
12217 p = duk__load_string_raw(ctx, p);
12218 if (duk_get_length(ctx, -1) == 0) {
12219 duk_pop(ctx);
12220 break;
12221 }
12222 tmp32 = DUK_RAW_READ_U32_BE(p);
12223 duk_push_u32(ctx, tmp32);
12224 duk_put_prop(ctx, -3);
12225 }
12226 duk_compact(ctx, -1);
12228
12229 duk_push_array(ctx); /* _Formals */
12230 for (arr_idx = 0; ; arr_idx++) {
12231 /* XXX: awkward */
12232 p = duk__load_string_raw(ctx, p);
12233 if (duk_get_length(ctx, -1) == 0) {
12235 break;
12236 }
12237 duk_put_prop_index(ctx, -2, arr_idx);
12238 }
12239 duk_compact(ctx, -1);
12241
12242 /* Return with final function pushed on stack top. */
12243 DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, -1)));
12244 DUK_ASSERT_TOP(ctx, idx_base + 1);
12245 return p;
12246
12247 format_error:
12248 return NULL;
12249}
12250
12252 duk_hthread *thr;
12254 duk_bufwriter_ctx bw_ctx_alloc;
12255 duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
12256 duk_uint8_t *p;
12257
12258 DUK_ASSERT(ctx != NULL);
12259 thr = (duk_hthread *) ctx;
12260
12261 /* Bound functions don't have all properties so we'd either need to
12262 * lookup the non-bound target function or reject bound functions.
12263 * For now, bound functions are rejected.
12264 */
12265 func = duk_require_hcompiledfunction(ctx, -1);
12266 DUK_ASSERT(func != NULL);
12269 /* Estimating the result size beforehand would be costly, so
12270 * start with a reasonable size and extend as needed.
12271 */
12273 p = DUK_BW_GET_PTR(thr, bw_ctx);
12274 *p++ = DUK__SER_MARKER;
12275 *p++ = DUK__SER_VERSION;
12276 p = duk__dump_func(ctx, func, bw_ctx, p);
12277 DUK_BW_SET_PTR(thr, bw_ctx, p);
12278 DUK_BW_COMPACT(thr, bw_ctx);
12279
12280 DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1)));
12281
12282 duk_remove(ctx, -2); /* [ ... func buf ] -> [ ... buf ] */
12283}
12284
12286 duk_hthread *thr;
12287 duk_uint8_t *p_buf, *p, *p_end;
12288 duk_size_t sz;
12289
12290 DUK_ASSERT(ctx != NULL);
12291 thr = (duk_hthread *) ctx;
12292 DUK_UNREF(ctx);
12293
12294 p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz);
12295 DUK_ASSERT(p_buf != NULL);
12296
12297 /* The caller is responsible for being sure that bytecode being loaded
12298 * is valid and trusted. Invalid bytecode can cause memory unsafe
12299 * behavior directly during loading or later during bytecode execution
12300 * (instruction validation would be quite complex to implement).
12301 *
12302 * This signature check is the only sanity check for detecting
12303 * accidental invalid inputs. The initial 0xFF byte ensures no
12304 * ordinary string will be accepted by accident.
12305 */
12306 p = p_buf;
12307 p_end = p_buf + sz;
12308 if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) {
12309 goto format_error;
12310 }
12311 p += 2;
12312
12313 p = duk__load_func(ctx, p, p_end);
12314 if (p == NULL) {
12315 goto format_error;
12316 }
12317
12318 duk_remove(ctx, -2); /* [ ... buf func ] -> [ ... func ] */
12319 return;
12320
12321 format_error:
12323}
12324
12325#undef DUK__SER_MARKER
12326#undef DUK__SER_VERSION
12327#undef DUK__SER_STRING
12328#undef DUK__SER_NUMBER
12329#undef DUK__BYTECODE_INITIAL_ALLOC
12330
12331#else /* DUK_USE_BYTECODE_DUMP_SUPPORT */
12332
12335}
12339}
12340
12341#endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */
12342/*
12343 * Calls.
12344 *
12345 * Protected variants should avoid ever throwing an error.
12346 */
12347
12348/* include removed: duk_internal.h */
12349
12350/* Prepare value stack for a method call through an object property.
12351 * May currently throw an error e.g. when getting the property.
12352 */
12353DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs) {
12355
12356 DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_index=%ld, nargs=%ld, stacktop=%ld",
12357 (long) normalized_obj_index, (long) nargs, (long) duk_get_top(ctx)));
12358
12359 /* [... key arg1 ... argN] */
12360
12361 /* duplicate key */
12362 duk_dup(ctx, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */
12363 duk_get_prop(ctx, normalized_obj_index);
12364
12365 DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
12366
12367 /* [... key arg1 ... argN func] */
12368
12369 duk_replace(ctx, -nargs - 2);
12370
12371 /* [... func arg1 ... argN] */
12372
12373 duk_dup(ctx, normalized_obj_index);
12374 duk_insert(ctx, -nargs - 1);
12375
12376 /* [... func this arg1 ... argN] */
12377}
12378
12379DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) {
12380 duk_hthread *thr = (duk_hthread *) ctx;
12381 duk_small_uint_t call_flags;
12382 duk_idx_t idx_func;
12383
12385 DUK_ASSERT(thr != NULL);
12386
12387 idx_func = duk_get_top(ctx) - nargs - 1;
12388 if (idx_func < 0 || nargs < 0) {
12389 /* note that we can't reliably pop anything here */
12391 }
12392
12393 /* XXX: awkward; we assume there is space for this, overwrite
12394 * directly instead?
12395 */
12396 duk_push_undefined(ctx);
12397 duk_insert(ctx, idx_func + 1);
12398
12399 call_flags = 0; /* not protected, respect reclimit, not constructor */
12400
12401 duk_handle_call_unprotected(thr, /* thread */
12402 nargs, /* num_stack_args */
12403 call_flags); /* call_flags */
12404}
12405
12407 duk_hthread *thr = (duk_hthread *) ctx;
12408 duk_small_uint_t call_flags;
12409 duk_idx_t idx_func;
12412 DUK_ASSERT(thr != NULL);
12413
12414 idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */
12415 if (idx_func < 0 || nargs < 0) {
12416 /* note that we can't reliably pop anything here */
12418 }
12419
12420 call_flags = 0; /* not protected, respect reclimit, not constructor */
12421
12422 duk_handle_call_unprotected(thr, /* thread */
12423 nargs, /* num_stack_args */
12424 call_flags); /* call_flags */
12425}
12426
12428 /*
12429 * XXX: if duk_handle_call() took values through indices, this could be
12430 * made much more sensible. However, duk_handle_call() needs to fudge
12431 * the 'this' and 'func' values to handle bound function chains, which
12432 * is now done "in-place", so this is not a trivial change.
12433 */
12434
12436
12437 obj_index = duk_require_normalize_index(ctx, obj_index); /* make absolute */
12438
12439 duk__call_prop_prep_stack(ctx, obj_index, nargs);
12440
12441 duk_call_method(ctx, nargs);
12442}
12443
12445 duk_hthread *thr = (duk_hthread *) ctx;
12446 duk_small_uint_t call_flags;
12447 duk_idx_t idx_func;
12448 duk_int_t rc;
12449
12451 DUK_ASSERT(thr != NULL);
12452
12453 idx_func = duk_get_top(ctx) - nargs - 1; /* must work for nargs <= 0 */
12454 if (idx_func < 0 || nargs < 0) {
12455 /* We can't reliably pop anything here because the stack input
12456 * shape is incorrect. So we throw an error; if the caller has
12457 * no catch point for this, a fatal error will occur. Another
12458 * alternative would be to just return an error. But then the
12459 * stack would be in an unknown state which might cause some
12460 * very hard to diagnose problems later on. Also note that even
12461 * if we did not throw an error here, the underlying call handler
12462 * might STILL throw an out-of-memory error or some other internal
12463 * fatal error.
12464 */
12466 return DUK_EXEC_ERROR; /* unreachable */
12467 }
12468
12469 /* awkward; we assume there is space for this */
12470 duk_push_undefined(ctx);
12471 duk_insert(ctx, idx_func + 1);
12472
12473 call_flags = 0; /* respect reclimit, not constructor */
12474
12475 rc = duk_handle_call_protected(thr, /* thread */
12476 nargs, /* num_stack_args */
12477 call_flags); /* call_flags */
12478
12479 return rc;
12480}
12481
12483 duk_hthread *thr = (duk_hthread *) ctx;
12484 duk_small_uint_t call_flags;
12485 duk_idx_t idx_func;
12486 duk_int_t rc;
12487
12489 DUK_ASSERT(thr != NULL);
12491 idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */
12492 if (idx_func < 0 || nargs < 0) {
12493 /* See comments in duk_pcall(). */
12495 return DUK_EXEC_ERROR; /* unreachable */
12496 }
12497
12498 call_flags = 0; /* respect reclimit, not constructor */
12499
12500 rc = duk_handle_call_protected(thr, /* thread */
12501 nargs, /* num_stack_args */
12502 call_flags); /* call_flags */
12503
12504 return rc;
12505}
12506
12508 duk_idx_t obj_index;
12509 duk_idx_t nargs;
12511 /* Get the original arguments. Note that obj_index may be a relative
12512 * index so the stack must have the same top when we use it.
12513 */
12514
12516
12517 obj_index = (duk_idx_t) duk_get_int(ctx, -2);
12518 nargs = (duk_idx_t) duk_get_int(ctx, -1);
12519 duk_pop_2(ctx);
12520
12521 obj_index = duk_require_normalize_index(ctx, obj_index); /* make absolute */
12522 duk__call_prop_prep_stack(ctx, obj_index, nargs);
12523 duk_call_method(ctx, nargs);
12524 return 1;
12525}
12526
12529 * Must be careful to catch errors related to value stack manipulation
12530 * and property lookup, not just the call itself.
12531 */
12532
12534
12535 duk_push_idx(ctx, obj_index);
12536 duk_push_idx(ctx, nargs);
12537
12538 /* Inputs: explicit arguments (nargs), +1 for key, +2 for obj_index/nargs passing.
12539 * If the value stack does not contain enough args, an error is thrown; this matches
12540 * behavior of the other protected call API functions.
12541 */
12542 return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 1 /*nrets*/);
12543}
12544
12546 duk_hthread *thr = (duk_hthread *) ctx;
12547 duk_int_t rc;
12548
12550 DUK_ASSERT(thr != NULL);
12551
12552 if (duk_get_top(ctx) < nargs || nrets < 0) {
12553 /* See comments in duk_pcall(). */
12555 return DUK_EXEC_ERROR; /* unreachable */
12556 }
12557
12558 rc = duk_handle_safe_call(thr, /* thread */
12559 func, /* func */
12560 nargs, /* num_stack_args */
12561 nrets); /* num_stack_res */
12562
12563 return rc;
12564}
12565
12566DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) {
12567 /*
12568 * There are two [[Construct]] operations in the specification:
12569 *
12570 * - E5 Section 13.2.2: for Function objects
12571 * - E5 Section 15.3.4.5.2: for "bound" Function objects
12572 *
12573 * The chain of bound functions is resolved in Section 15.3.4.5.2,
12574 * with arguments "piling up" until the [[Construct]] internal
12575 * method is called on the final, actual Function object. Note
12576 * that the "prototype" property is looked up *only* from the
12577 * final object, *before* calling the constructor.
12578 *
12579 * Currently we follow the bound function chain here to get the
12580 * "prototype" property value from the final, non-bound function.
12581 * However, we let duk_handle_call() handle the argument "piling"
12582 * when the constructor is called. The bound function chain is
12583 * thus now processed twice.
12584 *
12585 * When constructing new Array instances, an unnecessary object is
12586 * created and discarded now: the standard [[Construct]] creates an
12587 * object, and calls the Array constructor. The Array constructor
12588 * returns an Array instance, which is used as the result value for
12589 * the "new" operation; the object created before the Array constructor
12590 * call is discarded.
12591 *
12592 * This would be easy to fix, e.g. by knowing that the Array constructor
12593 * will always create a replacement object and skip creating the fallback
12594 * object in that case.
12595 *
12596 * Note: functions called via "new" need to know they are called as a
12597 * constructor. For instance, built-in constructors behave differently
12598 * depending on how they are called.
12599 */
12600
12601 /* XXX: merge this with duk_js_call.c, as this function implements
12602 * core semantics (or perhaps merge the two files altogether).
12603 */
12604
12605 duk_hthread *thr = (duk_hthread *) ctx;
12607 duk_hobject *cons;
12608 duk_hobject *fallback;
12609 duk_idx_t idx_cons;
12610 duk_small_uint_t call_flags;
12611
12613
12614 /* [... constructor arg1 ... argN] */
12615
12616 idx_cons = duk_require_normalize_index(ctx, -nargs - 1);
12617
12618 DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld",
12619 (long) duk_get_top(ctx), (long) nargs, (long) idx_cons));
12620
12621 /* XXX: code duplication */
12622
12623 /*
12624 * Figure out the final, non-bound constructor, to get "prototype"
12625 * property.
12626 */
12627
12628 duk_dup(ctx, idx_cons);
12629 for (;;) {
12630 duk_tval *tv;
12631 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
12632 DUK_ASSERT(tv != NULL);
12633
12634 if (DUK_TVAL_IS_OBJECT(tv)) {
12635 cons = DUK_TVAL_GET_OBJECT(tv);
12636 DUK_ASSERT(cons != NULL);
12638 /* Checking callability of the immediate target
12639 * is important, same for constructability.
12640 * Checking it for functions down the bound
12641 * function chain is not strictly necessary
12642 * because .bind() should normally reject them.
12643 * But it's good to check anyway because it's
12644 * technically possible to edit the bound function
12645 * chain via internal keys.
12646 */
12647 goto not_constructable;
12648 }
12649 if (!DUK_HOBJECT_HAS_BOUND(cons)) {
12650 break;
12651 }
12652 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
12653 /* Lightfuncs cannot be bound. */
12654 break;
12655 } else {
12656 /* Anything else is not constructable. */
12657 goto not_constructable;
12658 }
12659 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [... cons target] */
12660 duk_remove(ctx, -2); /* -> [... target] */
12661 }
12662 DUK_ASSERT(duk_is_callable(ctx, -1));
12663 DUK_ASSERT(duk_is_lightfunc(ctx, -1) ||
12664 (duk_get_hobject(ctx, -1) != NULL && !DUK_HOBJECT_HAS_BOUND(duk_get_hobject(ctx, -1))));
12665
12666 /* [... constructor arg1 ... argN final_cons] */
12667
12668 /*
12669 * Create "fallback" object to be used as the object instance,
12670 * unless the constructor returns a replacement value.
12671 * Its internal prototype needs to be set based on "prototype"
12672 * property of the constructor.
12673 */
12674
12675 duk_push_object(ctx); /* class Object, extensible */
12676
12677 /* [... constructor arg1 ... argN final_cons fallback] */
12678
12680 proto = duk_get_hobject(ctx, -1);
12681 if (!proto) {
12682 DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
12683 "-> leave standard Object prototype as fallback prototype"));
12684 } else {
12685 DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
12686 "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
12687 fallback = duk_get_hobject(ctx, -2);
12688 DUK_ASSERT(fallback != NULL);
12690 }
12691 duk_pop(ctx);
12692
12693 /* [... constructor arg1 ... argN final_cons fallback] */
12694
12695 /*
12696 * Manipulate callstack for the call.
12697 */
12698
12699 duk_dup_top(ctx);
12700 duk_insert(ctx, idx_cons + 1); /* use fallback as 'this' value */
12701 duk_insert(ctx, idx_cons); /* also stash it before constructor,
12702 * in case we need it (as the fallback value)
12703 */
12704 duk_pop(ctx); /* pop final_cons */
12705
12706
12707 /* [... fallback constructor fallback(this) arg1 ... argN];
12708 * Note: idx_cons points to first 'fallback', not 'constructor'.
12709 */
12710
12711 DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, idx_cons+2 (fallback/this) -> %!T, "
12712 "nargs=%ld, top=%ld",
12713 (duk_tval *) duk_get_tval(ctx, idx_cons + 1),
12714 (duk_tval *) duk_get_tval(ctx, idx_cons + 2),
12715 (long) nargs,
12716 (long) duk_get_top(ctx)));
12717
12718 /*
12719 * Call the constructor function (called in "constructor mode").
12720 */
12721
12722 call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL; /* not protected, respect reclimit, is a constructor call */
12723
12724 duk_handle_call_unprotected(thr, /* thread */
12725 nargs, /* num_stack_args */
12726 call_flags); /* call_flags */
12727
12728 /* [... fallback retval] */
12729
12730 DUK_DDD(DUK_DDDPRINT("constructor call finished, fallback=%!iT, retval=%!iT",
12731 (duk_tval *) duk_get_tval(ctx, -2),
12732 (duk_tval *) duk_get_tval(ctx, -1)));
12733
12734 /*
12735 * Determine whether to use the constructor return value as the created
12736 * object instance or not.
12737 */
12738
12739 if (duk_is_object(ctx, -1)) {
12740 duk_remove(ctx, -2);
12741 } else {
12742 duk_pop(ctx);
12743 }
12744
12745 /*
12746 * Augment created errors upon creation (not when they are thrown or
12747 * rethrown). __FILE__ and __LINE__ are not desirable here; the call
12748 * stack reflects the caller which is correct.
12749 */
12750
12751#ifdef DUK_USE_AUGMENT_ERROR_CREATE
12753 duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
12754#endif
12755
12756 /* [... retval] */
12758 return;
12759
12760 not_constructable:
12762}
12763
12765 duk_uint_t nargs;
12766
12767 nargs = duk_to_uint(ctx, -1);
12768 duk_pop(ctx);
12769
12770 duk_new(ctx, nargs);
12771 return 1;
12772}
12773
12776
12778
12779 /* For now, just use duk_safe_call() to wrap duk_new(). We can't
12780 * simply use a protected duk_handle_call() because there's post
12781 * processing which might throw. It should be possible to ensure
12782 * the post processing never throws (except in internal errors and
12783 * out of memory etc which are always allowed) and then remove this
12784 * wrapper.
12785 */
12786
12787 duk_push_uint(ctx, nargs);
12788 rc = duk_safe_call(ctx, duk__pnew_helper, nargs + 2 /*nargs*/, 1 /*nrets*/);
12789 return rc;
12790}
12791
12793 duk_hthread *thr = (duk_hthread *) ctx;
12794 duk_activation *act;
12795
12797 DUK_ASSERT(thr != NULL);
12799
12801 DUK_ASSERT(act != NULL); /* because callstack_top > 0 */
12802 return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
12803}
12804
12806 duk_hthread *thr = (duk_hthread *) ctx;
12807 duk_activation *act;
12808
12809 /* For user code this could just return 1 (strict) always
12810 * because all Duktape/C functions are considered strict,
12811 * and strict is also the default when nothing is running.
12812 * However, Duktape may call this function internally when
12813 * the current activation is an Ecmascript function, so
12814 * this cannot be replaced by a 'return 1' without fixing
12815 * the internal call sites.
12816 */
12819 DUK_ASSERT(thr != NULL);
12821
12823 if (act == NULL) {
12824 /* Strict by default. */
12825 return 1;
12826 }
12827 return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
12828}
12829
12830/*
12831 * Duktape/C function magic
12832 */
12833
12835 duk_hthread *thr = (duk_hthread *) ctx;
12836 duk_activation *act;
12837 duk_hobject *func;
12838
12840 DUK_ASSERT(thr != NULL);
12842
12844 if (act) {
12845 func = DUK_ACT_GET_FUNC(act);
12846 if (!func) {
12847 duk_tval *tv = &act->tv_func;
12848 duk_small_uint_t lf_flags;
12849 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
12850 return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
12851 }
12852 DUK_ASSERT(func != NULL);
12853
12856 return (duk_int_t) nf->magic;
12857 }
12858 }
12859 return 0;
12860}
12861
12863 duk_hthread *thr = (duk_hthread *) ctx;
12864 duk_tval *tv;
12865 duk_hobject *h;
12866
12868
12869 tv = duk_require_tval(ctx, index);
12870 if (DUK_TVAL_IS_OBJECT(tv)) {
12872 DUK_ASSERT(h != NULL);
12874 goto type_error;
12875 }
12876 return (duk_int_t) ((duk_hnativefunction *) h)->magic;
12877 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
12879 return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
12880 }
12881
12882 /* fall through */
12883 type_error:
12885 return 0;
12886}
12887
12890
12892
12895 nf->magic = (duk_int16_t) magic;
12896}
12897/*
12898 * Encoding and decoding basic formats: hex, base64.
12899 *
12900 * These are in-place operations which may allow an optimized implementation.
12901 *
12902 * Base-64: https://tools.ietf.org/html/rfc4648#section-4
12903 */
12905/* include removed: duk_internal.h */
12906
12907/* Shared handling for encode/decode argument. Fast path handling for
12908 * buffer and string values because they're the most common. In particular,
12909 * avoid creating a temporary string or buffer when possible.
12910 */
12911DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
12912 DUK_ASSERT(duk_is_valid_index(ctx, index)); /* checked by caller */
12913 if (duk_is_buffer(ctx, index)) {
12914 return (const duk_uint8_t *) duk_get_buffer(ctx, index, out_len);
12915 } else {
12916 return (const duk_uint8_t *) duk_to_lstring(ctx, index, out_len);
12917 }
12918}
12919
12920#if defined(DUK_USE_BASE64_FASTPATH)
12921DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
12922 duk_uint_t t;
12923 duk_size_t n_full, n_full3, n_final;
12924 const duk_uint8_t *src_end_fast;
12925
12926 n_full = srclen / 3; /* full 3-byte -> 4-char conversions */
12927 n_full3 = n_full * 3;
12928 n_final = srclen - n_full3;
12929 DUK_ASSERT_DISABLE(n_final >= 0);
12930 DUK_ASSERT(n_final <= 2);
12931
12932 src_end_fast = src + n_full3;
12933 while (DUK_UNLIKELY(src != src_end_fast)) {
12934 t = (duk_uint_t) (*src++);
12935 t = (t << 8) + (duk_uint_t) (*src++);
12936 t = (t << 8) + (duk_uint_t) (*src++);
12937
12938 *dst++ = duk_base64_enctab[t >> 18];
12939 *dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
12940 *dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
12941 *dst++ = duk_base64_enctab[t & 0x3f];
12942
12943#if 0 /* Tested: not faster on x64 */
12944 /* aaaaaabb bbbbcccc ccdddddd */
12945 dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
12946 dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];
12947 dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];
12948 dst[3] = duk_base64_enctab[src[2] & 0x3f];
12949 src += 3; dst += 4;
12950#endif
12951 }
12952
12953 switch (n_final) {
12954 /* case 0: nop */
12955 case 1: {
12956 /* XX== */
12957 t = (duk_uint_t) (*src++);
12958 *dst++ = duk_base64_enctab[t >> 2]; /* XXXXXX-- */
12959 *dst++ = duk_base64_enctab[(t << 4) & 0x3f]; /* ------XX */
12960 *dst++ = DUK_ASC_EQUALS;
12961 *dst++ = DUK_ASC_EQUALS;
12962 break;
12963 }
12964 case 2: {
12965 /* XXX= */
12966 t = (duk_uint_t) (*src++);
12967 t = (t << 8) + (duk_uint_t) (*src++);
12968 *dst++ = duk_base64_enctab[t >> 10]; /* XXXXXX-- -------- */
12969 *dst++ = duk_base64_enctab[(t >> 4) & 0x3f]; /* ------XX XXXX---- */
12970 *dst++ = duk_base64_enctab[(t << 2) & 0x3f]; /* -------- ----XXXX */
12971 *dst++ = DUK_ASC_EQUALS;
12972 break;
12973 }
12974 }
12975}
12976#else /* DUK_USE_BASE64_FASTPATH */
12977DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
12978 duk_small_uint_t i, snip;
12979 duk_uint_t t;
12980 duk_uint_fast8_t x, y;
12981 const duk_uint8_t *src_end;
12982
12983 src_end = src + srclen;
12984
12985 while (src < src_end) {
12986 /* read 3 bytes into 't', padded by zero */
12987 snip = 4;
12988 t = 0;
12989 for (i = 0; i < 3; i++) {
12990 t = t << 8;
12991 if (src >= src_end) {
12992 snip--;
12993 } else {
12994 t += (duk_uint_t) (*src++);
12995 }
12996 }
12997
12998 /*
12999 * Missing bytes snip base64 example
13000 * 0 4 XXXX
13001 * 1 3 XXX=
13002 * 2 2 XX==
13003 */
13004
13005 DUK_ASSERT(snip >= 2 && snip <= 4);
13006
13007 for (i = 0; i < 4; i++) {
13008 x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
13009 t = t << 6;
13010
13011 /* A straightforward 64-byte lookup would be faster
13012 * and cleaner, but this is shorter.
13013 */
13014 if (i >= snip) {
13015 y = '=';
13016 } else if (x <= 25) {
13017 y = x + 'A';
13018 } else if (x <= 51) {
13019 y = x - 26 + 'a';
13020 } else if (x <= 61) {
13021 y = x - 52 + '0';
13022 } else if (x == 62) {
13023 y = '+';
13024 } else {
13025 y = '/';
13026 }
13027
13028 *dst++ = (duk_uint8_t) y;
13029 }
13030 }
13031}
13032#endif /* DUK_USE_BASE64_FASTPATH */
13033
13034#if defined(DUK_USE_BASE64_FASTPATH)
13035DUK_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) {
13036 duk_int_t x;
13037 duk_int_t t;
13038 duk_small_uint_t n_equal;
13039 duk_small_uint_t n_chars;
13040 const duk_uint8_t *src_end;
13041 const duk_uint8_t *src_end_safe;
13042
13043 src_end = src + srclen;
13044 src_end_safe = src_end - 4; /* if 'src < src_end_safe', safe to read 4 bytes */
13045
13046 /* Innermost fast path processes 4 valid base-64 characters at a time
13047 * but bails out on whitespace, padding chars ('=') and invalid chars.
13048 * Once the slow path segment has been processed, we return to the
13049 * inner fast path again. This handles e.g. base64 with newlines
13050 * reasonably well because the majority of a line is in the fast path.
13051 */
13052 for (;;) {
13053 /* Fast path, handle units with just actual encoding characters. */
13054
13055 while (src <= src_end_safe) {
13056 /* The lookup byte is intentionally sign extended to (at least)
13057 * 32 bits and then ORed. This ensures that is at least 1 byte
13058 * is negative, the highest bit of 't' will be set at the end
13059 * and we don't need to check every byte.
13060 */
13061 DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p",
13062 (const void *) src, (const void *) src_end_safe, (const void *) src_end));
13063
13064 t = (duk_int_t) duk_base64_dectab[*src++];
13065 t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13066 t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13067 t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13068
13069 if (DUK_UNLIKELY(t < 0)) {
13070 DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit"));
13071 src -= 4;
13072 break;
13073 }
13074
13075 DUK_ASSERT(t <= 0xffffffL);
13076 DUK_ASSERT((t >> 24) == 0);
13077 *dst++ = (duk_uint8_t) (t >> 16);
13078 *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13079 *dst++ = (duk_uint8_t) (t & 0xff);
13080 }
13081
13082 /* Handle one slow path unit (or finish if we're done). */
13083
13084 n_equal = 0;
13085 n_chars = 0;
13086 t = 0;
13087 for (;;) {
13088 DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld",
13089 (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));
13090
13091 if (DUK_UNLIKELY(src >= src_end)) {
13092 goto done; /* two level break */
13093 }
13094
13095 x = duk_base64_dectab[*src++];
13096 if (DUK_UNLIKELY(x < 0)) {
13097 if (x == -2) {
13098 continue; /* allowed ascii whitespace */
13099 } else if (x == -3) {
13100 n_equal++;
13101 t <<= 6;
13102 } else {
13103 DUK_ASSERT(x == -1);
13104 goto error;
13105 }
13106 } else {
13107 DUK_ASSERT(x >= 0 && x <= 63);
13108 if (n_equal > 0) {
13109 /* Don't allow actual chars after equal sign. */
13110 goto error;
13111 }
13112 t = (t << 6) + x;
13113 }
13114
13115 if (DUK_UNLIKELY(n_chars == 3)) {
13116 /* Emit 3 bytes and backtrack if there was padding. There's
13117 * always space for the whole 3 bytes so no check needed.
13118 */
13119 DUK_ASSERT(t <= 0xffffffL);
13120 DUK_ASSERT((t >> 24) == 0);
13121 *dst++ = (duk_uint8_t) (t >> 16);
13122 *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13123 *dst++ = (duk_uint8_t) (t & 0xff);
13124
13125 if (DUK_UNLIKELY(n_equal > 0)) {
13126 DUK_ASSERT(n_equal <= 4);
13127
13128 /* There may be whitespace between the equal signs. */
13129 if (n_equal == 1) {
13130 /* XXX= */
13131 dst -= 1;
13132 } else if (n_equal == 2) {
13133 /* XX== */
13134 dst -= 2;
13135 } else {
13136 goto error; /* invalid padding */
13137 }
13138
13139 /* Continue parsing after padding, allows concatenated,
13140 * padded base64.
13141 */
13142 }
13143 break; /* back to fast loop */
13144 } else {
13145 n_chars++;
13146 }
13147 }
13148 }
13149 done:
13150 DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
13151 (const void *) src, (const void *) src_end, (long) n_chars));
13152
13153 DUK_ASSERT(src == src_end);
13154
13155 if (n_chars != 0) {
13156 /* Here we'd have the option of decoding unpadded base64
13157 * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
13158 * accepted.
13159 */
13160 goto error;
13161 }
13162
13163 *out_dst_final = dst;
13164 return 1;
13165
13166 error:
13167 return 0;
13168}
13169#else /* DUK_USE_BASE64_FASTPATH */
13170DUK_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) {
13171 duk_uint_t t;
13172 duk_uint_fast8_t x, y;
13173 duk_small_uint_t group_idx;
13174 duk_small_uint_t n_equal;
13175 const duk_uint8_t *src_end;
13176
13177 src_end = src + srclen;
13178 t = 0;
13179 group_idx = 0;
13180 n_equal = 0;
13181
13182 while (src < src_end) {
13183 x = *src++;
13184
13185 if (x >= 'A' && x <= 'Z') {
13186 y = x - 'A' + 0;
13187 } else if (x >= 'a' && x <= 'z') {
13188 y = x - 'a' + 26;
13189 } else if (x >= '0' && x <= '9') {
13190 y = x - '0' + 52;
13191 } else if (x == '+') {
13192 y = 62;
13193 } else if (x == '/') {
13194 y = 63;
13195 } else if (x == '=') {
13196 /* We don't check the zero padding bytes here right now
13197 * (that they're actually zero). This seems to be common
13198 * behavior for base-64 decoders.
13199 */
13200
13201 n_equal++;
13202 t <<= 6; /* shift in zeroes */
13203 goto skip_add;
13204 } else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
13205 /* allow basic ASCII whitespace */
13206 continue;
13207 } else {
13208 goto error;
13209 }
13210
13211 if (n_equal > 0) {
13212 /* Don't allow mixed padding and actual chars. */
13213 goto error;
13214 }
13215 t = (t << 6) + y;
13216 skip_add:
13217
13218 if (group_idx == 3) {
13219 /* output 3 bytes from 't' */
13220 *dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
13221 *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13222 *dst++ = (duk_uint8_t) (t & 0xff);
13223
13224 if (DUK_UNLIKELY(n_equal > 0)) {
13225 /* Backtrack. */
13226 DUK_ASSERT(n_equal <= 4);
13227 if (n_equal == 1) {
13228 dst -= 1;
13229 } else if (n_equal == 2) {
13230 dst -= 2;
13231 } else {
13232 goto error; /* invalid padding */
13233 }
13234
13235 /* Here we can choose either to end parsing and ignore
13236 * whatever follows, or to continue parsing in case
13237 * multiple (possibly padded) base64 strings have been
13238 * concatenated. Currently, keep on parsing.
13239 */
13240 n_equal = 0;
13241 }
13242
13243 t = 0;
13244 group_idx = 0;
13245 } else {
13246 group_idx++;
13247 }
13248 }
13250 if (group_idx != 0) {
13251 /* Here we'd have the option of decoding unpadded base64
13252 * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
13253 * accepted.
13254 */
13255 goto error;
13256 }
13257
13258 *out_dst_final = dst;
13259 return 1;
13260
13261 error:
13262 return 0;
13263}
13264#endif /* DUK_USE_BASE64_FASTPATH */
13265
13267 duk_hthread *thr = (duk_hthread *) ctx;
13268 const duk_uint8_t *src;
13269 duk_size_t srclen;
13270 duk_size_t dstlen;
13271 duk_uint8_t *dst;
13272 const char *ret;
13273
13275
13276 /* XXX: optimize for string inputs: no need to coerce to a buffer
13277 * which makes a copy of the input.
13278 */
13279
13281 src = duk__prep_codec_arg(ctx, index, &srclen);
13282 /* Note: for srclen=0, src may be NULL */
13283
13284 /* Computation must not wrap; this limit works for 32-bit size_t:
13285 * >>> srclen = 3221225469
13286 * >>> '%x' % ((srclen + 2) / 3 * 4)
13287 * 'fffffffc'
13288 */
13289 if (srclen > 3221225469UL) {
13290 goto type_error;
13291 }
13292 dstlen = (srclen + 2) / 3 * 4;
13293 dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen);
13294
13295 duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
13296
13297 ret = duk_to_string(ctx, -1);
13298 duk_replace(ctx, index);
13299 return ret;
13300
13301 type_error:
13303 return NULL; /* never here */
13304}
13305
13307 duk_hthread *thr = (duk_hthread *) ctx;
13308 const duk_uint8_t *src;
13309 duk_size_t srclen;
13310 duk_size_t dstlen;
13311 duk_uint8_t *dst;
13312 duk_uint8_t *dst_final;
13313 duk_bool_t retval;
13314
13316
13317 /* XXX: optimize for buffer inputs: no need to coerce to a string
13318 * which causes an unnecessary interning.
13319 */
13320
13322 src = duk__prep_codec_arg(ctx, index, &srclen);
13323
13324 /* Computation must not wrap, only srclen + 3 is at risk of
13325 * wrapping because after that the number gets smaller.
13326 * This limit works for 32-bit size_t:
13327 * 0x100000000 - 3 - 1 = 4294967292
13328 */
13329 if (srclen > 4294967292UL) {
13330 goto type_error;
13331 }
13332 dstlen = (srclen + 3) / 4 * 3; /* upper limit, assuming no whitespace etc */
13333 dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
13334 /* Note: for dstlen=0, dst may be NULL */
13335
13336 retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);
13337 if (!retval) {
13338 goto type_error;
13339 }
13340
13341 /* XXX: convert to fixed buffer? */
13342 (void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst));
13343 duk_replace(ctx, index);
13344 return;
13345
13346 type_error:
13348}
13349
13351 const duk_uint8_t *inp;
13352 duk_size_t len;
13353 duk_size_t i;
13354 duk_uint8_t *buf;
13355 const char *ret;
13356#if defined(DUK_USE_HEX_FASTPATH)
13357 duk_size_t len_safe;
13358 duk_uint16_t *p16;
13359#endif
13360
13362
13364 inp = duk__prep_codec_arg(ctx, index, &len);
13365 DUK_ASSERT(inp != NULL || len == 0);
13366
13367 /* Fixed buffer, no zeroing because we'll fill all the data. */
13368 buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len * 2, DUK_BUF_FLAG_NOZERO /*flags*/);
13369 DUK_ASSERT(buf != NULL);
13370
13371#if defined(DUK_USE_HEX_FASTPATH)
13372 DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0); /* pointer is aligned, guaranteed for fixed buffer */
13373 p16 = (duk_uint16_t *) (void *) buf;
13374 len_safe = len & ~0x03U;
13375 for (i = 0; i < len_safe; i += 4) {
13376 p16[0] = duk_hex_enctab[inp[i]];
13377 p16[1] = duk_hex_enctab[inp[i + 1]];
13378 p16[2] = duk_hex_enctab[inp[i + 2]];
13379 p16[3] = duk_hex_enctab[inp[i + 3]];
13380 p16 += 4;
13381 }
13382 for (; i < len; i++) {
13383 *p16++ = duk_hex_enctab[inp[i]];
13384 }
13385#else /* DUK_USE_HEX_FASTPATH */
13386 for (i = 0; i < len; i++) {
13388 t = (duk_small_uint_t) inp[i];
13389 buf[i*2 + 0] = duk_lc_digits[t >> 4];
13390 buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
13391 }
13392#endif /* DUK_USE_HEX_FASTPATH */
13393
13394 /* XXX: Using a string return value forces a string intern which is
13395 * not always necessary. As a rough performance measure, hex encode
13396 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
13397 * without string coercion. Change to returning a buffer and let the
13398 * caller coerce to string if necessary?
13399 */
13400
13401 ret = duk_to_string(ctx, -1);
13402 duk_replace(ctx, index);
13403 return ret;
13404}
13405
13407 duk_hthread *thr = (duk_hthread *) ctx;
13408 const duk_uint8_t *inp;
13409 duk_size_t len;
13410 duk_size_t i;
13411 duk_int_t t;
13412 duk_uint8_t *buf;
13413#if defined(DUK_USE_HEX_FASTPATH)
13414 duk_int_t chk;
13415 duk_uint8_t *p;
13416 duk_size_t len_safe;
13417#endif
13418
13420
13422 inp = duk__prep_codec_arg(ctx, index, &len);
13423 DUK_ASSERT(inp != NULL || len == 0);
13424
13425 if (len & 0x01) {
13426 goto type_error;
13427 }
13428
13429 /* Fixed buffer, no zeroing because we'll fill all the data. */
13430 buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len / 2, DUK_BUF_FLAG_NOZERO /*flags*/);
13431 DUK_ASSERT(buf != NULL);
13432
13433#if defined(DUK_USE_HEX_FASTPATH)
13434 p = buf;
13435 len_safe = len & ~0x07U;
13436 for (i = 0; i < len_safe; i += 8) {
13437 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
13438 ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13439 chk = t;
13440 p[0] = (duk_uint8_t) t;
13441 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
13442 ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
13443 chk |= t;
13444 p[1] = (duk_uint8_t) t;
13445 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
13446 ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
13447 chk |= t;
13448 p[2] = (duk_uint8_t) t;
13449 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
13450 ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
13451 chk |= t;
13452 p[3] = (duk_uint8_t) t;
13453 p += 4;
13454
13455 /* Check if any lookup above had a negative result. */
13456 if (DUK_UNLIKELY(chk < 0)) {
13457 goto type_error;
13458 }
13459 }
13460 for (; i < len; i += 2) {
13461 t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
13462 ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13463 if (DUK_UNLIKELY(t < 0)) {
13464 goto type_error;
13465 }
13466 *p++ = (duk_uint8_t) t;
13467 }
13468#else /* DUK_USE_HEX_FASTPATH */
13469 for (i = 0; i < len; i += 2) {
13470 /* For invalid characters the value -1 gets extended to
13471 * at least 16 bits. If either nybble is invalid, the
13472 * resulting 't' will be < 0.
13474 t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
13475 ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13476 if (DUK_UNLIKELY(t < 0)) {
13477 goto type_error;
13478 }
13479 buf[i >> 1] = (duk_uint8_t) t;
13480 }
13481#endif /* DUK_USE_HEX_FASTPATH */
13482
13483 duk_replace(ctx, index);
13484 return;
13485
13486 type_error:
13488}
13489
13491#ifdef DUK_USE_ASSERTIONS
13492 duk_idx_t top_at_entry;
13493#endif
13494 const char *ret;
13495
13497#ifdef DUK_USE_ASSERTIONS
13498 top_at_entry = duk_get_top(ctx);
13499#endif
13500
13503 index /*idx_value*/,
13504 DUK_INVALID_INDEX /*idx_replacer*/,
13505 DUK_INVALID_INDEX /*idx_space*/,
13506 0 /*flags*/);
13507 DUK_ASSERT(duk_is_string(ctx, -1));
13508 duk_replace(ctx, index);
13509 ret = duk_get_string(ctx, index);
13510
13511 DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
13512
13513 return ret;
13514}
13515
13517#ifdef DUK_USE_ASSERTIONS
13518 duk_idx_t top_at_entry;
13519#endif
13520
13522#ifdef DUK_USE_ASSERTIONS
13523 top_at_entry = duk_get_top(ctx);
13524#endif
13530 0 /*flags*/);
13531 duk_replace(ctx, index);
13533 DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
13534}
13535/*
13536 * Compilation and evaluation
13537 */
13538
13539/* include removed: duk_internal.h */
13540
13542struct duk__compile_raw_args {
13543 duk_size_t src_length; /* should be first on 64-bit platforms */
13544 const duk_uint8_t *src_buffer;
13546};
13547
13548/* Eval is just a wrapper now. */
13549DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
13550 duk_uint_t comp_flags;
13551 duk_int_t rc;
13552
13554
13555 /* Note: strictness is *not* inherited from the current Duktape/C.
13556 * This would be confusing because the current strictness state
13557 * depends on whether we're running inside a Duktape/C activation
13558 * (= strict mode) or outside of any activation (= non-strict mode).
13559 * See tests/api/test-eval-strictness.c for more discussion.
13560 */
13561
13562 /* [ ... source? filename? ] (depends on flags) */
13563
13564 comp_flags = flags;
13565 comp_flags |= DUK_COMPILE_EVAL;
13566 rc = duk_compile_raw(ctx, src_buffer, src_length, comp_flags); /* may be safe, or non-safe depending on flags */
13567
13568 /* [ ... closure/error ] */
13569
13570 if (rc != DUK_EXEC_SUCCESS) {
13571 rc = DUK_EXEC_ERROR;
13572 goto got_rc;
13573 }
13574
13575 duk_push_global_object(ctx); /* explicit 'this' binding, see GH-164 */
13576
13577 if (flags & DUK_COMPILE_SAFE) {
13578 rc = duk_pcall_method(ctx, 0);
13579 } else {
13580 duk_call_method(ctx, 0);
13581 rc = DUK_EXEC_SUCCESS;
13582 }
13583
13584 /* [ ... result/error ] */
13585
13586 got_rc:
13587 if (flags & DUK_COMPILE_NORESULT) {
13588 duk_pop(ctx);
13589 }
13590
13591 return rc;
13592}
13593
13594/* Helper which can be called both directly and with duk_safe_call(). */
13596 duk_hthread *thr = (duk_hthread *) ctx;
13597 duk__compile_raw_args *comp_args;
13598 duk_uint_t flags;
13599 duk_small_uint_t comp_flags;
13600 duk_hcompiledfunction *h_templ;
13601
13603
13604 /* Note: strictness is not inherited from the current Duktape/C
13605 * context. Otherwise it would not be possible to compile
13606 * non-strict code inside a Duktape/C activation (which is
13607 * always strict now). See tests/api/test-eval-strictness.c
13608 * for discussion.
13609 */
13610
13611 /* [ ... source? filename? &comp_args ] (depends on flags) */
13612
13613 comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1);
13614 flags = comp_args->flags;
13615 duk_pop(ctx);
13616
13617 /* [ ... source? filename? ] */
13618
13619 if (flags & DUK_COMPILE_NOFILENAME) {
13620 /* Automatic filename: 'eval' or 'input'. */
13622 }
13623
13624 /* [ ... source? filename ] */
13625
13626 if (!comp_args->src_buffer) {
13627 duk_hstring *h_sourcecode;
13628
13629 h_sourcecode = duk_get_hstring(ctx, -2);
13630 if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */
13631 (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */
13632 /* XXX: when this error is caused by a nonexistent
13633 * file given to duk_peval_file() or similar, the
13634 * error message is not the best possible.
13635 */
13637 }
13638 DUK_ASSERT(h_sourcecode != NULL);
13639 comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
13640 comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
13641 }
13642 DUK_ASSERT(comp_args->src_buffer != NULL);
13643
13644 /* XXX: unnecessary translation of flags */
13645 comp_flags = 0;
13646 if (flags & DUK_COMPILE_EVAL) {
13647 comp_flags |= DUK_JS_COMPILE_FLAG_EVAL;
13648 }
13649 if (flags & DUK_COMPILE_FUNCTION) {
13650 comp_flags |= DUK_JS_COMPILE_FLAG_EVAL |
13652 }
13653 if (flags & DUK_COMPILE_STRICT) {
13654 comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
13655 }
13656
13657 /* [ ... source? filename ] */
13658
13659 duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags);
13660
13661 /* [ ... source? func_template ] */
13662
13663 if (flags & DUK_COMPILE_NOSOURCE) {
13664 ;
13665 } else {
13666 duk_remove(ctx, -2);
13667 }
13669 /* [ ... func_template ] */
13670
13671 h_templ = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
13672 DUK_ASSERT(h_templ != NULL);
13674 h_templ,
13677 1 /*add_auto_proto*/);
13678 duk_remove(ctx, -2); /* -> [ ... closure ] */
13679
13680 /* [ ... closure ] */
13681
13682 return 1;
13683}
13684
13685DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
13686 duk__compile_raw_args comp_args_alloc;
13687 duk__compile_raw_args *comp_args = &comp_args_alloc;
13688
13690
13691 if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
13692 /* String length is computed here to avoid multiple evaluation
13693 * of a macro argument in the calling side.
13694 */
13695 src_length = DUK_STRLEN(src_buffer);
13696 }
13697
13698 comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
13699 comp_args->src_length = src_length;
13700 comp_args->flags = flags;
13701 duk_push_pointer(ctx, (void *) comp_args);
13702
13703 /* [ ... source? filename? &comp_args ] (depends on flags) */
13704
13705 if (flags & DUK_COMPILE_SAFE) {
13706 duk_int_t rc;
13707 duk_int_t nargs;
13708 duk_int_t nrets = 1;
13709
13710 /* Arguments can be: [ source? filename? &comp_args] so that
13711 * nargs is 1 to 3. Call site encodes the correct nargs count
13712 * directly into flags.
13713 */
13714 nargs = flags & 0x07;
13715 DUK_ASSERT(nargs == (1 +
13716 ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
13717 ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1)));
13718 rc = duk_safe_call(ctx, duk__do_compile, nargs, nrets);
13719
13720 /* [ ... closure ] */
13721 return rc;
13722 }
13723
13724 (void) duk__do_compile(ctx);
13725
13726 /* [ ... closure ] */
13727 return DUK_EXEC_SUCCESS;
13728}
13729/*
13730 * Debugging related API calls
13731 */
13732
13733/* include removed: duk_internal.h */
13734
13736 duk_idx_t idx;
13737 duk_idx_t top;
13738
13740
13741 /* We don't duk_require_stack() here now, but rely on the caller having
13742 * enough space.
13743 */
13744
13745 top = duk_get_top(ctx);
13746 duk_push_array(ctx);
13747 for (idx = 0; idx < top; idx++) {
13748 duk_dup(ctx, idx);
13749 duk_put_prop_index(ctx, -2, idx);
13750 }
13751
13752 /* XXX: conversion errors should not propagate outwards.
13753 * Perhaps values need to be coerced individually?
13754 */
13756 duk_get_top_index(ctx), /*idx_value*/
13757 DUK_INVALID_INDEX, /*idx_replacer*/
13758 DUK_INVALID_INDEX, /*idx_space*/
13762
13763 duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1));
13764 duk_replace(ctx, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
13765 duk_pop(ctx);
13766 DUK_ASSERT(duk_is_string(ctx, -1));
13767}
13768
13769#if defined(DUK_USE_DEBUGGER_SUPPORT)
13770
13773 duk_debug_write_function write_cb,
13775 duk_debug_read_flush_function read_flush_cb,
13776 duk_debug_write_flush_function write_flush_cb,
13777 duk_debug_request_function request_cb,
13778 duk_debug_detached_function detached_cb,
13779 void *udata) {
13780 duk_hthread *thr = (duk_hthread *) ctx;
13781 duk_heap *heap;
13782 const char *str;
13783 duk_size_t len;
13784
13785 /* XXX: should there be an error or an automatic detach if
13786 * already attached?
13787 */
13788
13789 DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
13790
13792 DUK_ASSERT(read_cb != NULL);
13793 DUK_ASSERT(write_cb != NULL);
13794 /* Other callbacks are optional. */
13795
13796 heap = thr->heap;
13797 heap->dbg_read_cb = read_cb;
13798 heap->dbg_write_cb = write_cb;
13799 heap->dbg_peek_cb = peek_cb;
13800 heap->dbg_read_flush_cb = read_flush_cb;
13801 heap->dbg_write_flush_cb = write_flush_cb;
13802 heap->dbg_request_cb = request_cb;
13803 heap->dbg_detached_cb = detached_cb;
13804 heap->dbg_udata = udata;
13805 heap->dbg_have_next_byte = 0;
13806
13807 /* Start in paused state. */
13808 heap->dbg_processing = 0;
13809 heap->dbg_paused = 1;
13810 heap->dbg_state_dirty = 1;
13811 heap->dbg_force_restart = 0;
13812 heap->dbg_step_type = 0;
13813 heap->dbg_step_thread = NULL;
13814 heap->dbg_step_csindex = 0;
13815 heap->dbg_step_startline = 0;
13816 heap->dbg_exec_counter = 0;
13817 heap->dbg_last_counter = 0;
13818 heap->dbg_last_time = 0.0;
13819
13820 /* Send version identification and flush right afterwards. Note that
13821 * we must write raw, unframed bytes here.
13822 */
13823 duk_push_sprintf(ctx, "%ld %ld %s %s\n",
13825 (long) DUK_VERSION,
13826 (const char *) DUK_GIT_DESCRIBE,
13827 (const char *) DUK_USE_TARGET_INFO);
13828 str = duk_get_lstring(ctx, -1, &len);
13829 DUK_ASSERT(str != NULL);
13830 duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
13831 duk_debug_write_flush(thr);
13832 duk_pop(ctx);
13833}
13834
13836 duk_hthread *thr;
13837
13838 DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
13839
13841 thr = (duk_hthread *) ctx;
13842 DUK_ASSERT(thr != NULL);
13843 DUK_ASSERT(thr->heap != NULL);
13844
13845 /* Can be called multiple times with no harm. */
13846 duk_debug_do_detach(thr->heap);
13847}
13848
13850 duk_hthread *thr;
13851 duk_bool_t processed_messages;
13852
13854 thr = (duk_hthread *) ctx;
13855 DUK_ASSERT(thr != NULL);
13856 DUK_ASSERT(thr->heap != NULL);
13857
13858 if (!DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13859 return;
13860 }
13861 if (thr->callstack_top > 0 || thr->heap->dbg_processing) {
13862 /* Calling duk_debugger_cooperate() while Duktape is being
13863 * called into is not supported. This is not a 100% check
13864 * but prevents any damage in most cases.
13865 */
13866 return;
13867 }
13868
13869 processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
13870 DUK_UNREF(processed_messages);
13871}
13872
13874 duk_hthread *thr;
13875 duk_idx_t top;
13876 duk_idx_t idx;
13877 duk_bool_t ret = 0;
13878
13880 thr = (duk_hthread *) ctx;
13881 DUK_ASSERT(thr != NULL);
13882 DUK_ASSERT(thr->heap != NULL);
13883
13884 DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
13885
13886 top = duk_get_top(ctx);
13887 if (top < nvalues) {
13888 DUK_ERROR_API(thr, "not enough stack values for notify");
13889 return ret; /* unreachable */
13890 }
13891 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13892 duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
13893 for (idx = top - nvalues; idx < top; idx++) {
13894 duk_tval *tv = DUK_GET_TVAL_POSIDX(ctx, idx);
13895 duk_debug_write_tval(thr, tv);
13896 }
13897 duk_debug_write_eom(thr);
13898
13899 /* Return non-zero (true) if we have a good reason to believe
13900 * the notify was delivered; if we're still attached at least
13901 * a transport error was not indicated by the transport write
13902 * callback. This is not a 100% guarantee of course.
13903 */
13904 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13905 ret = 1;
13906 }
13907 }
13908 duk_pop_n(ctx, nvalues);
13909 return ret;
13910}
13911
13913 duk_hthread *thr;
13914
13916 thr = (duk_hthread *) ctx;
13917 DUK_ASSERT(thr != NULL);
13918 DUK_ASSERT(thr->heap != NULL);
13919
13920 DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
13921
13922 /* Treat like a debugger statement: ignore when not attached. */
13923 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13924 DUK_HEAP_SET_PAUSED(thr->heap);
13925
13926 /* Pause on the next opcode executed. This is always safe to do even
13927 * inside the debugger message loop: the interrupt counter will be reset
13928 * to its proper value when the message loop exits.
13929 */
13930 thr->interrupt_init = 1;
13931 thr->interrupt_counter = 0;
13932 }
13933}
13934
13935#else /* DUK_USE_DEBUGGER_SUPPORT */
13936
13939 duk_debug_write_function write_cb,
13942 duk_debug_write_flush_function write_flush_cb,
13943 duk_debug_request_function request_cb,
13944 duk_debug_detached_function detached_cb,
13945 void *udata) {
13947 DUK_UNREF(read_cb);
13948 DUK_UNREF(write_cb);
13949 DUK_UNREF(peek_cb);
13950 DUK_UNREF(read_flush_cb);
13951 DUK_UNREF(write_flush_cb);
13952 DUK_UNREF(request_cb);
13953 DUK_UNREF(detached_cb);
13954 DUK_UNREF(udata);
13955 DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
13956}
13957
13960 DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
13961}
13962
13964 /* nop */
13966 DUK_UNREF(ctx);
13967}
13973
13974 top = duk_get_top(ctx);
13975 if (top < nvalues) {
13976 DUK_ERROR_API((duk_hthread *) ctx, "not enough stack values for notify");
13977 return 0; /* unreachable */
13978 }
13979
13980 /* No debugger support, just pop values. */
13981 duk_pop_n(ctx, nvalues);
13982 return 0;
13983}
13984
13986 /* Treat like debugger statement: nop */
13988 DUK_UNREF(ctx);
13989}
13990
13991#endif /* DUK_USE_DEBUGGER_SUPPORT */
13992/*
13993 * Heap creation and destruction
13994 */
13995
13996/* include removed: duk_internal.h */
13997
14000 duk_realloc_function realloc_func,
14001 duk_free_function free_func,
14002 void *heap_udata,
14003 duk_fatal_function fatal_handler) {
14004 duk_heap *heap = NULL;
14005 duk_context *ctx;
14006
14007 /* Assume that either all memory funcs are NULL or non-NULL, mixed
14008 * cases will now be unsafe.
14009 */
14010
14011 /* XXX: just assert non-NULL values here and make caller arguments
14012 * do the defaulting to the default implementations (smaller code)?
14013 */
14014
14015 if (!alloc_func) {
14016 DUK_ASSERT(realloc_func == NULL);
14017 DUK_ASSERT(free_func == NULL);
14018#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
14019 alloc_func = duk_default_alloc_function;
14020 realloc_func = duk_default_realloc_function;
14021 free_func = duk_default_free_function;
14022#else
14023 DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
14024 return NULL;
14025#endif
14026 } else {
14027 DUK_ASSERT(realloc_func != NULL);
14028 DUK_ASSERT(free_func != NULL);
14029 }
14030
14031 if (!fatal_handler) {
14032 fatal_handler = duk_default_fatal_handler;
14034
14035 DUK_ASSERT(alloc_func != NULL);
14036 DUK_ASSERT(realloc_func != NULL);
14037 DUK_ASSERT(free_func != NULL);
14038 DUK_ASSERT(fatal_handler != NULL);
14039
14040 heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
14041 if (!heap) {
14042 return NULL;
14043 }
14044 ctx = (duk_context *) heap->heap_thread;
14045 DUK_ASSERT(ctx != NULL);
14046 DUK_ASSERT(((duk_hthread *) ctx)->heap != NULL);
14047 return ctx;
14048}
14049
14051 duk_hthread *thr = (duk_hthread *) ctx;
14052 duk_heap *heap;
14053
14054 if (!ctx) {
14055 return;
14056 }
14057 heap = thr->heap;
14058 DUK_ASSERT(heap != NULL);
14059
14060 duk_heap_free(heap);
14061}
14062
14063/* XXX: better place for this */
14065 duk_hthread *thr = (duk_hthread *) ctx;
14066 duk_hobject *h_glob;
14067 duk_hobject *h_prev_glob;
14068 duk_hobject *h_env;
14069 duk_hobject *h_prev_env;
14070
14071 DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(ctx, -1)));
14072
14073 h_glob = duk_require_hobject(ctx, -1);
14074 DUK_ASSERT(h_glob != NULL);
14075
14076 /*
14077 * Replace global object.
14078 */
14079
14080 h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
14081 DUK_UNREF(h_prev_glob);
14082 thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
14083 DUK_HOBJECT_INCREF(thr, h_glob);
14084 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob); /* side effects, in theory (referenced by global env) */
14085
14086 /*
14087 * Replace lexical environment for global scope
14088 *
14089 * Create a new object environment for the global lexical scope.
14090 * We can't just reset the _Target property of the current one,
14091 * because the lexical scope is shared by other threads with the
14092 * same (initial) built-ins.
14093 */
14094
14095 (void) duk_push_object_helper(ctx,
14098 -1); /* no prototype, updated below */
14099
14100 duk_dup(ctx, -2);
14101 duk_dup(ctx, -3);
14102
14103 /* [ ... new_glob new_env new_glob new_glob ] */
14104
14107
14108 /* [ ... new_glob new_env ] */
14109
14110 h_env = duk_get_hobject(ctx, -1);
14111 DUK_ASSERT(h_env != NULL);
14112
14113 h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
14114 thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_env;
14115 DUK_HOBJECT_INCREF(thr, h_env);
14116 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env); /* side effects */
14117 DUK_UNREF(h_env); /* without refcounts */
14118 DUK_UNREF(h_prev_env);
14120 /* [ ... new_glob new_env ] */
14121
14122 duk_pop_2(ctx);
14123
14124 /* [ ... ] */
14125}
14126/*
14127 * Logging
14128 *
14129 * Current logging primitive is a sprintf-style log which is convenient
14130 * for most C code. Another useful primitive would be to log N arguments
14131 * from value stack (like the Ecmascript binding does).
14132 */
14133
14134/* include removed: duk_internal.h */
14135
14136DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, va_list ap) {
14137 /* stridx_logfunc[] must be static to allow initializer with old compilers like BCC */
14138 static const duk_uint16_t stridx_logfunc[6] = {
14141 };
14142
14144
14145 if (level < 0) {
14146 level = 0;
14147 } else if (level > (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1) {
14148 level = (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1;
14149 }
14150
14153 duk_get_prop_stridx(ctx, -1, stridx_logfunc[level]);
14154 duk_dup(ctx, -2);
14155
14156 /* [ ... Logger clog logfunc clog ] */
14157
14158 duk_push_vsprintf(ctx, fmt, ap);
14159
14160 /* [ ... Logger clog logfunc clog(=this) msg ] */
14161
14162 duk_call_method(ctx, 1 /*nargs*/);
14163
14164 /* [ ... Logger clog res ] */
14165
14166 duk_pop_3(ctx);
14168
14169DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...) {
14170 va_list ap;
14171
14173
14174 va_start(ap, fmt);
14175 duk_log_va(ctx, level, fmt, ap);
14176 va_end(ap);
14177}
14178/*
14179 * Memory calls.
14180 */
14181
14182/* include removed: duk_internal.h */
14185 duk_hthread *thr = (duk_hthread *) ctx;
14186
14188
14189 return DUK_ALLOC_RAW(thr->heap, size);
14190}
14192DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) {
14193 duk_hthread *thr = (duk_hthread *) ctx;
14194
14196
14197 DUK_FREE_RAW(thr->heap, ptr);
14198}
14200DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) {
14201 duk_hthread *thr = (duk_hthread *) ctx;
14202
14204
14205 return DUK_REALLOC_RAW(thr->heap, ptr, size);
14206}
14208DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) {
14209 duk_hthread *thr = (duk_hthread *) ctx;
14210
14212
14213 return DUK_ALLOC(thr->heap, size);
14214}
14215
14216DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) {
14217 duk_hthread *thr = (duk_hthread *) ctx;
14218
14220
14221 DUK_FREE(thr->heap, ptr);
14222}
14223
14224DUK_EXTERNAL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) {
14225 duk_hthread *thr = (duk_hthread *) ctx;
14226
14228
14229 /*
14230 * Note: since this is an exposed API call, there should be
14231 * no way a mark-and-sweep could have a side effect on the
14232 * memory allocation behind 'ptr'; the pointer should never
14233 * be something that Duktape wants to change.
14234 *
14235 * Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
14236 * have the storage location here anyway).
14237 */
14238
14239 return DUK_REALLOC(thr->heap, ptr, size);
14240}
14243 duk_hthread *thr = (duk_hthread *) ctx;
14244 duk_heap *heap;
14245
14247 DUK_ASSERT(out_funcs != NULL);
14248 DUK_ASSERT(thr != NULL);
14249 DUK_ASSERT(thr->heap != NULL);
14250
14251 heap = thr->heap;
14252 out_funcs->alloc_func = heap->alloc_func;
14253 out_funcs->realloc_func = heap->realloc_func;
14254 out_funcs->free_func = heap->free_func;
14255 out_funcs->udata = heap->heap_udata;
14256}
14257
14258DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags) {
14259#ifdef DUK_USE_MARK_AND_SWEEP
14260 duk_hthread *thr = (duk_hthread *) ctx;
14261 duk_heap *heap;
14262
14263 DUK_UNREF(flags);
14264
14265 /* NULL accepted */
14266 if (!ctx) {
14267 return;
14268 }
14270 heap = thr->heap;
14271 DUK_ASSERT(heap != NULL);
14272
14273 DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
14274 duk_heap_mark_and_sweep(heap, 0);
14275#else
14276 DUK_D(DUK_DPRINT("mark-and-sweep requested by application but mark-and-sweep not enabled, ignoring"));
14277 DUK_UNREF(ctx);
14279#endif
14280}
14281/*
14282 * Object handling: property access and other support functions.
14283 */
14284
14285/* include removed: duk_internal.h */
14286
14287/*
14288 * Property handling
14289 *
14290 * The API exposes only the most common property handling functions.
14291 * The caller can invoke Ecmascript built-ins for full control (e.g.
14292 * defineProperty, getOwnPropertyDescriptor).
14293 */
14294
14296 duk_hthread *thr = (duk_hthread *) ctx;
14297 duk_tval *tv_obj;
14298 duk_tval *tv_key;
14299 duk_bool_t rc;
14300
14302
14303 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14304 * resize is not necessary for a property get right now.
14305 */
14306
14307 tv_obj = duk_require_tval(ctx, obj_index);
14308 tv_key = duk_require_tval(ctx, -1);
14309
14310 rc = duk_hobject_getprop(thr, tv_obj, tv_key);
14311 DUK_ASSERT(rc == 0 || rc == 1);
14312 /* a value is left on stack regardless of rc */
14313
14314 duk_remove(ctx, -2); /* remove key */
14315 return rc; /* 1 if property found, 0 otherwise */
14316}
14317
14320 DUK_ASSERT(key != NULL);
14321
14322 obj_index = duk_require_normalize_index(ctx, obj_index);
14323 duk_push_string(ctx, key);
14324 return duk_get_prop(ctx, obj_index);
14325}
14326
14329
14330 obj_index = duk_require_normalize_index(ctx, obj_index);
14331 duk_push_uarridx(ctx, arr_index);
14332 return duk_get_prop(ctx, obj_index);
14333}
14334
14336 duk_hthread *thr = (duk_hthread *) ctx;
14337
14339 DUK_ASSERT_DISABLE(stridx >= 0);
14341 DUK_UNREF(thr);
14342
14343 obj_index = duk_require_normalize_index(ctx, obj_index);
14344 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14345 return duk_get_prop(ctx, obj_index);
14346}
14347
14349 duk_bool_t rc;
14350
14352 DUK_ASSERT_DISABLE(stridx >= 0);
14354
14355 rc = duk_get_prop_stridx(ctx, obj_index, stridx);
14356 if (out_has_prop) {
14357 *out_has_prop = rc;
14358 }
14359 rc = duk_to_boolean(ctx, -1);
14360 DUK_ASSERT(rc == 0 || rc == 1);
14361 duk_pop(ctx);
14362 return rc;
14363}
14364
14366 duk_hthread *thr = (duk_hthread *) ctx;
14367 duk_tval *tv_obj;
14368 duk_tval *tv_key;
14369 duk_tval *tv_val;
14370 duk_small_int_t throw_flag;
14371 duk_bool_t rc;
14372
14373 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14374 * resize is not necessary for a property put right now (putprop protects
14375 * against it internally).
14376 */
14377
14378 /* Key and value indices are either (-2, -1) or (-1, -2). Given idx_key,
14379 * idx_val is always (idx_key ^ 0x01).
14380 */
14381 DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
14382 (idx_key == -1 && (idx_key ^ 1) == -2));
14383 tv_obj = duk_require_tval(ctx, obj_idx);
14384 tv_key = duk_require_tval(ctx, idx_key);
14385 tv_val = duk_require_tval(ctx, idx_key ^ 1);
14386 throw_flag = duk_is_strict_call(ctx);
14387
14388 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
14389 DUK_ASSERT(rc == 0 || rc == 1);
14390
14391 duk_pop_2(ctx); /* remove key and value */
14392 return rc; /* 1 if property found, 0 otherwise */
14393}
14394
14397 return duk__put_prop_shared(ctx, obj_idx, -2);
14398}
14399
14400DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
14402 DUK_ASSERT(key != NULL);
14403
14404 /* Careful here and with other duk_put_prop_xxx() helpers: the
14405 * target object and the property value may be in the same value
14406 * stack slot (unusual, but still conceptually clear).
14407 */
14408 obj_idx = duk_normalize_index(ctx, obj_idx);
14409 (void) duk_push_string(ctx, key);
14410 return duk__put_prop_shared(ctx, obj_idx, -1);
14411}
14412
14415
14416 obj_idx = duk_require_normalize_index(ctx, obj_idx);
14417 duk_push_uarridx(ctx, arr_idx);
14418 return duk__put_prop_shared(ctx, obj_idx, -1);
14419}
14420
14422 duk_hthread *thr = (duk_hthread *) ctx;
14423
14425 DUK_ASSERT_DISABLE(stridx >= 0);
14427 DUK_UNREF(thr);
14428
14429 obj_idx = duk_require_normalize_index(ctx, obj_idx);
14430 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14431 return duk__put_prop_shared(ctx, obj_idx, -1);
14432}
14433
14435 duk_hthread *thr = (duk_hthread *) ctx;
14436 duk_tval *tv_obj;
14437 duk_tval *tv_key;
14438 duk_small_int_t throw_flag;
14439 duk_bool_t rc;
14440
14442
14443 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14444 * resize is not necessary for a property delete right now.
14445 */
14446
14447 tv_obj = duk_require_tval(ctx, obj_index);
14448 tv_key = duk_require_tval(ctx, -1);
14449 throw_flag = duk_is_strict_call(ctx);
14451 rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
14452 DUK_ASSERT(rc == 0 || rc == 1);
14453
14454 duk_pop(ctx); /* remove key */
14455 return rc;
14456}
14457
14460 DUK_ASSERT(key != NULL);
14461
14462 obj_index = duk_require_normalize_index(ctx, obj_index);
14463 duk_push_string(ctx, key);
14464 return duk_del_prop(ctx, obj_index);
14465}
14466
14469
14470 obj_index = duk_require_normalize_index(ctx, obj_index);
14471 duk_push_uarridx(ctx, arr_index);
14472 return duk_del_prop(ctx, obj_index);
14473}
14474
14476 duk_hthread *thr = (duk_hthread *) ctx;
14477
14479 DUK_ASSERT_DISABLE(stridx >= 0);
14481 DUK_UNREF(thr);
14482
14483 obj_index = duk_require_normalize_index(ctx, obj_index);
14484 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14485 return duk_del_prop(ctx, obj_index);
14486}
14487
14489 duk_hthread *thr = (duk_hthread *) ctx;
14490 duk_tval *tv_obj;
14491 duk_tval *tv_key;
14492 duk_bool_t rc;
14495
14496 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14497 * resize is not necessary for a property existence check right now.
14498 */
14499
14500 tv_obj = duk_require_tval(ctx, obj_index);
14501 tv_key = duk_require_tval(ctx, -1);
14503 rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
14504 DUK_ASSERT(rc == 0 || rc == 1);
14505
14506 duk_pop(ctx); /* remove key */
14507 return rc; /* 1 if property found, 0 otherwise */
14508}
14509
14512 DUK_ASSERT(key != NULL);
14513
14514 obj_index = duk_require_normalize_index(ctx, obj_index);
14515 duk_push_string(ctx, key);
14516 return duk_has_prop(ctx, obj_index);
14517}
14518
14521
14522 obj_index = duk_require_normalize_index(ctx, obj_index);
14523 duk_push_uarridx(ctx, arr_index);
14524 return duk_has_prop(ctx, obj_index);
14525}
14526
14528 duk_hthread *thr = (duk_hthread *) ctx;
14529
14531 DUK_ASSERT_DISABLE(stridx >= 0);
14533 DUK_UNREF(thr);
14534
14535 obj_index = duk_require_normalize_index(ctx, obj_index);
14536 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14537 return duk_has_prop(ctx, obj_index);
14538}
14539
14540/* Define own property without inheritance looks and such. This differs from
14541 * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
14542 * not invoked by this method. The caller must be careful to invoke any such
14543 * behaviors if necessary.
14544 */
14545DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags) {
14546 duk_hthread *thr = (duk_hthread *) ctx;
14547 duk_hobject *obj;
14548 duk_hstring *key;
14549
14551
14552 obj = duk_require_hobject(ctx, obj_index);
14553 DUK_ASSERT(obj != NULL);
14554 key = duk_to_hstring(ctx, -2);
14555 DUK_ASSERT(key != NULL);
14556 DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
14557
14558 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14560 duk_pop(ctx); /* pop key */
14561}
14562
14563DUK_INTERNAL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags) {
14564 duk_hthread *thr = (duk_hthread *) ctx;
14565 duk_hobject *obj;
14566
14568
14569 obj = duk_require_hobject(ctx, obj_index);
14570 DUK_ASSERT(obj != NULL);
14571
14572 duk_hobject_define_property_internal_arridx(thr, obj, arr_index, desc_flags);
14573 /* value popped by call */
14574}
14575
14577 duk_hthread *thr = (duk_hthread *) ctx;
14579 duk_hstring *key;
14580
14582 DUK_ASSERT_DISABLE(stridx >= 0);
14584
14585 obj = duk_require_hobject(ctx, obj_index);
14586 DUK_ASSERT(obj != NULL);
14587 key = DUK_HTHREAD_GET_STRING(thr, stridx);
14588 DUK_ASSERT(key != NULL);
14589 DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
14590
14591 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14592 /* value popped by call */
14593}
14594
14596 duk_hthread *thr = (duk_hthread *) ctx;
14597 duk_hobject *obj;
14598 duk_hstring *key;
14599
14601 DUK_ASSERT_DISABLE(stridx >= 0);
14603 DUK_ASSERT_DISABLE(builtin_idx >= 0);
14605
14606 obj = duk_require_hobject(ctx, obj_index);
14607 DUK_ASSERT(obj != NULL);
14608 key = DUK_HTHREAD_GET_STRING(thr, stridx);
14609 DUK_ASSERT(key != NULL);
14610
14611 duk_push_hobject(ctx, thr->builtins[builtin_idx]);
14612 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14613 /* value popped by call */
14614}
14615
14616/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
14617 * setter/getter into an object property. This is needed by the 'arguments'
14618 * object creation code, function instance creation code, and Function.prototype.bind().
14619 */
14620
14622 duk_hthread *thr = (duk_hthread *) ctx;
14623 duk_hobject *obj = duk_require_hobject(ctx, obj_index);
14625 duk_hobject_define_accessor_internal(thr, obj, DUK_HTHREAD_GET_STRING(thr, stridx), thrower, thrower, desc_flags);
14626}
14627
14628/* Object.defineProperty() equivalent C binding. */
14629DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags) {
14630 duk_hthread *thr = (duk_hthread *) ctx;
14631 duk_idx_t idx_base;
14632 duk_hobject *obj;
14633 duk_hstring *key;
14634 duk_idx_t idx_value;
14635 duk_hobject *get;
14636 duk_hobject *set;
14637 duk_uint_t is_data_desc;
14638 duk_uint_t is_acc_desc;
14639
14641
14642 obj = duk_require_hobject(ctx, obj_index);
14643
14644 is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
14645 is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
14646 if (is_data_desc && is_acc_desc) {
14647 /* "Have" flags must not be conflicting so that they would
14648 * apply to both a plain property and an accessor at the same
14649 * time.
14650 */
14651 goto fail_invalid_desc;
14652 }
14653
14654 idx_base = duk_get_top_index(ctx);
14655 if (flags & DUK_DEFPROP_HAVE_SETTER) {
14659 set = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
14660 if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
14661 goto fail_not_callable;
14662 }
14663 idx_base--;
14664 } else {
14665 set = NULL;
14666 }
14667 if (flags & DUK_DEFPROP_HAVE_GETTER) {
14671 get = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
14672 if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
14673 goto fail_not_callable;
14674 }
14675 idx_base--;
14676 } else {
14677 get = NULL;
14678 }
14679 if (flags & DUK_DEFPROP_HAVE_VALUE) {
14680 idx_value = idx_base;
14681 idx_base--;
14682 } else {
14683 idx_value = (duk_idx_t) -1;
14684 }
14685 key = duk_require_hstring(ctx, idx_base);
14686
14687 duk_require_valid_index(ctx, idx_base);
14688
14690 flags /*defprop_flags*/,
14691 obj,
14692 key,
14693 idx_value,
14694 get,
14695 set);
14696
14697 /* Clean up stack */
14698
14699 duk_set_top(ctx, idx_base);
14700
14701 /* [ ... obj ... ] */
14702
14703 return;
14705 fail_invalid_desc:
14707 return;
14708
14709 fail_not_callable:
14711 return;
14712}
14713
14714/*
14715 * Object related
14716 *
14717 * Note: seal() and freeze() are accessible through Ecmascript bindings,
14718 * and are not exposed through the API.
14720
14721DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) {
14722 duk_hthread *thr = (duk_hthread *) ctx;
14723 duk_hobject *obj;
14724
14726
14727 obj = duk_get_hobject(ctx, obj_index);
14728 if (obj) {
14729 /* Note: this may fail, caller should protect the call if necessary */
14730 duk_hobject_compact_props(thr, obj);
14731 }
14732}
14733
14734/* XXX: the duk_hobject_enum.c stack APIs should be reworked */
14735
14736DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) {
14738
14739 duk_dup(ctx, obj_index);
14741 duk_hobject_enumerator_create(ctx, enum_flags); /* [target] -> [enum] */
14742}
14743
14744DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) {
14746
14747 duk_require_hobject(ctx, enum_index);
14748 duk_dup(ctx, enum_index);
14749 return duk_hobject_enumerator_next(ctx, get_value);
14750}
14751
14752/*
14753 * Helpers for writing multiple properties
14755
14757 const duk_function_list_entry *ent = funcs;
14758
14760
14761 obj_index = duk_require_normalize_index(ctx, obj_index);
14762 if (ent != NULL) {
14763 while (ent->key != NULL) {
14764 duk_push_c_function(ctx, ent->value, ent->nargs);
14765 duk_put_prop_string(ctx, obj_index, ent->key);
14766 ent++;
14767 }
14768 }
14769}
14770
14771DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers) {
14772 const duk_number_list_entry *ent = numbers;
14775
14776 obj_index = duk_require_normalize_index(ctx, obj_index);
14777 if (ent != NULL) {
14778 while (ent->key != NULL) {
14779 duk_push_number(ctx, ent->value);
14780 duk_put_prop_string(ctx, obj_index, ent->key);
14781 ent++;
14782 }
14783 }
14784}
14785
14786/*
14787 * Shortcut for accessing global object properties
14789
14791 duk_hthread *thr = (duk_hthread *) ctx;
14792 duk_bool_t ret;
14793
14796
14797 /* XXX: direct implementation */
14798
14800 ret = duk_get_prop_string(ctx, -1, key);
14801 duk_remove(ctx, -2);
14802 return ret;
14803}
14804
14806 duk_hthread *thr = (duk_hthread *) ctx;
14807 duk_bool_t ret;
14811
14812 /* XXX: direct implementation */
14813
14815 duk_insert(ctx, -2);
14816 ret = duk_put_prop_string(ctx, -2, key); /* [ ... global val ] -> [ ... global ] */
14817 duk_pop(ctx);
14818 return ret;
14819}
14820
14821/*
14822 * Object prototype
14823 */
14824
14826 duk_hthread *thr = (duk_hthread *) ctx;
14827 duk_hobject *obj;
14829
14831 DUK_UNREF(thr);
14832
14833 obj = duk_require_hobject(ctx, index);
14834 DUK_ASSERT(obj != NULL);
14835
14836 /* XXX: shared helper for duk_push_hobject_or_undefined()? */
14838 if (proto) {
14839 duk_push_hobject(ctx, proto);
14840 } else {
14841 duk_push_undefined(ctx);
14842 }
14843}
14844
14846 duk_hthread *thr = (duk_hthread *) ctx;
14847 duk_hobject *obj;
14849
14851
14852 obj = duk_require_hobject(ctx, index);
14853 DUK_ASSERT(obj != NULL);
14856 proto = duk_get_hobject(ctx, -1);
14857 /* proto can also be NULL here (allowed explicitly) */
14858
14859#if defined(DUK_USE_ROM_OBJECTS)
14861 DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
14862 return;
14864#endif
14865
14867
14868 duk_pop(ctx);
14870
14871/*
14872 * Object finalizer
14873 */
14874
14875/* XXX: these could be implemented as macros calling an internal function
14876 * directly.
14877 * XXX: same issue as with Duktape.fin: there's no way to delete the property
14878 * now (just set it to undefined).
14879 */
14882
14884}
14885
14888
14890}
14891/*
14892 * API calls related to general value stack manipulation: resizing the value
14893 * stack, pushing and popping values, type checking and reading values,
14894 * coercing values, etc.
14895 *
14896 * Also contains internal functions (such as duk_get_tval()), defined
14897 * in duk_api_internal.h, with semantics similar to the public API.
14898 */
14900/* XXX: repetition of stack pre-checks -> helper or macro or inline */
14901/* XXX: shared api error strings, and perhaps even throw code for rare cases? */
14902
14903/* include removed: duk_internal.h */
14904
14905/*
14906 * Forward declarations
14907 */
14908
14910
14911/*
14912 * Global state for working around missing variadic macros
14913 */
14915#ifndef DUK_USE_VARIADIC_MACROS
14918#endif
14919
14920/*
14921 * Misc helpers
14922 */
14924/* Check that there's room to push one value. */
14925#if defined(DUK_USE_VALSTACK_UNSAFE)
14926/* Faster but value stack overruns are memory unsafe. */
14927#define DUK__CHECK_SPACE() do { \
14928 DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
14929 } while (0)
14930#else
14931#define DUK__CHECK_SPACE() do { \
14932 if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
14933 DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \
14934 } \
14935 } while (0)
14936#endif
14937
14939
14941 duk_hthread *thr;
14942 duk_tval *tv;
14944 duk_double_t d;
14945
14946 thr = (duk_hthread *) ctx;
14947
14948 tv = duk_get_tval(ctx, index);
14949 if (tv == NULL) {
14950 goto error_notnumber;
14951 }
14952
14953 /*
14954 * Special cases like NaN and +/- Infinity are handled explicitly
14955 * because a plain C coercion from double to int handles these cases
14956 * in undesirable ways. For instance, NaN may coerce to INT_MIN
14957 * (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
14958 *
14959 * This double-to-int coercion differs from ToInteger() because it
14960 * has a finite range (ToInteger() allows e.g. +/- Infinity). It
14961 * also differs from ToInt32() because the INT_MIN/INT_MAX clamping
14962 * depends on the size of the int type on the platform. In particular,
14963 * on platforms with a 64-bit int type, the full range is allowed.
14964 */
14965
14966#if defined(DUK_USE_FASTINT)
14967 if (DUK_TVAL_IS_FASTINT(tv)) {
14968 duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
14969#if (DUK_INT_MAX <= 0x7fffffffL)
14970 /* Clamping only necessary for 32-bit ints. */
14971 if (t < DUK_INT_MIN) {
14972 t = DUK_INT_MIN;
14973 } else if (t > DUK_INT_MAX) {
14974 t = DUK_INT_MAX;
14975 }
14976#endif
14977 return (duk_int_t) t;
14978 }
14979#endif
14980
14981 if (DUK_TVAL_IS_NUMBER(tv)) {
14982 d = DUK_TVAL_GET_NUMBER(tv);
14984 if (c == DUK_FP_NAN) {
14985 return 0;
14986 } else if (d < (duk_double_t) DUK_INT_MIN) {
14987 /* covers -Infinity */
14988 return DUK_INT_MIN;
14989 } else if (d > (duk_double_t) DUK_INT_MAX) {
14990 /* covers +Infinity */
14991 return DUK_INT_MAX;
14992 } else {
14993 /* coerce towards zero */
14994 return (duk_int_t) d;
14995 }
14996 }
14997
14998 error_notnumber:
14999
15000 if (require) {
15002 /* not reachable */
15003 }
15004 return 0;
15005}
15006
15008 duk_hthread *thr;
15009 duk_tval *tv;
15011 duk_double_t d;
15012
15013 /* Same as above but for unsigned int range. */
15014
15015 thr = (duk_hthread *) ctx;
15016
15017 tv = duk_get_tval(ctx, index);
15018 if (tv == NULL) {
15019 goto error_notnumber;
15020 }
15021
15022#if defined(DUK_USE_FASTINT)
15023 if (DUK_TVAL_IS_FASTINT(tv)) {
15024 duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
15025 if (t < 0) {
15026 t = 0;
15027 }
15028#if (DUK_UINT_MAX <= 0xffffffffUL)
15029 /* Clamping only necessary for 32-bit ints. */
15030 else if (t > DUK_UINT_MAX) {
15031 t = DUK_UINT_MAX;
15032 }
15033#endif
15034 return (duk_uint_t) t;
15035 }
15036#endif
15037
15038 if (DUK_TVAL_IS_NUMBER(tv)) {
15039 d = DUK_TVAL_GET_NUMBER(tv);
15041 if (c == DUK_FP_NAN) {
15042 return 0;
15043 } else if (d < 0.0) {
15044 /* covers -Infinity */
15045 return (duk_uint_t) 0;
15046 } else if (d > (duk_double_t) DUK_UINT_MAX) {
15047 /* covers +Infinity */
15048 return (duk_uint_t) DUK_UINT_MAX;
15049 } else {
15050 /* coerce towards zero */
15051 return (duk_uint_t) d;
15052 }
15053 }
15054
15055 error_notnumber:
15057 if (require) {
15059 /* not reachable */
15060 }
15061 return 0;
15062}
15063
15064/*
15065 * Stack index validation/normalization and getting a stack duk_tval ptr.
15066 *
15067 * These are called by many API entrypoints so the implementations must be
15068 * fast and "inlined".
15069 *
15070 * There's some repetition because of this; keep the functions in sync.
15071 */
15072
15074 duk_hthread *thr = (duk_hthread *) ctx;
15075 duk_uidx_t vs_size;
15076 duk_uidx_t uindex;
15077
15080
15081 /* Care must be taken to avoid pointer wrapping in the index
15082 * validation. For instance, on a 32-bit platform with 8-byte
15083 * duk_tval the index 0x20000000UL would wrap the memory space
15084 * once.
15085 */
15086
15087 /* Assume value stack sizes (in elements) fits into duk_idx_t. */
15089 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15090 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15091
15092 if (index < 0) {
15093 uindex = vs_size + (duk_uidx_t) index;
15094 } else {
15095 /* since index non-negative */
15097 uindex = (duk_uidx_t) index;
15098 }
15099
15100 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15101 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15102
15103 if (DUK_LIKELY(uindex < vs_size)) {
15104 return (duk_idx_t) uindex;
15105 }
15106 return DUK_INVALID_INDEX;
15107}
15108
15110 duk_hthread *thr = (duk_hthread *) ctx;
15111 duk_uidx_t vs_size;
15112 duk_uidx_t uindex;
15113
15116
15118 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15119 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15120
15121 if (index < 0) {
15122 uindex = vs_size + (duk_uidx_t) index;
15123 } else {
15125 uindex = (duk_uidx_t) index;
15126 }
15127
15128 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15129 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15130
15131 if (DUK_LIKELY(uindex < vs_size)) {
15132 return (duk_idx_t) uindex;
15133 }
15135 return 0; /* unreachable */
15136}
15137
15139 duk_hthread *thr = (duk_hthread *) ctx;
15140 duk_uidx_t vs_size;
15141 duk_uidx_t uindex;
15142
15145
15147 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15148 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15150 if (index < 0) {
15151 uindex = vs_size + (duk_uidx_t) index;
15152 } else {
15154 uindex = (duk_uidx_t) index;
15155 }
15156
15157 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15158 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15159
15160 if (DUK_LIKELY(uindex < vs_size)) {
15161 return thr->valstack_bottom + uindex;
15162 }
15163 return NULL;
15164}
15165
15167 duk_hthread *thr = (duk_hthread *) ctx;
15168 duk_uidx_t vs_size;
15169 duk_uidx_t uindex;
15170
15173
15175 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15176 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15177
15178 /* Use unsigned arithmetic to optimize comparison. */
15179 if (index < 0) {
15180 uindex = vs_size + (duk_uidx_t) index;
15181 } else {
15183 uindex = (duk_uidx_t) index;
15184 }
15185
15186 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15187 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15189 if (DUK_LIKELY(uindex < vs_size)) {
15190 return thr->valstack_bottom + uindex;
15191 }
15193 return NULL;
15194}
15195
15196/* Non-critical. */
15200
15201 return (duk_normalize_index(ctx, index) >= 0);
15202}
15203
15204/* Non-critical. */
15206 duk_hthread *thr = (duk_hthread *) ctx;
15207
15210
15211 if (duk_normalize_index(ctx, index) < 0) {
15213 return; /* unreachable */
15214 }
15215}
15217/*
15218 * Value stack top handling
15219 */
15220
15222 duk_hthread *thr = (duk_hthread *) ctx;
15223
15225
15226 return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
15227}
15228
15229/* Set stack top within currently allocated range, but don't reallocate.
15230 * This is performance critical especially for call handling, so whenever
15231 * changing, profile and look at generated code.
15232 */
15234 duk_hthread *thr = (duk_hthread *) ctx;
15235 duk_uidx_t vs_size;
15236 duk_uidx_t vs_limit;
15237 duk_uidx_t uindex;
15238 duk_tval *tv;
15239
15242
15245 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15246 vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
15247
15248 if (index < 0) {
15249 /* Negative indices are always within allocated stack but
15250 * must not go below zero index.
15251 */
15252 uindex = vs_size + (duk_uidx_t) index;
15253 } else {
15254 /* Positive index can be higher than valstack top but must
15255 * not go above allocated stack (equality is OK).
15256 */
15257 uindex = (duk_uidx_t) index;
15258 }
15259
15260 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15261 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15262 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
15263
15264#if defined(DUK_USE_VALSTACK_UNSAFE)
15265 DUK_ASSERT(uindex <= vs_limit);
15266 DUK_UNREF(vs_limit);
15267#else
15268 if (DUK_UNLIKELY(uindex > vs_limit)) {
15270 return; /* unreachable */
15271 }
15272#endif
15273 DUK_ASSERT(uindex <= vs_limit);
15274
15275 /* Handle change in value stack top. Respect value stack
15276 * initialization policy: 'undefined' above top. Note that
15277 * DECREF may cause a side effect that reallocates valstack,
15278 * so must relookup after DECREF.
15279 */
15280
15281 if (uindex >= vs_size) {
15282 /* Stack size increases or stays the same. */
15283#if defined(DUK_USE_ASSERTIONS)
15284 duk_uidx_t count;
15285
15286 count = uindex - vs_size;
15287 while (count != 0) {
15288 count--;
15289 tv = thr->valstack_top + count;
15291 }
15292#endif
15293 thr->valstack_top = thr->valstack_bottom + uindex;
15294 } else {
15295 /* Stack size decreases. */
15296#if defined(DUK_USE_REFERENCE_COUNTING)
15297 duk_uidx_t count;
15298
15299 count = vs_size - uindex;
15300 DUK_ASSERT(count > 0);
15301 while (count > 0) {
15302 count--;
15303 tv = --thr->valstack_top; /* tv -> value just before prev top value; must relookup */
15304 DUK_ASSERT(tv >= thr->valstack_bottom);
15305 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
15306 }
15307#else /* DUK_USE_REFERENCE_COUNTING */
15308 duk_uidx_t count;
15309 duk_tval *tv_end;
15310
15311 count = vs_size - uindex;
15312 tv = thr->valstack_top;
15313 tv_end = tv - count;
15314 DUK_ASSERT(tv > tv_end);
15315 do {
15316 tv--;
15318 } while (tv != tv_end);
15319 thr->valstack_top = tv_end;
15320#endif /* DUK_USE_REFERENCE_COUNTING */
15321 }
15322}
15323
15325 duk_hthread *thr = (duk_hthread *) ctx;
15326 duk_idx_t ret;
15327
15329
15330 ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
15331 if (DUK_UNLIKELY(ret < 0)) {
15332 /* Return invalid index; if caller uses this without checking
15333 * in another API call, the index won't map to a valid stack
15334 * entry.
15335 */
15336 return DUK_INVALID_INDEX;
15337 }
15338 return ret;
15339}
15340
15342 duk_hthread *thr = (duk_hthread *) ctx;
15343 duk_idx_t ret;
15344
15346
15347 ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
15348 if (DUK_UNLIKELY(ret < 0)) {
15349 DUK_ERROR_API_INDEX(thr, -1);
15350 return 0; /* unreachable */
15351 }
15352 return ret;
15353}
15354
15355/*
15356 * Value stack resizing.
15357 *
15358 * This resizing happens above the current "top": the value stack can be
15359 * grown or shrunk, but the "top" is not affected. The value stack cannot
15360 * be resized to a size below the current "top".
15361 *
15362 * The low level reallocation primitive must carefully recompute all value
15363 * stack pointers, and must also work if ALL pointers are NULL. The resize
15364 * is quite tricky because the valstack realloc may cause a mark-and-sweep,
15365 * which may run finalizers. Running finalizers may resize the valstack
15366 * recursively (the same value stack we're working on). So, after realloc
15367 * returns, we know that the valstack "top" should still be the same (there
15368 * should not be live values above the "top"), but its underlying size and
15369 * pointer may have changed.
15370 */
15371
15372/* XXX: perhaps refactor this to allow caller to specify some parameters, or
15373 * at least a 'compact' flag which skips any spare or round-up .. useful for
15374 * emergency gc.
15375 */
15376
15378 duk_hthread *thr = (duk_hthread *) ctx;
15379 duk_ptrdiff_t old_bottom_offset;
15380 duk_ptrdiff_t old_top_offset;
15381 duk_ptrdiff_t old_end_offset_post;
15382#ifdef DUK_USE_DEBUG
15383 duk_ptrdiff_t old_end_offset_pre;
15384 duk_tval *old_valstack_pre;
15385 duk_tval *old_valstack_post;
15386#endif
15387 duk_tval *new_valstack;
15388 duk_size_t new_alloc_size;
15389 duk_tval *p;
15390
15392 DUK_ASSERT(thr != NULL);
15393 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15395 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15396 DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size); /* can't resize below 'top' */
15397 DUK_ASSERT(new_size <= thr->valstack_max); /* valstack limit caller has check, prevents wrapping */
15398 DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval)); /* specific assert for wrapping */
15399
15400 /* get pointer offsets for tweaking below */
15401 old_bottom_offset = (((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack));
15402 old_top_offset = (((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack));
15403#ifdef DUK_USE_DEBUG
15404 old_end_offset_pre = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* not very useful, used for debugging */
15405 old_valstack_pre = thr->valstack;
15406#endif
15407
15408 /* Allocate a new valstack.
15409 *
15410 * Note: cannot use a plain DUK_REALLOC() because a mark-and-sweep may
15411 * invalidate the original thr->valstack base pointer inside the realloc
15412 * process. See doc/memory-management.rst.
15413 */
15414
15415 new_alloc_size = sizeof(duk_tval) * new_size;
15416 new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
15417 if (!new_valstack) {
15418 /* Because new_size != 0, if condition doesn't need to be
15419 * (new_valstack != NULL || new_size == 0).
15420 */
15421 DUK_ASSERT(new_size != 0);
15422 DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
15423 (unsigned long) new_size, (unsigned long) new_alloc_size));
15424 return 0;
15425 }
15426
15427 /* Note: the realloc may have triggered a mark-and-sweep which may
15428 * have resized our valstack internally. However, the mark-and-sweep
15429 * MUST NOT leave the stack bottom/top in a different state. Particular
15430 * assumptions and facts:
15431 *
15432 * - The thr->valstack pointer may be different after realloc,
15433 * and the offset between thr->valstack_end <-> thr->valstack
15434 * may have changed.
15435 * - The offset between thr->valstack_bottom <-> thr->valstack
15436 * and thr->valstack_top <-> thr->valstack MUST NOT have changed,
15437 * because mark-and-sweep must adhere to a strict stack policy.
15438 * In other words, logical bottom and top MUST NOT have changed.
15439 * - All values above the top are unreachable but are initialized
15440 * to UNDEFINED, up to the post-realloc valstack_end.
15441 * - 'old_end_offset' must be computed after realloc to be correct.
15442 */
15443
15444 DUK_ASSERT((((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack)) == old_bottom_offset);
15445 DUK_ASSERT((((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack)) == old_top_offset);
15446
15447 /* success, fixup pointers */
15448 old_end_offset_post = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* must be computed after realloc */
15449#ifdef DUK_USE_DEBUG
15450 old_valstack_post = thr->valstack;
15451#endif
15452 thr->valstack = new_valstack;
15453 thr->valstack_end = new_valstack + new_size;
15454#if !defined(DUK_USE_PREFER_SIZE)
15455 thr->valstack_size = new_size;
15456#endif
15457 thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_bottom_offset);
15458 thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_top_offset);
15459
15460 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15462 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15463
15464 /* useful for debugging */
15465#ifdef DUK_USE_DEBUG
15466 if (old_end_offset_pre != old_end_offset_post) {
15467 DUK_D(DUK_DPRINT("valstack was resized during valstack_resize(), probably by mark-and-sweep; "
15468 "end offset changed: %lu -> %lu",
15469 (unsigned long) old_end_offset_pre,
15470 (unsigned long) old_end_offset_post));
15471 }
15472 if (old_valstack_pre != old_valstack_post) {
15473 DUK_D(DUK_DPRINT("valstack pointer changed during valstack_resize(), probably by mark-and-sweep: %p -> %p",
15474 (void *) old_valstack_pre,
15475 (void *) old_valstack_post));
15476 }
15477#endif
15478
15479 DUK_DD(DUK_DDPRINT("resized valstack to %lu elements (%lu bytes), bottom=%ld, top=%ld, "
15480 "new pointers: start=%p end=%p bottom=%p top=%p",
15481 (unsigned long) new_size, (unsigned long) new_alloc_size,
15482 (long) (thr->valstack_bottom - thr->valstack),
15483 (long) (thr->valstack_top - thr->valstack),
15484 (void *) thr->valstack, (void *) thr->valstack_end,
15485 (void *) thr->valstack_bottom, (void *) thr->valstack_top));
15486
15487 /* Init newly allocated slots (only). */
15488 p = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + old_end_offset_post);
15489 while (p < thr->valstack_end) {
15490 /* Never executed if new size is smaller. */
15492 p++;
15493 }
15494
15495 /* Assert for value stack initialization policy. */
15496#if defined(DUK_USE_ASSERTIONS)
15497 p = thr->valstack_top;
15498 while (p < thr->valstack_end) {
15500 p++;
15501 }
15502#endif
15503
15504 return 1;
15505}
15506
15509 duk_size_t min_new_size,
15510 duk_small_uint_t flags) {
15511 duk_hthread *thr = (duk_hthread *) ctx;
15512 duk_size_t old_size;
15513 duk_size_t new_size;
15514 duk_bool_t is_shrink = 0;
15515 duk_small_uint_t shrink_flag = (flags & DUK_VSRESIZE_FLAG_SHRINK);
15516 duk_small_uint_t compact_flag = (flags & DUK_VSRESIZE_FLAG_COMPACT);
15517 duk_small_uint_t throw_flag = (flags & DUK_VSRESIZE_FLAG_THROW);
15518
15519 DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, "
15520 "curr_bottom=%ld, shrink=%d, compact=%d, throw=%d",
15521 (unsigned long) min_new_size,
15522 (long) (thr->valstack_end - thr->valstack),
15523 (long) (thr->valstack_top - thr->valstack),
15524 (long) (thr->valstack_bottom - thr->valstack),
15525 (int) shrink_flag, (int) compact_flag, (int) throw_flag));
15526
15528 DUK_ASSERT(thr != NULL);
15529 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15531 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15532
15533#if defined(DUK_USE_PREFER_SIZE)
15534 old_size = (duk_size_t) (thr->valstack_end - thr->valstack);
15535#else
15536 DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
15537 old_size = thr->valstack_size;
15538#endif
15539
15540 if (min_new_size <= old_size) {
15541 is_shrink = 1;
15542 if (!shrink_flag ||
15543 old_size - min_new_size < DUK_VALSTACK_SHRINK_THRESHOLD) {
15544 DUK_DDD(DUK_DDDPRINT("no need to grow or shrink valstack"));
15545 return 1;
15546 }
15547 }
15548
15549 new_size = min_new_size;
15550 if (!compact_flag) {
15551 if (is_shrink) {
15552 /* shrink case; leave some spare */
15553 new_size += DUK_VALSTACK_SHRINK_SPARE;
15554 }
15555
15556 /* round up roughly to next 'grow step' */
15557 new_size = (new_size / DUK_VALSTACK_GROW_STEP + 1) * DUK_VALSTACK_GROW_STEP;
15558 }
15559
15560 DUK_DD(DUK_DDPRINT("want to %s valstack: %lu -> %lu elements (min_new_size %lu)",
15561 (const char *) (new_size > old_size ? "grow" : "shrink"),
15562 (unsigned long) old_size, (unsigned long) new_size,
15563 (unsigned long) min_new_size));
15564
15565 if (new_size > thr->valstack_max) {
15566 /* Note: may be triggered even if minimal new_size would not reach the limit,
15567 * plan limit accordingly (taking DUK_VALSTACK_GROW_STEP into account).
15568 */
15569 if (throw_flag) {
15571 } else {
15572 return 0;
15573 }
15574 }
15575
15576 /*
15577 * When resizing the valstack, a mark-and-sweep may be triggered for
15578 * the allocation of the new valstack. If the mark-and-sweep needs
15579 * to use our thread for something, it may cause *the same valstack*
15580 * to be resized recursively. This happens e.g. when mark-and-sweep
15581 * finalizers are called. This is taken into account carefully in
15582 * duk__resize_valstack().
15583 *
15584 * 'new_size' is known to be <= valstack_max, which ensures that
15585 * size_t and pointer arithmetic won't wrap in duk__resize_valstack().
15586 */
15587
15588 if (!duk__resize_valstack(ctx, new_size)) {
15589 if (is_shrink) {
15590 DUK_DD(DUK_DDPRINT("valstack resize failed, but is a shrink, ignore"));
15591 return 1;
15592 }
15593
15594 DUK_DD(DUK_DDPRINT("valstack resize failed"));
15595
15596 if (throw_flag) {
15598 } else {
15599 return 0;
15600 }
15601 }
15602
15603 DUK_DDD(DUK_DDDPRINT("valstack resize successful"));
15604 return 1;
15605}
15606
15608 duk_hthread *thr = (duk_hthread *) ctx;
15609 duk_size_t min_new_size;
15610
15613
15614 if (DUK_UNLIKELY(extra < 0)) {
15615 /* Clamping to zero makes the API more robust to calling code
15616 * calculation errors.
15617 */
15618 extra = 0;
15619 }
15620
15621 min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
15622 return duk_valstack_resize_raw(ctx,
15623 min_new_size, /* min_new_size */
15624 0 /* no shrink */ | /* flags */
15625 0 /* no compact */ |
15626 0 /* no throw */);
15627}
15628
15630 duk_hthread *thr = (duk_hthread *) ctx;
15631 duk_size_t min_new_size;
15632
15635
15636 if (DUK_UNLIKELY(extra < 0)) {
15637 /* Clamping to zero makes the API more robust to calling code
15638 * calculation errors.
15639 */
15640 extra = 0;
15641 }
15642
15643 min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
15644 (void) duk_valstack_resize_raw(ctx,
15645 min_new_size, /* min_new_size */
15646 0 /* no shrink */ | /* flags */
15647 0 /* no compact */ |
15649}
15650
15652 duk_size_t min_new_size;
15653
15655
15656 if (DUK_UNLIKELY(top < 0)) {
15657 /* Clamping to zero makes the API more robust to calling code
15658 * calculation errors.
15659 */
15660 top = 0;
15661 }
15662
15663 min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
15664 return duk_valstack_resize_raw(ctx,
15665 min_new_size, /* min_new_size */
15666 0 /* no shrink */ | /* flags */
15667 0 /* no compact */ |
15668 0 /* no throw */);
15669}
15670
15672 duk_size_t min_new_size;
15673
15675
15676 if (DUK_UNLIKELY(top < 0)) {
15677 /* Clamping to zero makes the API more robust to calling code
15678 * calculation errors.
15679 */
15680 top = 0;
15681 }
15682
15683 min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
15684 (void) duk_valstack_resize_raw(ctx,
15685 min_new_size, /* min_new_size */
15686 0 /* no shrink */ | /* flags */
15687 0 /* no compact */ |
15689}
15690
15691/*
15692 * Basic stack manipulation: swap, dup, insert, replace, etc
15693 */
15694
15695DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
15697 duk_tval *tv2;
15698 duk_tval tv_tmp;
15699
15701
15702 tv1 = duk_require_tval(ctx, index1);
15703 DUK_ASSERT(tv1 != NULL);
15704 tv2 = duk_require_tval(ctx, index2);
15705 DUK_ASSERT(tv2 != NULL);
15706
15707 /* If tv1==tv2 this is a NOP, no check is needed */
15708 DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
15709 DUK_TVAL_SET_TVAL(tv1, tv2);
15710 DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
15711}
15712
15715
15716 duk_swap(ctx, index, -1);
15717}
15718
15720 duk_hthread *thr;
15721 duk_tval *tv_from;
15722 duk_tval *tv_to;
15723
15725 thr = (duk_hthread *) ctx;
15727
15728 tv_from = duk_require_tval(ctx, from_index);
15729 tv_to = thr->valstack_top++;
15730 DUK_ASSERT(tv_from != NULL);
15731 DUK_ASSERT(tv_to != NULL);
15732 DUK_TVAL_SET_TVAL(tv_to, tv_from);
15733 DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
15734}
15735
15737 duk_hthread *thr;
15738 duk_tval *tv_from;
15739 duk_tval *tv_to;
15742 thr = (duk_hthread *) ctx;
15744
15745 if (thr->valstack_top - thr->valstack_bottom <= 0) {
15746 DUK_ERROR_API_INDEX(thr, -1);
15747 return; /* unreachable */
15748 }
15749 tv_from = thr->valstack_top - 1;
15750 tv_to = thr->valstack_top++;
15751 DUK_ASSERT(tv_from != NULL);
15752 DUK_ASSERT(tv_to != NULL);
15753 DUK_TVAL_SET_TVAL(tv_to, tv_from);
15754 DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
15755}
15756
15757DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index) {
15758 duk_tval *p;
15759 duk_tval *q;
15760 duk_tval tv_tmp;
15761 duk_size_t nbytes;
15762
15764
15765 p = duk_require_tval(ctx, to_index);
15766 DUK_ASSERT(p != NULL);
15767 q = duk_require_tval(ctx, -1);
15768 DUK_ASSERT(q != NULL);
15769
15770 DUK_ASSERT(q >= p);
15771
15772 /* nbytes
15773 * <--------->
15774 * [ ... | p | x | x | q ]
15775 * => [ ... | q | p | x | x ]
15776 */
15777
15778 nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
15779
15780 DUK_DDD(DUK_DDDPRINT("duk_insert: to_index=%ld, p=%p, q=%p, nbytes=%lu",
15781 (long) to_index, (void *) p, (void *) q, (unsigned long) nbytes));
15782
15783 /* No net refcount changes. */
15784
15785 if (nbytes > 0) {
15786 DUK_TVAL_SET_TVAL(&tv_tmp, q);
15787 DUK_ASSERT(nbytes > 0);
15788 DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);
15789 DUK_TVAL_SET_TVAL(p, &tv_tmp);
15790 } else {
15791 /* nop: insert top to top */
15792 DUK_ASSERT(nbytes == 0);
15793 DUK_ASSERT(p == q);
15794 }
15795}
15796
15797DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index) {
15798 duk_hthread *thr = (duk_hthread *) ctx;
15799 duk_tval *tv1;
15800 duk_tval *tv2;
15801 duk_tval tv_tmp;
15802
15804
15805 tv1 = duk_require_tval(ctx, -1);
15806 DUK_ASSERT(tv1 != NULL);
15807 tv2 = duk_require_tval(ctx, to_index);
15808 DUK_ASSERT(tv2 != NULL);
15809
15810 /* For tv1 == tv2, both pointing to stack top, the end result
15811 * is same as duk_pop(ctx).
15812 */
15813 DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
15814 DUK_TVAL_SET_TVAL(tv2, tv1);
15816 thr->valstack_top--;
15817 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
15818}
15819
15820DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index) {
15821 duk_hthread *thr = (duk_hthread *) ctx;
15822 duk_tval *tv1;
15823 duk_tval *tv2;
15824
15826 DUK_UNREF(thr); /* w/o refcounting */
15827
15828 tv1 = duk_require_tval(ctx, from_index);
15829 DUK_ASSERT(tv1 != NULL);
15830 tv2 = duk_require_tval(ctx, to_index);
15831 DUK_ASSERT(tv2 != NULL);
15832
15833 /* For tv1 == tv2, this is a no-op (no explicit check needed). */
15834 DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1); /* side effects */
15835}
15836
15838 duk_hthread *thr = (duk_hthread *) ctx;
15839 duk_tval *p;
15840 duk_tval *q;
15841#ifdef DUK_USE_REFERENCE_COUNTING
15842 duk_tval tv_tmp;
15843#endif
15844 duk_size_t nbytes;
15845
15847
15848 p = duk_require_tval(ctx, index);
15849 DUK_ASSERT(p != NULL);
15850 q = duk_require_tval(ctx, -1);
15851 DUK_ASSERT(q != NULL);
15852
15853 DUK_ASSERT(q >= p);
15854
15855 /* nbytes zero size case
15856 * <--------->
15857 * [ ... | p | x | x | q ] [ ... | p==q ]
15858 * => [ ... | x | x | q ] [ ... ]
15859 */
15860
15861#ifdef DUK_USE_REFERENCE_COUNTING
15862 /* use a temp: decref only when valstack reachable values are correct */
15863 DUK_TVAL_SET_TVAL(&tv_tmp, p);
15864#endif
15865
15866 nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
15867 DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes); /* zero size not an issue: pointers are valid */
15868
15870 thr->valstack_top--;
15871
15872#ifdef DUK_USE_REFERENCE_COUNTING
15873 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
15874#endif
15875}
15876
15877/*
15878 * Stack slice primitives
15879 */
15880
15881DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy) {
15882 duk_hthread *to_thr = (duk_hthread *) to_ctx;
15883 duk_hthread *from_thr = (duk_hthread *) from_ctx;
15884 void *src;
15885 duk_size_t nbytes;
15886 duk_tval *p;
15887 duk_tval *q;
15888
15889 /* XXX: several pointer comparison issues here */
15890
15891 DUK_ASSERT_CTX_VALID(to_ctx);
15892 DUK_ASSERT_CTX_VALID(from_ctx);
15893 DUK_ASSERT(to_ctx != NULL);
15894 DUK_ASSERT(from_ctx != NULL);
15895
15896 if (to_ctx == from_ctx) {
15898 return;
15899 }
15900 if ((count < 0) ||
15901 (count > (duk_idx_t) to_thr->valstack_max)) {
15902 /* Maximum value check ensures 'nbytes' won't wrap below. */
15904 return;
15905 }
15906
15907 nbytes = sizeof(duk_tval) * count;
15908 if (nbytes == 0) {
15909 return;
15910 }
15911 DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
15912 if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) {
15914 }
15915 src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
15916 if (src < (void *) from_thr->valstack_bottom) {
15918 }
15919
15920 /* copy values (no overlap even if to_ctx == from_ctx; that's not
15921 * allowed now anyway)
15922 */
15923 DUK_ASSERT(nbytes > 0);
15924 DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
15925
15926 p = to_thr->valstack_top;
15927 to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
15928
15929 if (is_copy) {
15930 /* Incref copies, keep originals. */
15931 q = to_thr->valstack_top;
15932 while (p < q) {
15933 DUK_TVAL_INCREF(to_thr, p); /* no side effects */
15934 p++;
15935 }
15936 } else {
15937 /* No net refcount change. */
15938 p = from_thr->valstack_top;
15939 q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
15940 from_thr->valstack_top = q;
15941
15942 while (p > q) {
15943 p--;
15945 /* XXX: fast primitive to set a bunch of values to UNDEFINED */
15946 }
15947 }
15948}
15949
15950/*
15951 * Get/require
15952 */
15953
15955 duk_hthread *thr = (duk_hthread *) ctx;
15956 duk_tval *tv;
15957
15959
15960 tv = duk_get_tval(ctx, index);
15961 if (tv && DUK_TVAL_IS_UNDEFINED(tv)) {
15962 return;
15963 }
15965 return; /* not reachable */
15966}
15967
15969 duk_hthread *thr = (duk_hthread *) ctx;
15970 duk_tval *tv;
15971
15973
15974 tv = duk_get_tval(ctx, index);
15975 if (tv && DUK_TVAL_IS_NULL(tv)) {
15976 return;
15977 }
15979 return; /* not reachable */
15981
15983 duk_bool_t ret = 0; /* default: false */
15984 duk_tval *tv;
15985
15987
15988 tv = duk_get_tval(ctx, index);
15989 if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
15990 ret = DUK_TVAL_GET_BOOLEAN(tv);
15991 }
15992
15993 DUK_ASSERT(ret == 0 || ret == 1);
15994 return ret;
15995}
15998 duk_hthread *thr = (duk_hthread *) ctx;
15999 duk_tval *tv;
16000
16002
16003 tv = duk_get_tval(ctx, index);
16004 if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
16006 DUK_ASSERT(ret == 0 || ret == 1);
16007 return ret;
16008 }
16010 return 0; /* not reachable */
16011}
16012
16014 duk_double_union ret;
16015 duk_tval *tv;
16016
16018
16019 ret.d = DUK_DOUBLE_NAN; /* default: NaN */
16020 tv = duk_get_tval(ctx, index);
16021 if (tv && DUK_TVAL_IS_NUMBER(tv)) {
16022 ret.d = DUK_TVAL_GET_NUMBER(tv);
16023 }
16024
16025 /*
16026 * Number should already be in NaN-normalized form, but let's
16027 * normalize anyway.
16028 */
16029
16031 return ret.d;
16032}
16033
16035 duk_hthread *thr = (duk_hthread *) ctx;
16036 duk_tval *tv;
16037
16039
16041 if (tv && DUK_TVAL_IS_NUMBER(tv)) {
16042 duk_double_union ret;
16043 ret.d = DUK_TVAL_GET_NUMBER(tv);
16044
16045 /*
16046 * Number should already be in NaN-normalized form,
16047 * but let's normalize anyway.
16048 */
16049
16051 return ret.d;
16054 return DUK_DOUBLE_NAN; /* not reachable */
16055}
16056
16058 /* Custom coercion for API */
16060 return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
16061}
16062
16064 /* Custom coercion for API */
16066 return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
16067}
16068
16070 /* Custom coercion for API */
16072 return (duk_int_t) duk__api_coerce_d2i(ctx, index, 1 /*require*/);
16073}
16074
16076 /* Custom coercion for API */
16078 return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 1 /*require*/);
16079}
16080
16082 const char *ret;
16083 duk_tval *tv;
16084
16086
16087 /* default: NULL, length 0 */
16088 ret = NULL;
16089 if (out_len) {
16090 *out_len = 0;
16091 }
16093 tv = duk_get_tval(ctx, index);
16094 if (tv && DUK_TVAL_IS_STRING(tv)) {
16095 /* Here we rely on duk_hstring instances always being zero
16096 * terminated even if the actual string is not.
16097 */
16099 DUK_ASSERT(h != NULL);
16100 ret = (const char *) DUK_HSTRING_GET_DATA(h);
16101 if (out_len) {
16102 *out_len = DUK_HSTRING_GET_BYTELEN(h);
16103 }
16104 }
16105
16106 return ret;
16107}
16108
16110 duk_hthread *thr = (duk_hthread *) ctx;
16111 const char *ret;
16112
16114
16115 /* Note: this check relies on the fact that even a zero-size string
16116 * has a non-NULL pointer.
16117 */
16118 ret = duk_get_lstring(ctx, index, out_len);
16119 if (ret) {
16120 return ret;
16123 return NULL; /* not reachable */
16124}
16125
16128
16129 return duk_get_lstring(ctx, index, NULL);
16130}
16131
16134
16136}
16137
16139 duk_tval *tv;
16140
16142
16143 tv = duk_get_tval(ctx, index);
16144 if (tv && DUK_TVAL_IS_POINTER(tv)) {
16145 void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
16146 return (void *) p;
16147 }
16148
16149 return NULL;
16150}
16151
16153 duk_hthread *thr = (duk_hthread *) ctx;
16154 duk_tval *tv;
16155
16157
16158 /* Note: here we must be wary of the fact that a pointer may be
16159 * valid and be a NULL.
16160 */
16161 tv = duk_get_tval(ctx, index);
16162 if (tv && DUK_TVAL_IS_POINTER(tv)) {
16163 void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
16164 return (void *) p;
16165 }
16167 return NULL; /* not reachable */
16168}
16169
16170#if 0 /*unused*/
16171DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) {
16172 duk_tval *tv;
16173
16175
16176 tv = duk_get_tval(ctx, index);
16177 if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
16179 DUK_ASSERT(h != NULL);
16180 return (void *) h;
16181 }
16182
16183 return NULL;
16184}
16185#endif
16186
16188 duk_hthread *thr = (duk_hthread *) ctx;
16189 duk_tval *tv;
16190
16192 DUK_UNREF(thr);
16193
16194 if (out_size != NULL) {
16195 *out_size = 0;
16196 }
16198 tv = duk_get_tval(ctx, index);
16199 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
16202 if (out_size) {
16203 *out_size = DUK_HBUFFER_GET_SIZE(h);
16204 }
16205 return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
16206 }
16207
16208 if (throw_flag) {
16210 }
16211 return NULL;
16212}
16213
16215 return duk__get_buffer_helper(ctx, index, out_size, 0 /*throw_flag*/);
16216}
16217
16219 return duk__get_buffer_helper(ctx, index, out_size, 1 /*throw_flag*/);
16220}
16221
16223 duk_hthread *thr = (duk_hthread *) ctx;
16224 duk_tval *tv;
16225
16227 DUK_UNREF(thr);
16228
16229 if (out_size != NULL) {
16230 *out_size = 0;
16231 }
16232
16233 tv = duk_get_tval(ctx, index);
16234 if (tv == NULL) {
16235 goto fail;
16236 }
16237
16238 if (DUK_TVAL_IS_BUFFER(tv)) {
16240 DUK_ASSERT(h != NULL);
16241 if (out_size) {
16242 *out_size = DUK_HBUFFER_GET_SIZE(h);
16243 }
16244 return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
16245 } else if (DUK_TVAL_IS_OBJECT(tv)) {
16247 DUK_ASSERT(h != NULL);
16249 /* XXX: this is probably a useful shared helper: for a
16250 * duk_hbufferobject, get a validated buffer pointer/length.
16251 */
16252 duk_hbufferobject *h_bufobj = (duk_hbufferobject *) h;
16254
16255 if (h_bufobj->buf != NULL &&
16257 duk_uint8_t *p;
16258
16259 p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
16260 if (out_size != NULL) {
16261 *out_size = (duk_size_t) h_bufobj->length;
16262 }
16263 return (void *) (p + h_bufobj->offset);
16264 }
16265 /* if slice not fully valid, treat as error */
16266 }
16267 }
16268
16269 fail:
16270 if (throw_flag) {
16273 return NULL;
16274}
16275
16277 return duk__get_buffer_data_helper(ctx, index, out_size, 0 /*throw_flag*/);
16278}
16279
16281 return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/);
16282}
16283
16284/* Raw helper for getting a value from the stack, checking its tag.
16285 * The tag cannot be a number because numbers don't have an internal
16286 * tag in the packed representation.
16287 */
16291
16293
16294 tv = duk_get_tval(ctx, index);
16295 if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) {
16296 duk_heaphdr *ret;
16297 ret = DUK_TVAL_GET_HEAPHDR(tv);
16298 DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
16299 return ret;
16300 }
16302 return (duk_heaphdr *) NULL;
16303}
16304
16315 return (duk_hstring *) h;
16316}
16317
16328 return (duk_hobject *) h;
16329}
16330
16333}
16334
16336 duk_heaphdr *h;
16338 if (h == NULL) {
16340 }
16341 return (duk_hbuffer *) h;
16342}
16343
16346 if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) {
16347 h = NULL;
16348 }
16349 return (duk_hthread *) h;
16350}
16351
16360
16368
16377
16403 if (!tv) {
16404 return NULL;
16405 }
16406 if (!DUK_TVAL_IS_OBJECT(tv)) {
16407 return NULL;
16408 }
16409 h = DUK_TVAL_GET_OBJECT(tv);
16410 DUK_ASSERT(h != NULL);
16411
16413 return NULL;
16414 }
16416 f = (duk_hnativefunction *) h;
16422 duk_hthread *thr = (duk_hthread *) ctx;
16424
16426
16427 ret = duk_get_c_function(ctx, index);
16428 if (!ret) {
16430 }
16431 return ret;
16432}
16433
16437 }
16438}
16439
16442
16443 return (duk_context *) duk_get_hthread(ctx, index);
16444}
16445
16448
16449 return (duk_context *) duk_require_hthread(ctx, index);
16450}
16453 duk_tval *tv;
16454 void *ret;
16455
16457
16458 tv = duk_get_tval(ctx, index);
16459 if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
16460 ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
16461 DUK_ASSERT(ret != NULL);
16462 return ret;
16463 }
16464
16465 return (void *) NULL;
16466}
16467
16469 duk_hthread *thr = (duk_hthread *) ctx;
16470 duk_tval *tv;
16471 void *ret;
16472
16474
16475 tv = duk_require_tval(ctx, index);
16476 DUK_ASSERT(tv != NULL);
16478 ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
16479 DUK_ASSERT(ret != NULL);
16480 return ret;
16481 }
16482
16484 return (void *) NULL; /* not reachable */
16485}
16486
16487#if 0
16488/* This would be pointless: we'd return NULL for both lightfuncs and
16489 * unexpected types.
16490 */
16491DUK_INTERNAL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) {
16492}
16493#endif
16494
16495/* Useful for internal call sites where we either expect an object (function)
16496 * or a lightfunc. Accepts an object (returned as is) or a lightfunc (coerced
16497 * to an object). Return value is NULL if value is neither an object nor a
16498 * lightfunc.
16499 */
16501 duk_tval *tv;
16502
16504
16505 tv = duk_require_tval(ctx, index);
16506 DUK_ASSERT(tv != NULL);
16507 if (DUK_TVAL_IS_OBJECT(tv)) {
16508 return DUK_TVAL_GET_OBJECT(tv);
16509 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16510 duk_to_object(ctx, index);
16511 return duk_require_hobject(ctx, index);
16512 }
16513
16514 return NULL;
16515}
16516
16517/* Useful for internal call sites where we either expect an object (function)
16518 * or a lightfunc. Returns NULL for a lightfunc.
16519 */
16521 duk_hthread *thr = (duk_hthread *) ctx;
16522 duk_tval *tv;
16523
16525
16526 tv = duk_require_tval(ctx, index);
16527 DUK_ASSERT(tv != NULL);
16528 if (DUK_TVAL_IS_OBJECT(tv)) {
16529 return DUK_TVAL_GET_OBJECT(tv);
16530 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16531 return NULL;
16532 }
16534 return NULL; /* not reachable */
16535}
16536
16537/* Useful for internal call sites where we either expect an object (function)
16538 * or a lightfunc. Accepts an object (returned as is) or a lightfunc (coerced
16539 * to an object). Return value is never NULL.
16540 */
16542 duk_hthread *thr = (duk_hthread *) ctx;
16543 duk_tval *tv;
16544
16546
16547 tv = duk_require_tval(ctx, index);
16548 if (DUK_TVAL_IS_OBJECT(tv)) {
16549 return DUK_TVAL_GET_OBJECT(tv);
16550 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16551 duk_to_object(ctx, index);
16552 return duk_require_hobject(ctx, index);
16553 }
16555 return NULL; /* not reachable */
16556}
16557
16559 duk_hobject *h;
16560
16562 DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
16563 DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
16564
16566 if (h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum) {
16567 h = NULL;
16568 }
16569 return h;
16570}
16571
16573 duk_hthread *thr;
16574 duk_hobject *h;
16577 DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
16578 DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
16579 thr = (duk_hthread *) ctx;
16580
16582 if (!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum)) {
16583 duk_hstring *h_class;
16585 DUK_UNREF(h_class);
16586
16588 }
16589 return h;
16590}
16591
16593 duk_tval *tv;
16594
16596
16597 tv = duk_get_tval(ctx, index);
16598 if (!tv) {
16599 return 0;
16600 }
16601
16602 switch (DUK_TVAL_GET_TAG(tv)) {
16603 case DUK_TAG_UNDEFINED:
16604 case DUK_TAG_NULL:
16605 case DUK_TAG_BOOLEAN:
16606 case DUK_TAG_POINTER:
16607 return 0;
16608 case DUK_TAG_STRING: {
16610 DUK_ASSERT(h != NULL);
16612 }
16613 case DUK_TAG_OBJECT: {
16615 DUK_ASSERT(h != NULL);
16616 return (duk_size_t) duk_hobject_get_length((duk_hthread *) ctx, h);
16617 }
16618 case DUK_TAG_BUFFER: {
16620 DUK_ASSERT(h != NULL);
16621 return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
16622 }
16623 case DUK_TAG_LIGHTFUNC: {
16625 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
16626 return (duk_size_t) DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
16627 }
16628#if defined(DUK_USE_FASTINT)
16629 case DUK_TAG_FASTINT:
16630#endif
16631 default:
16632 /* number */
16635 return 0;
16636 }
16637
16639}
16640
16642 duk_hthread *thr = (duk_hthread *) ctx;
16643 duk_hobject *h;
16644
16646
16647 h = duk_get_hobject(ctx, index);
16648 if (!h) {
16649 return;
16650 }
16651
16652 duk_hobject_set_length(thr, h, (duk_uint32_t) length); /* XXX: typing */
16653}
16654
16655/*
16656 * Conversions and coercions
16657 *
16658 * The conversion/coercions are in-place operations on the value stack.
16659 * Some operations are implemented here directly, while others call a
16660 * helper in duk_js_ops.c after validating arguments.
16661 */
16662
16663/* E5 Section 8.12.8 */
16664
16666 if (duk_get_prop_stridx(ctx, index, func_stridx)) {
16667 /* [ ... func ] */
16668 if (duk_is_callable(ctx, -1)) {
16669 duk_dup(ctx, index); /* -> [ ... func this ] */
16670 duk_call_method(ctx, 0); /* -> [ ... retval ] */
16671 if (duk_is_primitive(ctx, -1)) {
16672 duk_replace(ctx, index);
16673 return 1;
16674 }
16675 /* [ ... retval ]; popped below */
16676 }
16677 }
16678 duk_pop(ctx); /* [ ... func/retval ] -> [ ... ] */
16679 return 0;
16680}
16681
16683 duk_hthread *thr = (duk_hthread *) ctx;
16684 duk_hobject *obj;
16685 /* inline initializer for coercers[] is not allowed by old compilers like BCC */
16686 duk_small_int_t coercers[2];
16687
16689 DUK_ASSERT(thr != NULL);
16690
16691 coercers[0] = DUK_STRIDX_VALUE_OF;
16692 coercers[1] = DUK_STRIDX_TO_STRING;
16693
16696
16697 if (hint == DUK_HINT_NONE) {
16699 hint = DUK_HINT_STRING;
16700 } else {
16701 hint = DUK_HINT_NUMBER;
16702 }
16703 }
16705 if (hint == DUK_HINT_STRING) {
16706 coercers[0] = DUK_STRIDX_TO_STRING;
16707 coercers[1] = DUK_STRIDX_VALUE_OF;
16708 }
16709
16710 if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[0])) {
16711 return;
16712 }
16713
16714 if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[1])) {
16715 return;
16717
16719}
16720
16722 duk_hthread *thr = (duk_hthread *) ctx;
16723 duk_tval *tv;
16724
16726 DUK_UNREF(thr);
16727
16728 tv = duk_require_tval(ctx, index);
16730 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
16731}
16732
16734 duk_hthread *thr = (duk_hthread *) ctx;
16735 duk_tval *tv;
16736
16738 DUK_UNREF(thr);
16739
16740 tv = duk_require_tval(ctx, index);
16741 DUK_ASSERT(tv != NULL);
16742 DUK_TVAL_SET_NULL_UPDREF(thr, tv); /* side effects */
16743}
16745/* E5 Section 9.1 */
16748 DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
16749
16751
16754 /* everything except object stay as is */
16755 return;
16756 }
16757 duk_to_defaultvalue(ctx, index, hint);
16758}
16759
16760/* E5 Section 9.2 */
16762 duk_hthread *thr = (duk_hthread *) ctx;
16763 duk_tval *tv;
16764 duk_bool_t val;
16765
16767 DUK_UNREF(thr);
16768
16770
16771 tv = duk_require_tval(ctx, index);
16772 DUK_ASSERT(tv != NULL);
16773
16774 val = duk_js_toboolean(tv);
16775 DUK_ASSERT(val == 0 || val == 1);
16776
16777 /* Note: no need to re-lookup tv, conversion is side effect free */
16778 DUK_ASSERT(tv != NULL);
16779 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val); /* side effects */
16780 return val;
16781}
16782
16784 duk_hthread *thr = (duk_hthread *) ctx;
16785 duk_tval *tv;
16786 duk_double_t d;
16787
16789
16791 DUK_ASSERT(tv != NULL);
16792 /* XXX: fastint? */
16793 d = duk_js_tonumber(thr, tv);
16794
16795 /* Note: need to re-lookup because ToNumber() may have side effects */
16796 tv = duk_require_tval(ctx, index);
16797 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
16798 return d;
16799}
16800
16801/* XXX: combine all the integer conversions: they share everything
16802 * but the helper function for coercion.
16803 */
16804
16806
16808 duk_hthread *thr = (duk_hthread *) ctx;
16810 duk_double_t d;
16811
16813
16814 tv = duk_require_tval(ctx, index);
16815 DUK_ASSERT(tv != NULL);
16816 d = coerce_func(thr, tv);
16817
16818 /* XXX: fastint? */
16819
16820 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16821 tv = duk_require_tval(ctx, index);
16822 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
16823 return d;
16824}
16825
16827 /* Value coercion (in stack): ToInteger(), E5 Section 9.4
16828 * API return value coercion: custom
16829 */
16832 return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
16833}
16834
16836 /* Value coercion (in stack): ToInteger(), E5 Section 9.4
16837 * API return value coercion: custom
16838 */
16841 return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
16842}
16843
16845 duk_hthread *thr = (duk_hthread *) ctx;
16846 duk_tval *tv;
16847 duk_int32_t ret;
16848
16850
16851 tv = duk_require_tval(ctx, index);
16852 DUK_ASSERT(tv != NULL);
16853 ret = duk_js_toint32(thr, tv);
16854
16855 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16856 tv = duk_require_tval(ctx, index);
16857 DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv, ret); /* side effects */
16858 return ret;
16859}
16860
16862 duk_hthread *thr = (duk_hthread *) ctx;
16863 duk_tval *tv;
16864 duk_uint32_t ret;
16865
16867
16868 tv = duk_require_tval(ctx, index);
16869 DUK_ASSERT(tv != NULL);
16870 ret = duk_js_touint32(thr, tv);
16871
16872 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16873 tv = duk_require_tval(ctx, index);
16874 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret); /* side effects */
16875 return ret;
16876}
16877
16879 duk_hthread *thr = (duk_hthread *) ctx;
16881 duk_uint16_t ret;
16882
16884
16885 tv = duk_require_tval(ctx, index);
16886 DUK_ASSERT(tv != NULL);
16887 ret = duk_js_touint16(thr, tv);
16888
16889 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16890 tv = duk_require_tval(ctx, index);
16891 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret); /* side effects */
16892 return ret;
16893}
16894
16895#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16896/* Special coercion for Uint8ClampedArray. */
16898 duk_double_t d;
16899 duk_double_t t;
16900 duk_uint8_t ret;
16901
16902 /* XXX: Simplify this algorithm, should be possible to come up with
16903 * a shorter and faster algorithm by inspecting IEEE representation
16904 * directly.
16905 */
16906
16907 d = duk_to_number(ctx, index);
16908 if (d <= 0.0) {
16909 return 0;
16910 } else if (d >= 255) {
16911 return 255;
16912 } else if (DUK_ISNAN(d)) {
16913 /* Avoid NaN-to-integer coercion as it is compiler specific. */
16914 return 0;
16916
16917 t = d - DUK_FLOOR(d);
16918 if (t == 0.5) {
16919 /* Exact halfway, round to even. */
16920 ret = (duk_uint8_t) d;
16921 ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
16922 * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
16923 */
16924 } else {
16925 /* Not halfway, round to nearest. */
16926 ret = (duk_uint8_t) (d + 0.5);
16927 }
16928 return ret;
16930#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
16931
16932DUK_EXTERNAL const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
16934
16935 (void) duk_to_string(ctx, index);
16936 return duk_require_lstring(ctx, index, out_len);
16937}
16938
16941
16942 duk_to_string(ctx, -1);
16943 return 1;
16944}
16945
16948
16950
16951 /* We intentionally ignore the duk_safe_call() return value and only
16952 * check the output type. This way we don't also need to check that
16953 * the returned value is indeed a string in the success case.
16954 */
16955
16956 duk_dup(ctx, index);
16957 (void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/);
16958 if (!duk_is_string(ctx, -1)) {
16959 /* Error: try coercing error to string once. */
16960 (void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/);
16961 if (!duk_is_string(ctx, -1)) {
16962 /* Double error */
16963 duk_pop(ctx);
16965 } else {
16966 ;
16967 }
16968 } else {
16969 ;
16970 }
16972 DUK_ASSERT(duk_get_string(ctx, -1) != NULL);
16973
16974 duk_replace(ctx, index);
16975 return duk_get_lstring(ctx, index, out_len);
16976}
16977
16978#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
16979DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index) {
16980 (void) duk_safe_to_string(ctx, index);
16983 return duk_get_hstring(ctx, index);
16984}
16985#endif
16986
16987/* Coerce top into Object.prototype.toString() output. */
16989 duk_hthread *thr;
16990 duk_uint_t typemask;
16991 duk_hstring *h_strclass;
16992
16994 thr = (duk_hthread *) ctx;
16995 DUK_UNREF(thr);
16996
16997 typemask = duk_get_type_mask(ctx, -1);
16998 if (typemask & DUK_TYPE_MASK_UNDEFINED) {
16999 h_strclass = DUK_HTHREAD_STRING_UC_UNDEFINED(thr);
17000 } else if (typemask & DUK_TYPE_MASK_NULL) {
17002 } else {
17003 duk_hobject *h_obj;
17004
17005 duk_to_object(ctx, -1);
17006 h_obj = duk_get_hobject(ctx, -1);
17007 DUK_ASSERT(h_obj != NULL);
17008
17009 h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h_obj);
17010 }
17011 DUK_ASSERT(h_strclass != NULL);
17012
17013 duk_pop(ctx);
17014 duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
17015}
17016
17017#if !defined(DUK_USE_PARANOID_ERRORS)
17019 duk_hthread *thr;
17020 duk_hstring *h_strclass;
17021
17023 DUK_ASSERT(h != NULL);
17024 thr = (duk_hthread *) ctx;
17025 DUK_UNREF(thr);
17026
17027 h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h);
17028 DUK_ASSERT(h_strclass != NULL);
17029 duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
17030}
17031#endif /* !DUK_USE_PARANOID_ERRORS */
17032
17033/* XXX: other variants like uint, u32 etc */
17035 duk_hthread *thr = (duk_hthread *) ctx;
17036 duk_tval *tv;
17037 duk_tval tv_tmp;
17038 duk_double_t d, dmin, dmax;
17039 duk_int_t res;
17040 duk_bool_t clamped = 0;
17041
17043
17044 tv = duk_require_tval(ctx, index);
17045 DUK_ASSERT(tv != NULL);
17046 d = duk_js_tointeger(thr, tv); /* E5 Section 9.4, ToInteger() */
17047
17048 dmin = (duk_double_t) minval;
17049 dmax = (duk_double_t) maxval;
17050
17051 if (d < dmin) {
17052 clamped = 1;
17053 res = minval;
17054 d = dmin;
17055 } else if (d > dmax) {
17056 clamped = 1;
17057 res = maxval;
17058 d = dmax;
17059 } else {
17060 res = (duk_int_t) d;
17061 }
17062 DUK_UNREF(d); /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
17063 /* 'd' and 'res' agree here */
17064
17065 /* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
17066 tv = duk_get_tval(ctx, index);
17067 DUK_ASSERT(tv != NULL); /* not popped by side effect */
17068 DUK_TVAL_SET_TVAL(&tv_tmp, tv);
17069#if defined(DUK_USE_FASTINT)
17070#if (DUK_INT_MAX <= 0x7fffffffL)
17071 DUK_TVAL_SET_FASTINT_I32(tv, res);
17072#else
17073 /* Clamping needed if duk_int_t is 64 bits. */
17074 if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
17075 DUK_TVAL_SET_FASTINT(tv, res);
17076 } else {
17077 DUK_TVAL_SET_NUMBER(tv, d);
17078 }
17079#endif
17080#else
17081 DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */
17082#endif
17083 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
17084
17085 if (out_clamped) {
17086 *out_clamped = clamped;
17087 } else {
17088 /* coerced value is updated to value stack even when RangeError thrown */
17089 if (clamped) {
17091 }
17092 }
17093
17094 return res;
17095}
17096
17099 return duk_to_int_clamped_raw(ctx, index, minval, maxval, &dummy);
17100}
17101
17103 return duk_to_int_clamped_raw(ctx, index, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */
17104}
17105
17107 duk_hthread *thr = (duk_hthread *) ctx;
17108 duk_tval *tv;
17109
17111 DUK_UNREF(thr);
17112
17114
17115 tv = duk_require_tval(ctx, index);
17116 DUK_ASSERT(tv != NULL);
17117
17118 switch (DUK_TVAL_GET_TAG(tv)) {
17119 case DUK_TAG_UNDEFINED: {
17121 break;
17122 }
17123 case DUK_TAG_NULL: {
17125 break;
17126 }
17127 case DUK_TAG_BOOLEAN: {
17128 if (DUK_TVAL_GET_BOOLEAN(tv)) {
17130 } else {
17132 }
17133 break;
17134 }
17135 case DUK_TAG_STRING: {
17136 /* nop */
17137 goto skip_replace;
17138 }
17139 case DUK_TAG_OBJECT: {
17141 return duk_to_string(ctx, index); /* Note: recursive call */
17142 }
17143 case DUK_TAG_BUFFER: {
17145
17146 /* Note: this allows creation of internal strings. */
17147
17148 DUK_ASSERT(h != NULL);
17149 duk_push_lstring(ctx,
17150 (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
17152 break;
17153 }
17154 case DUK_TAG_POINTER: {
17155 void *ptr = DUK_TVAL_GET_POINTER(tv);
17156 if (ptr != NULL) {
17157 duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) ptr);
17158 } else {
17159 /* Represent a null pointer as 'null' to be consistent with
17160 * the JX format variant. Native '%p' format for a NULL
17161 * pointer may be e.g. '(nil)'.
17162 */
17164 }
17165 break;
17166 }
17167 case DUK_TAG_LIGHTFUNC: {
17168 /* Should match Function.prototype.toString() */
17170 break;
17171 }
17172#if defined(DUK_USE_FASTINT)
17173 case DUK_TAG_FASTINT:
17174#endif
17175 default: {
17176 /* number */
17179 duk_push_tval(ctx, tv);
17181 10 /*radix*/,
17182 0 /*precision:shortest*/,
17183 0 /*force_exponential*/);
17184 break;
17185 }
17187
17188 duk_replace(ctx, index);
17189
17190 skip_replace:
17191 return duk_require_string(ctx, index);
17192}
17193
17195 duk_hstring *ret;
17197 duk_to_string(ctx, index);
17198 ret = duk_get_hstring(ctx, index);
17199 DUK_ASSERT(ret != NULL);
17200 return ret;
17201}
17202
17204 duk_hthread *thr = (duk_hthread *) ctx;
17205 duk_hbuffer *h_buf;
17206 const duk_uint8_t *src_data;
17207 duk_size_t src_size;
17208 duk_uint8_t *dst_data;
17209
17211 DUK_UNREF(thr);
17212
17214
17215 h_buf = duk_get_hbuffer(ctx, index);
17216 if (h_buf != NULL) {
17217 /* Buffer is kept as is, with the fixed/dynamic nature of the
17218 * buffer only changed if requested. An external buffer
17219 * is converted into a non-external dynamic buffer in a
17220 * duk_to_dynamic_buffer() call.
17221 */
17222 duk_uint_t tmp;
17223 duk_uint8_t *tmp_ptr;
17224
17225 tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
17226 src_data = (const duk_uint8_t *) tmp_ptr;
17227 src_size = DUK_HBUFFER_GET_SIZE(h_buf);
17228
17230 if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
17231 mode == DUK_BUF_MODE_DONTCARE) {
17232 /* Note: src_data may be NULL if input is a zero-size
17233 * dynamic buffer.
17234 */
17235 dst_data = tmp_ptr;
17236 goto skip_copy;
17237 }
17238 } else {
17239 /* Non-buffer value is first ToString() coerced, then converted
17240 * to a buffer (fixed buffer is used unless a dynamic buffer is
17241 * explicitly requested).
17242 */
17243
17244 src_data = (const duk_uint8_t *) duk_to_lstring(ctx, index, &src_size);
17245 }
17246
17247 dst_data = (duk_uint8_t *) duk_push_buffer(ctx, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
17248 if (DUK_LIKELY(src_size > 0)) {
17249 /* When src_size == 0, src_data may be NULL (if source
17250 * buffer is dynamic), and dst_data may be NULL (if
17251 * target buffer is dynamic). Avoid zero-size memcpy()
17252 * with an invalid pointer.
17253 */
17254 DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);
17255 }
17256 duk_replace(ctx, index);
17257 skip_copy:
17258
17259 if (out_size) {
17260 *out_size = src_size;
17261 }
17262 return dst_data;
17263}
17264
17266 duk_tval *tv;
17267 void *res;
17268
17270
17272
17273 tv = duk_require_tval(ctx, index);
17274 DUK_ASSERT(tv != NULL);
17275
17276 switch (DUK_TVAL_GET_TAG(tv)) {
17277 case DUK_TAG_UNDEFINED:
17278 case DUK_TAG_NULL:
17279 case DUK_TAG_BOOLEAN:
17280 res = NULL;
17281 break;
17282 case DUK_TAG_POINTER:
17283 res = DUK_TVAL_GET_POINTER(tv);
17284 break;
17285 case DUK_TAG_STRING:
17286 case DUK_TAG_OBJECT:
17287 case DUK_TAG_BUFFER:
17288 /* Heap allocated: return heap pointer which is NOT useful
17289 * for the caller, except for debugging.
17290 */
17291 res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
17292 break;
17293 case DUK_TAG_LIGHTFUNC:
17294 /* Function pointers do not always cast correctly to void *
17295 * (depends on memory and segmentation model for instance),
17296 * so they coerce to NULL.
17297 */
17298 res = NULL;
17299 break;
17300#if defined(DUK_USE_FASTINT)
17301 case DUK_TAG_FASTINT:
17302#endif
17303 default:
17304 /* number */
17307 res = NULL;
17308 break;
17309 }
17310
17311 duk_push_pointer(ctx, res);
17312 duk_replace(ctx, index);
17313 return res;
17314}
17315
17317 duk_hthread *thr = (duk_hthread *) ctx;
17318 duk_tval *tv;
17319 duk_uint_t flags = 0; /* shared flags for a subset of types */
17321
17323
17325
17326 tv = duk_require_tval(ctx, index);
17327 DUK_ASSERT(tv != NULL);
17328
17329 switch (DUK_TVAL_GET_TAG(tv)) {
17330 case DUK_TAG_UNDEFINED:
17331 case DUK_TAG_NULL: {
17333 break;
17334 }
17335 case DUK_TAG_BOOLEAN: {
17339 goto create_object;
17340 }
17341 case DUK_TAG_STRING: {
17346 goto create_object;
17347 }
17348 case DUK_TAG_OBJECT: {
17349 /* nop */
17350 break;
17351 }
17352 case DUK_TAG_BUFFER: {
17353 /* A plain buffer coerces to a Duktape.Buffer because it's the
17354 * object counterpart of the plain buffer value. But it might
17355 * still make more sense to produce an ArrayBuffer here?
17356 */
17357
17358 duk_hbufferobject *h_bufobj;
17359 duk_hbuffer *h_val;
17360
17361 h_val = DUK_TVAL_GET_BUFFER(tv);
17362 DUK_ASSERT(h_val != NULL);
17363
17364 h_bufobj = duk_push_bufferobject_raw(ctx,
17369 DUK_ASSERT(h_bufobj != NULL);
17372
17373 h_bufobj->buf = h_val;
17374 DUK_HBUFFER_INCREF(thr, h_val);
17375 DUK_ASSERT(h_bufobj->offset == 0);
17376 h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
17377 DUK_ASSERT(h_bufobj->shift == 0);
17379
17381 goto replace_value;
17382 }
17383 case DUK_TAG_POINTER: {
17387 goto create_object;
17388 }
17389 case DUK_TAG_LIGHTFUNC: {
17390 /* Lightfunc coerces to a Function instance with concrete
17391 * properties. Since 'length' is virtual for Duktape/C
17392 * functions, don't need to define that.
17393 *
17394 * The result is made extensible to mimic what happens to
17395 * strings:
17396 * > Object.isExtensible(Object('foo'))
17397 * true
17398 */
17399 duk_small_uint_t lf_flags;
17400 duk_idx_t nargs;
17401 duk_small_uint_t lf_len;
17402 duk_c_function func;
17404
17405 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
17406
17407 nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
17408 if (nargs == DUK_LFUNC_NARGS_VARARGS) {
17409 nargs = (duk_idx_t) DUK_VARARGS;
17410 }
17417 /* DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC: omitted here intentionally */
17419 (void) duk__push_c_function_raw(ctx, func, nargs, flags);
17420
17421 lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
17422 if ((duk_idx_t) lf_len != nargs) {
17423 /* Explicit length is only needed if it differs from 'nargs'. */
17424 duk_push_int(ctx, (duk_int_t) lf_len);
17426 }
17427 duk_push_lightfunc_name(ctx, tv);
17429
17430 nf = duk_get_hnativefunction(ctx, -1);
17431 DUK_ASSERT(nf != NULL);
17432 nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
17433
17434 /* Enable DUKFUNC exotic behavior once properties are set up. */
17436 goto replace_value;
17437 }
17438#if defined(DUK_USE_FASTINT)
17439 case DUK_TAG_FASTINT:
17440#endif
17441 default: {
17447 goto create_object;
17448 }
17449 }
17450 return;
17451
17452 create_object:
17453 (void) duk_push_object_helper(ctx, flags, proto);
17454
17455 /* Note: Boolean prototype's internal value property is not writable,
17456 * but duk_xdef_prop_stridx() disregards the write protection. Boolean
17457 * instances are immutable.
17458 *
17459 * String and buffer special behaviors are already enabled which is not
17460 * ideal, but a write to the internal value is not affected by them.
17461 */
17462 duk_dup(ctx, index);
17464
17465 replace_value:
17467}
17468
17469/*
17470 * Type checking
17471 */
17472
17474 duk_tval *tv;
17475
17476 tv = duk_get_tval(ctx, index);
17477 if (!tv) {
17478 return 0;
17479 }
17480 return (DUK_TVAL_GET_TAG(tv) == tag);
17481}
17482
17484 duk_hobject *obj;
17485
17487
17488 obj = duk_get_hobject(ctx, index);
17489 if (obj) {
17490 return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
17491 }
17492 return 0;
17493}
17494
17496 duk_tval *tv;
17497
17499
17500 tv = duk_get_tval(ctx, index);
17501 if (!tv) {
17502 return DUK_TYPE_NONE;
17503 }
17504 switch (DUK_TVAL_GET_TAG(tv)) {
17505 case DUK_TAG_UNDEFINED:
17506 return DUK_TYPE_UNDEFINED;
17507 case DUK_TAG_NULL:
17508 return DUK_TYPE_NULL;
17509 case DUK_TAG_BOOLEAN:
17510 return DUK_TYPE_BOOLEAN;
17511 case DUK_TAG_STRING:
17512 return DUK_TYPE_STRING;
17513 case DUK_TAG_OBJECT:
17514 return DUK_TYPE_OBJECT;
17515 case DUK_TAG_BUFFER:
17516 return DUK_TYPE_BUFFER;
17517 case DUK_TAG_POINTER:
17518 return DUK_TYPE_POINTER;
17519 case DUK_TAG_LIGHTFUNC:
17520 return DUK_TYPE_LIGHTFUNC;
17521#if defined(DUK_USE_FASTINT)
17522 case DUK_TAG_FASTINT:
17523#endif
17524 default:
17525 /* Note: number has no explicit tag (in 8-byte representation) */
17528 return DUK_TYPE_NUMBER;
17529 }
17531}
17532
17533#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
17534DUK_LOCAL const char *duk__type_names[] = {
17535 "none",
17536 "undefined",
17537 "null",
17538 "boolean",
17539 "number",
17540 "string",
17541 "object",
17542 "buffer",
17543 "pointer",
17544 "lightfunc"
17545};
17546
17547DUK_INTERNAL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index) {
17548 duk_int_t type_tag;
17549
17550 type_tag = duk_get_type(ctx, index);
17551 DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
17552 DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
17553
17554 return duk__type_names[type_tag];
17555}
17556#endif
17557
17560
17561 return (duk_get_type(ctx, index) == type) ? 1 : 0;
17562}
17563
17565 duk_tval *tv;
17566
17568
17569 tv = duk_get_tval(ctx, index);
17570 if (!tv) {
17571 return DUK_TYPE_MASK_NONE;
17572 }
17573 switch (DUK_TVAL_GET_TAG(tv)) {
17574 case DUK_TAG_UNDEFINED:
17576 case DUK_TAG_NULL:
17577 return DUK_TYPE_MASK_NULL;
17578 case DUK_TAG_BOOLEAN:
17579 return DUK_TYPE_MASK_BOOLEAN;
17580 case DUK_TAG_STRING:
17581 return DUK_TYPE_MASK_STRING;
17582 case DUK_TAG_OBJECT:
17583 return DUK_TYPE_MASK_OBJECT;
17584 case DUK_TAG_BUFFER:
17586 case DUK_TAG_POINTER:
17587 return DUK_TYPE_MASK_POINTER;
17588 case DUK_TAG_LIGHTFUNC:
17590#if defined(DUK_USE_FASTINT)
17591 case DUK_TAG_FASTINT:
17592#endif
17593 default:
17594 /* Note: number has no explicit tag (in 8-byte representation) */
17597 return DUK_TYPE_MASK_NUMBER;
17598 }
17604
17606
17607 if (duk_get_type_mask(ctx, index) & mask) {
17608 return 1;
17609 }
17628 duk_tval *tv;
17630
17632
17633 tv = duk_get_tval(ctx, index);
17634 if (!tv) {
17635 return 0;
17636 }
17637 tag = DUK_TVAL_GET_TAG(tv);
17638 return (tag == DUK_TAG_UNDEFINED) || (tag == DUK_TAG_NULL);
17639}
17640
17643 return duk__tag_check(ctx, index, DUK_TAG_BOOLEAN);
17644}
17645
17647 duk_tval *tv;
17650
17651 /*
17652 * Number is special because it doesn't have a specific
17653 * tag in the 8-byte representation.
17654 */
17655
17656 /* XXX: shorter version for 12-byte representation? */
17657
17658 tv = duk_get_tval(ctx, index);
17659 if (!tv) {
17660 return 0;
17661 }
17662 return DUK_TVAL_IS_NUMBER(tv);
17663}
17664
17666 /* XXX: This will now return false for non-numbers, even though they would
17667 * coerce to NaN (as a general rule). In particular, duk_get_number()
17668 * returns a NaN for non-numbers, so should this function also return
17669 * true for non-numbers?
17670 */
17672 duk_tval *tv;
17673
17675
17677 if (!tv || !DUK_TVAL_IS_NUMBER(tv)) {
17678 return 0;
17679 }
17680 return DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
17685 return duk__tag_check(ctx, index, DUK_TAG_STRING);
17690 return duk__tag_check(ctx, index, DUK_TAG_OBJECT);
17702
17706}
17707
17709 duk_hobject *obj;
17710
17712
17713 obj = duk_get_hobject(ctx, index);
17714 if (obj) {
17716 }
17717 return 0;
17718}
17725 tv = duk_get_tval(ctx, index);
17726 if (tv && DUK_TVAL_IS_LIGHTFUNC(tv)) {
17727 return 1;
17728 }
17730 index,
17739 index,
17746 index,
17760 index,
17762}
17763
17765 duk_tval *tv;
17766
17768
17769 tv = duk_get_tval(ctx, index);
17770 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17772 DUK_ASSERT(h != NULL);
17773 return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
17774 }
17775 return 0;
17776}
17777
17779 duk_tval *tv;
17780
17782
17783 tv = duk_get_tval(ctx, index);
17784 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17786 DUK_ASSERT(h != NULL);
17787 return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
17788 }
17789 return 0;
17790}
17791
17793 duk_tval *tv;
17794
17796
17797 tv = duk_get_tval(ctx, index);
17798 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17800 DUK_ASSERT(h != NULL);
17801 return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
17802 }
17803 return 0;
17804}
17805
17807 duk_hthread *thr = (duk_hthread *) ctx;
17808 duk_hobject *h;
17809 duk_uint_t sanity;
17810
17812
17813 h = duk_get_hobject(ctx, index);
17814
17816 do {
17817 if (!h) {
17818 return DUK_ERR_NONE;
17819 }
17820 if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
17821 return DUK_ERR_EVAL_ERROR;
17822 }
17824 return DUK_ERR_RANGE_ERROR;
17825 }
17828 }
17830 return DUK_ERR_SYNTAX_ERROR;
17831 }
17832 if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
17833 return DUK_ERR_TYPE_ERROR;
17834 }
17836 return DUK_ERR_URI_ERROR;
17837 }
17838 if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
17839 return DUK_ERR_ERROR;
17840 }
17841
17842 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
17843 } while (--sanity > 0);
17844
17845 return DUK_ERR_NONE;
17846}
17847
17849 * Pushers
17850 */
17851
17853 duk_hthread *thr;
17854 duk_tval *tv_slot;
17855
17857 DUK_ASSERT(tv != NULL);
17858 thr = (duk_hthread *) ctx;
17860 tv_slot = thr->valstack_top++;
17861 DUK_TVAL_SET_TVAL(tv_slot, tv);
17862 DUK_TVAL_INCREF(thr, tv); /* no side effects */
17863}
17864
17866 duk_hthread *thr;
17867
17869 thr = (duk_hthread *) ctx;
17871
17872 /* Because value stack init policy is 'undefined above top',
17873 * we don't need to write, just assert.
17874 */
17875 thr->valstack_top++;
17877}
17878
17880 duk_hthread *thr;
17881 duk_tval *tv_slot;
17882
17884 thr = (duk_hthread *) ctx;
17886 tv_slot = thr->valstack_top++;
17887 DUK_TVAL_SET_NULL(tv_slot);
17888}
17889
17891 duk_hthread *thr;
17892 duk_tval *tv_slot;
17894
17896 thr = (duk_hthread *) ctx;
17898 b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */
17899 tv_slot = thr->valstack_top++;
17900 DUK_TVAL_SET_BOOLEAN(tv_slot, b);
17901}
17902
17904 duk_hthread *thr;
17905 duk_tval *tv_slot;
17906
17908 thr = (duk_hthread *) ctx;
17910 tv_slot = thr->valstack_top++;
17912}
17913
17915 duk_hthread *thr;
17916 duk_tval *tv_slot;
17917
17919 thr = (duk_hthread *) ctx;
17921 tv_slot = thr->valstack_top++;
17924
17925/* normalize NaN which may not match our canonical internal NaN */
17927 duk_hthread *thr;
17928 duk_tval *tv_slot;
17930
17932 thr = (duk_hthread *) ctx;
17934 du.d = val;
17936 tv_slot = thr->valstack_top++;
17937 DUK_TVAL_SET_NUMBER(tv_slot, du.d);
17938}
17939
17941#if defined(DUK_USE_FASTINT)
17942 duk_hthread *thr;
17943 duk_tval *tv_slot;
17944
17946 thr = (duk_hthread *) ctx;
17948 tv_slot = thr->valstack_top++;
17949#if DUK_INT_MAX <= 0x7fffffffL
17950 DUK_TVAL_SET_FASTINT_I32(tv_slot, (duk_int32_t) val);
17951#else
17952 if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
17953 DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
17954 } else {
17955 duk_double_t = (duk_double_t) val;
17957 }
17958#endif
17959#else /* DUK_USE_FASTINT */
17960 duk_hthread *thr;
17961 duk_tval *tv_slot;
17962 duk_double_t d;
17963
17965 thr = (duk_hthread *) ctx;
17967 d = (duk_double_t) val;
17968 tv_slot = thr->valstack_top++;
17969 DUK_TVAL_SET_NUMBER(tv_slot, d);
17970#endif /* DUK_USE_FASTINT */
17971}
17972
17974#if defined(DUK_USE_FASTINT)
17975 duk_hthread *thr;
17976 duk_tval *tv_slot;
17977
17979 thr = (duk_hthread *) ctx;
17981 tv_slot = thr->valstack_top++;
17982#if DUK_UINT_MAX <= 0xffffffffUL
17983 DUK_TVAL_SET_FASTINT_U32(tv_slot, (duk_uint32_t) val);
17984#else
17985 if (val <= DUK_FASTINT_MAX) { /* val is unsigned so >= 0 */
17986 /* XXX: take advantage of val being unsigned, no need to mask */
17987 DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
17988 } else {
17989 duk_double_t = (duk_double_t) val;
17991 }
17992#endif
17993#else /* DUK_USE_FASTINT */
17994 duk_hthread *thr;
17995 duk_tval *tv_slot;
17996 duk_double_t d;
17997
17999 thr = (duk_hthread *) ctx;
18001 d = (duk_double_t) val;
18002 tv_slot = thr->valstack_top++;
18003 DUK_TVAL_SET_NUMBER(tv_slot, d);
18004#endif /* DUK_USE_FASTINT */
18005}
18006
18008 duk_hthread *thr;
18009 duk_tval *tv_slot;
18011
18013 thr = (duk_hthread *) ctx;
18017 tv_slot = thr->valstack_top++;
18018 DUK_TVAL_SET_NUMBER(tv_slot, du.d);
18019}
18020
18021DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len) {
18022 duk_hthread *thr = (duk_hthread *) ctx;
18023 duk_hstring *h;
18024 duk_tval *tv_slot;
18025
18027
18028 /* check stack before interning (avoid hanging temp) */
18029 if (thr->valstack_top >= thr->valstack_end) {
18031 }
18032
18033 /* NULL with zero length represents an empty string; NULL with higher
18034 * length is also now trated like an empty string although it is
18035 * a bit dubious. This is unlike duk_push_string() which pushes a
18036 * 'null' if the input string is a NULL.
18037 */
18038 if (!str) {
18039 len = 0;
18041
18042 /* Check for maximum string length */
18043 if (len > DUK_HSTRING_MAX_BYTELEN) {
18045 }
18046
18047 h = duk_heap_string_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
18048 DUK_ASSERT(h != NULL);
18049
18050 tv_slot = thr->valstack_top++;
18051 DUK_TVAL_SET_STRING(tv_slot, h);
18052 DUK_HSTRING_INCREF(thr, h); /* no side effects */
18053
18054 return (const char *) DUK_HSTRING_GET_DATA(h);
18055}
18057DUK_EXTERNAL const char *duk_push_string(duk_context *ctx, const char *str) {
18059
18060 if (str) {
18061 return duk_push_lstring(ctx, str, DUK_STRLEN(str));
18062 } else {
18063 duk_push_null(ctx);
18064 return NULL;
18065 }
18066}
18067
18068#ifdef DUK_USE_FILE_IO
18069/* This is a bit clunky because it is ANSI C portable. Should perhaps
18070 * relocate to another file because this is potentially platform
18071 * dependent.
18072 */
18073DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
18074 duk_hthread *thr = (duk_hthread *) ctx;
18075 duk_file *f = NULL;
18076 char *buf;
18077 long sz; /* ANSI C typing */
18078
18080
18081 if (!path) {
18082 goto fail;
18083 }
18084 f = DUK_FOPEN(path, "rb");
18085 if (!f) {
18086 goto fail;
18087 }
18088 if (DUK_FSEEK(f, 0, SEEK_END) < 0) {
18089 goto fail;
18090 }
18091 sz = DUK_FTELL(f);
18092 if (sz < 0) {
18093 goto fail;
18094 }
18095 if (DUK_FSEEK(f, 0, SEEK_SET) < 0) {
18096 goto fail;
18097 }
18098 buf = (char *) duk_push_fixed_buffer(ctx, (duk_size_t) sz);
18099 DUK_ASSERT(buf != NULL);
18100 if ((duk_size_t) DUK_FREAD(buf, 1, (size_t) sz, f) != (duk_size_t) sz) {
18101 goto fail;
18102 }
18103 (void) DUK_FCLOSE(f); /* ignore fclose() error */
18104 f = NULL;
18105 return duk_to_string(ctx, -1);
18106
18107 fail:
18108 if (f) {
18109 DUK_FCLOSE(f);
18110 }
18111
18112 if (flags != 0) {
18113 DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE); /* only flag now */
18114 duk_push_undefined(ctx);
18115 } else {
18116 /* XXX: string not shared because it is conditional */
18117 DUK_ERROR_TYPE(thr, "read file error");
18118 }
18119 return NULL;
18120}
18121#else
18122DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
18123 duk_hthread *thr = (duk_hthread *) ctx;
18125 DUK_UNREF(path);
18126
18127 if (flags != 0) {
18128 DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE); /* only flag now */
18129 duk_push_undefined(ctx);
18130 } else {
18131 /* XXX: string not shared because it is conditional */
18132 DUK_ERROR_UNSUPPORTED(thr, "file I/O disabled");
18133 }
18134 return NULL;
18135}
18136#endif /* DUK_USE_FILE_IO */
18137
18138DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val) {
18139 duk_hthread *thr;
18140 duk_tval *tv_slot;
18141
18143 thr = (duk_hthread *) ctx;
18145 tv_slot = thr->valstack_top++;
18146 DUK_TVAL_SET_POINTER(tv_slot, val);
18147}
18148
18149DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t check_object_coercible) {
18150 duk_hthread *thr;
18151 duk_tval *tv_slot;
18152
18154 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
18155 thr = (duk_hthread *) ctx;
18158
18159 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* because of valstack init policy */
18160 tv_slot = thr->valstack_top++;
18161
18162 if (DUK_UNLIKELY(thr->callstack_top == 0)) {
18163 if (check_object_coercible) {
18164 goto type_error;
18165 }
18166 /* 'undefined' already on stack top */
18167 } else {
18168 duk_tval *tv;
18169
18170 /* 'this' binding is just before current activation's bottom */
18172 tv = thr->valstack_bottom - 1;
18173 if (check_object_coercible &&
18175 /* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
18176 goto type_error;
18178
18179 DUK_TVAL_SET_TVAL(tv_slot, tv);
18180 DUK_TVAL_INCREF(thr, tv);
18181 }
18182 return;
18184 type_error:
18186}
18187
18190
18191 duk__push_this_helper(ctx, 0 /*check_object_coercible*/);
18192}
18193
18196
18197 duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18198}
18199
18201 duk_hobject *h;
18202
18204
18205 duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18206 duk_to_object(ctx, -1);
18207 h = duk_get_hobject(ctx, -1);
18208 DUK_ASSERT(h != NULL);
18209 return h;
18210}
18211
18213 duk_hstring *h;
18214
18216
18217 duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18218 duk_to_string(ctx, -1);
18219 h = duk_get_hstring(ctx, -1);
18221 return h;
18222}
18223
18225 duk_hthread *thr;
18226
18227 DUK_ASSERT(ctx != NULL);
18228 thr = (duk_hthread *) ctx;
18229
18230 DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */
18231 DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */
18232 DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */
18233
18234 return thr->valstack_bottom - 1;
18235}
18236
18238 duk_hthread *thr = (duk_hthread *) ctx;
18239 duk_activation *act;
18240
18242 DUK_ASSERT(thr != NULL);
18245
18247 if (act) {
18248 duk_push_tval(ctx, &act->tv_func);
18249 } else {
18251 }
18252}
18253
18255 duk_hthread *thr = (duk_hthread *) ctx;
18256
18258 DUK_ASSERT(thr != NULL);
18259
18260 if (thr->heap->curr_thread) {
18262 } else {
18263 duk_push_undefined(ctx);
18264 }
18265}
18266
18271}
18272
18273/* XXX: size optimize */
18277 DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
18278 duk_pop(ctx);
18280 duk_dup_top(ctx);
18281 duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C); /* [ ... parent stash stash ] -> [ ... parent stash ] */
18282 }
18283 duk_remove(ctx, -2);
18284}
18287 duk_hthread *thr = (duk_hthread *) ctx;
18288 duk_heap *heap;
18290 heap = thr->heap;
18291 DUK_ASSERT(heap->heap_object != NULL);
18292 duk_push_hobject(ctx, heap->heap_object);
18293 duk__push_stash(ctx);
18294}
18295
18299 duk__push_stash(ctx);
18300}
18301
18303 duk_hthread *thr = (duk_hthread *) ctx;
18305 if (!target_ctx) {
18307 return; /* not reached */
18308 }
18309 duk_push_hobject(ctx, (duk_hobject *) target_ctx);
18310 duk__push_stash(ctx);
18311}
18312
18313/* XXX: duk_ssize_t would be useful here */
18314DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
18315 duk_int_t len;
18316
18318 DUK_UNREF(ctx);
18319
18320 /* NUL terminator handling doesn't matter here */
18321 len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
18322 if (len < (duk_int_t) sz) {
18323 /* Return value of 'sz' or more indicates output was (potentially)
18324 * truncated.
18325 */
18326 return (duk_int_t) len;
18327 }
18328 return -1;
18329}
18330
18331DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
18332 duk_hthread *thr = (duk_hthread *) ctx;
18333 duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
18335 duk_bool_t pushed_buf = 0;
18336 void *buf;
18337 duk_int_t len; /* XXX: duk_ssize_t */
18338 const char *res;
18339
18341
18342 /* special handling of fmt==NULL */
18343 if (!fmt) {
18344 duk_hstring *h_str;
18346 h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr); /* rely on interning, must be this string */
18347 return (const char *) DUK_HSTRING_GET_DATA(h_str);
18348 }
18349
18350 /* initial estimate based on format string */
18351 sz = DUK_STRLEN(fmt) + 16; /* format plus something to avoid just missing */
18354 }
18355 DUK_ASSERT(sz > 0);
18356
18357 /* Try to make do with a stack buffer to avoid allocating a temporary buffer.
18358 * This works 99% of the time which is quite nice.
18359 */
18360 for (;;) {
18361 va_list ap_copy; /* copied so that 'ap' can be reused */
18362
18363 if (sz <= sizeof(stack_buf)) {
18364 buf = stack_buf;
18365 } else if (!pushed_buf) {
18366 pushed_buf = 1;
18367 buf = duk_push_dynamic_buffer(ctx, sz);
18368 } else {
18369 buf = duk_resize_buffer(ctx, -1, sz);
18370 }
18371 DUK_ASSERT(buf != NULL);
18372
18373 DUK_VA_COPY(ap_copy, ap);
18374 len = duk__try_push_vsprintf(ctx, buf, sz, fmt, ap_copy);
18375 va_end(ap_copy);
18376 if (len >= 0) {
18377 break;
18378 }
18379
18380 /* failed, resize and try again */
18381 sz = sz * 2;
18384 }
18385 }
18386
18387 /* Cannot use duk_to_string() on the buffer because it is usually
18388 * larger than 'len'. Also, 'buf' is usually a stack buffer.
18389 */
18390 res = duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len); /* [ buf? res ] */
18391 if (pushed_buf) {
18392 duk_remove(ctx, -2);
18393 }
18394 return res;
18395}
18396
18397DUK_EXTERNAL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) {
18398 va_list ap;
18399 const char *ret;
18400
18402
18403 /* allow fmt==NULL */
18404 va_start(ap, fmt);
18405 ret = duk_push_vsprintf(ctx, fmt, ap);
18406 va_end(ap);
18407
18408 return ret;
18409}
18410
18411DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
18412 duk_hthread *thr = (duk_hthread *) ctx;
18413 duk_tval *tv_slot;
18414 duk_hobject *h;
18415 duk_idx_t ret;
18416
18418 DUK_ASSERT(prototype_bidx == -1 ||
18419 (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
18420
18421 /* check stack first */
18422 if (thr->valstack_top >= thr->valstack_end) {
18424 }
18425
18426 h = duk_hobject_alloc(thr->heap, hobject_flags_and_class);
18427 if (!h) {
18429 }
18430
18431 DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
18432
18433 tv_slot = thr->valstack_top;
18435 DUK_HOBJECT_INCREF(thr, h); /* no side effects */
18436 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18437 thr->valstack_top++;
18438
18439 /* object is now reachable */
18440
18441 if (prototype_bidx >= 0) {
18442 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[prototype_bidx]);
18443 } else {
18444 DUK_ASSERT(prototype_bidx == -1);
18446 }
18447
18448 return ret;
18450
18452 duk_hthread *thr = (duk_hthread *) ctx;
18453 duk_idx_t ret;
18454 duk_hobject *h;
18455
18457
18458 ret = duk_push_object_helper(ctx, hobject_flags_and_class, -1);
18459 h = duk_get_hobject(ctx, -1);
18460 DUK_ASSERT(h != NULL);
18463 return ret;
18464}
18465
18468
18469 return duk_push_object_helper(ctx,
18473}
18474
18476 duk_hthread *thr = (duk_hthread *) ctx;
18477 duk_hobject *obj;
18478 duk_idx_t ret;
18479
18481
18482 ret = duk_push_object_helper(ctx,
18487
18488 obj = duk_require_hobject(ctx, ret);
18489
18490 /*
18491 * An array must have a 'length' property (E5 Section 15.4.5.2).
18492 * The special array behavior flag must only be enabled once the
18493 * length property has been added.
18494 *
18495 * The internal property must be a number (and preferably a
18496 * fastint if fastint support is enabled).
18497 */
18498
18499 duk_push_int(ctx, 0);
18500#if defined(DUK_USE_FASTINT)
18501 DUK_ASSERT(DUK_TVAL_IS_FASTINT(duk_require_tval(ctx, -1)));
18502#endif
18503
18505 obj,
18509
18510 return ret;
18511}
18512
18514 duk_hthread *thr = (duk_hthread *) ctx;
18515 duk_hthread *obj;
18516 duk_idx_t ret;
18517 duk_tval *tv_slot;
18518
18520
18521 /* check stack first */
18522 if (thr->valstack_top >= thr->valstack_end) {
18524 }
18525
18526 obj = duk_hthread_alloc(thr->heap,
18530 if (!obj) {
18532 }
18534#if defined(DUK_USE_ROM_STRINGS)
18535 /* Nothing to initialize, strs[] is in ROM. */
18536#else
18537#if defined(DUK_USE_HEAPPTR16)
18538 obj->strs16 = thr->strs16;
18539#else
18540 obj->strs = thr->strs;
18541#endif
18542#endif
18543 DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
18544
18545 /* make the new thread reachable */
18546 tv_slot = thr->valstack_top;
18547 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18548 DUK_HTHREAD_INCREF(thr, obj);
18549 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18550 thr->valstack_top++;
18551
18552 /* important to do this *after* pushing, to make the thread reachable for gc */
18553 if (!duk_hthread_init_stacks(thr->heap, obj)) {
18555 }
18556
18557 /* initialize built-ins - either by copying or creating new ones */
18558 if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
18560 } else {
18562 }
18563
18564 /* default prototype (Note: 'obj' must be reachable) */
18566
18567 /* Initial stack size satisfies the stack spare constraints so there
18568 * is no need to require stack here.
18569 */
18572
18573 return ret;
18574}
18575
18577 duk_hthread *thr = (duk_hthread *) ctx;
18579 duk_idx_t ret;
18580 duk_tval *tv_slot;
18581
18583
18584 /* check stack first */
18585 if (thr->valstack_top >= thr->valstack_end) {
18587 }
18588
18589 /* Template functions are not strictly constructable (they don't
18590 * have a "prototype" property for instance), so leave the
18591 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
18592 */
18593
18598 if (!obj) {
18600 }
18601
18602 DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
18603
18604 tv_slot = thr->valstack_top;
18605 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18606 DUK_HOBJECT_INCREF(thr, obj);
18607 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18608 thr->valstack_top++;
18609
18610 /* default prototype (Note: 'obj' must be reachable) */
18612
18613 return ret;
18614}
18615
18617 duk_hthread *thr = (duk_hthread *) ctx;
18619 duk_idx_t ret;
18620 duk_tval *tv_slot;
18621 duk_int16_t func_nargs;
18622
18624
18625 /* check stack first */
18626 if (thr->valstack_top >= thr->valstack_end) {
18628 }
18629 if (func == NULL) {
18630 goto api_error;
18631 }
18632 if (nargs >= 0 && nargs < DUK_HNATIVEFUNCTION_NARGS_MAX) {
18633 func_nargs = (duk_int16_t) nargs;
18634 } else if (nargs == DUK_VARARGS) {
18636 } else {
18637 goto api_error;
18638 }
18639
18640 obj = duk_hnativefunction_alloc(thr->heap, flags);
18641 if (!obj) {
18643 }
18644
18645 obj->func = func;
18646 obj->nargs = func_nargs;
18647
18648 DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
18649 (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
18651 tv_slot = thr->valstack_top;
18652 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18653 DUK_HOBJECT_INCREF(thr, obj);
18654 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18655 thr->valstack_top++;
18656
18657 /* default prototype (Note: 'obj' must be reachable) */
18659
18660 return ret;
18661
18662 api_error:
18664 return 0; /* not reached */
18665}
18666
18682}
18697 (void) duk__push_c_function_raw(ctx, func, nargs, flags);
18699
18701 duk_uint_t flags;
18702
18704
18711
18712 (void) duk__push_c_function_raw(ctx, func, nargs, flags);
18713}
18714
18716 duk_hthread *thr = (duk_hthread *) ctx;
18717 duk_tval tv_tmp;
18718 duk_small_uint_t lf_flags;
18719
18721
18722 /* check stack first */
18723 if (thr->valstack_top >= thr->valstack_end) {
18725 }
18726
18727 if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
18728 /* as is */
18729 } else if (nargs == DUK_VARARGS) {
18731 } else {
18732 goto api_error;
18733 }
18734 if (!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX)) {
18735 goto api_error;
18736 }
18737 if (!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX)) {
18738 goto api_error;
18739 }
18740
18741 lf_flags = DUK_LFUNC_FLAGS_PACK(magic, length, nargs);
18742 DUK_TVAL_SET_LIGHTFUNC(&tv_tmp, func, lf_flags);
18743 duk_push_tval(ctx, &tv_tmp); /* XXX: direct valstack write */
18745 return ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
18746
18747 api_error:
18749 return 0; /* not reached */
18750}
18751
18752DUK_INTERNAL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
18753 duk_hthread *thr = (duk_hthread *) ctx;
18754 duk_hbufferobject *obj;
18755 duk_tval *tv_slot;
18756
18757 DUK_ASSERT(ctx != NULL);
18758 DUK_ASSERT(prototype_bidx >= 0);
18759
18760 /* check stack first */
18761 if (thr->valstack_top >= thr->valstack_end) {
18763 }
18764
18765 obj = duk_hbufferobject_alloc(thr->heap, hobject_flags_and_class);
18766 if (!obj) {
18769
18770 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
18772
18773 tv_slot = thr->valstack_top;
18774 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18775 DUK_HOBJECT_INCREF(thr, obj);
18776 thr->valstack_top++;
18777
18778 return obj;
18779}
18780
18781/* XXX: There's quite a bit of overlap with buffer creation handling in
18782 * duk_bi_buffer.c. Look for overlap and refactor.
18783 */
18784#define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,isview) \
18785 (((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (isview))
18786
18787#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
18788static const duk_uint32_t duk__bufobj_flags_lookup[] = {
18802};
18803#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
18804/* Only allow Duktape.Buffer when support disabled. */
18805static const duk_uint32_t duk__bufobj_flags_lookup[] = {
18807};
18808#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
18809#undef DUK__PACK_ARGS
18810
18811DUK_EXTERNAL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
18812 duk_hthread *thr;
18813 duk_hbufferobject *h_bufobj;
18814 duk_hbuffer *h_val;
18815 duk_uint32_t tmp;
18816 duk_uint_t classnum;
18817 duk_uint_t protobidx;
18818 duk_uint_t lookupidx;
18819 duk_uint_t uint_offset, uint_length, uint_added;
18820
18822 thr = (duk_hthread *) ctx;
18823 DUK_UNREF(thr);
18824
18825 /* The underlying types for offset/length in duk_hbufferobject is
18826 * duk_uint_t; make sure argument values fit and that offset + length
18827 * does not wrap.
18828 */
18829 uint_offset = (duk_uint_t) byte_offset;
18830 uint_length = (duk_uint_t) byte_length;
18831 if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
18832 if ((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length) {
18833 goto range_error;
18834 }
18835 }
18836 uint_added = uint_offset + uint_length;
18837 if (uint_added < uint_offset) {
18838 goto range_error;
18839 }
18840 DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
18841
18842 DUK_ASSERT_DISABLE(flags >= 0); /* flags is unsigned */
18843 lookupidx = flags & 0x0f; /* 4 low bits */
18844 if (lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t)) {
18845 goto arg_error;
18846 }
18847 tmp = duk__bufobj_flags_lookup[lookupidx];
18848 classnum = tmp >> 24;
18849 protobidx = (tmp >> 16) & 0xff;
18850
18851 h_val = duk_require_hbuffer(ctx, idx_buffer);
18852 DUK_ASSERT(h_val != NULL);
18853
18854 h_bufobj = duk_push_bufferobject_raw(ctx,
18858 protobidx);
18859 DUK_ASSERT(h_bufobj != NULL);
18860
18861 h_bufobj->buf = h_val;
18862 DUK_HBUFFER_INCREF(thr, h_val);
18863 h_bufobj->offset = uint_offset;
18864 h_bufobj->length = uint_length;
18865 h_bufobj->shift = (tmp >> 4) & 0x0f;
18866 h_bufobj->elem_type = (tmp >> 8) & 0xff;
18867 h_bufobj->is_view = tmp & 0x0f;
18869
18870#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
18871 /* TypedArray views need an automatic ArrayBuffer which must be
18872 * provided as .buffer property of the view. Just create a new
18873 * ArrayBuffer sharing the same underlying buffer.
18874 */
18875 if (flags & DUK_BUFOBJ_CREATE_ARRBUF) {
18876 h_bufobj = duk_push_bufferobject_raw(ctx,
18881
18882 DUK_ASSERT(h_bufobj != NULL);
18883
18884 h_bufobj->buf = h_val;
18885 DUK_HBUFFER_INCREF(thr, h_val);
18886 h_bufobj->offset = uint_offset;
18887 h_bufobj->length = uint_length;
18888 DUK_ASSERT(h_bufobj->shift == 0);
18890 DUK_ASSERT(h_bufobj->is_view == 0);
18894 duk_compact(ctx, -1);
18895 }
18896#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
18897
18898 return;
18899
18900 range_error:
18902 return; /* not reached */
18903
18904 arg_error:
18906 return; /* not reached */
18907}
18908
18909DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
18910 duk_hthread *thr = (duk_hthread *) ctx;
18911 duk_idx_t ret;
18913#ifdef DUK_USE_AUGMENT_ERROR_CREATE
18914 duk_bool_t noblame_fileline;
18915#endif
18916
18918 DUK_ASSERT(thr != NULL);
18919 DUK_UNREF(filename);
18920 DUK_UNREF(line);
18921
18922 /* Error code also packs a tracedata related flag. */
18923#ifdef DUK_USE_AUGMENT_ERROR_CREATE
18924 noblame_fileline = err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE;
18925#endif
18926 err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
18927
18928 /* error gets its 'name' from the prototype */
18929 proto = duk_error_prototype_from_code(thr, err_code);
18933 proto);
18934
18935 /* ... and its 'message' from an instance property */
18936 if (fmt) {
18937 duk_push_vsprintf(ctx, fmt, ap);
18939 } else {
18940 /* If no explicit message given, put error code into message field
18941 * (as a number). This is not fully in keeping with the Ecmascript
18942 * error model because messages are supposed to be strings (Error
18943 * constructors use ToString() on their argument). However, it's
18944 * probably more useful than having a separate 'code' property.
18945 */
18946 duk_push_int(ctx, err_code);
18948 }
18949
18950 /* XXX: .code = err_code disabled, not sure if useful */
18951
18952 /* Creation time error augmentation */
18953#ifdef DUK_USE_AUGMENT_ERROR_CREATE
18954 /* filename may be NULL in which case file/line is not recorded */
18955 duk_err_augment_error_create(thr, thr, filename, line, noblame_fileline); /* may throw an error */
18956#endif
18958 return ret;
18959}
18960
18961DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
18962 va_list ap;
18963 duk_idx_t ret;
18964
18966
18967 va_start(ap, fmt);
18968 ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
18969 va_end(ap);
18970 return ret;
18971}
18972
18973#if !defined(DUK_USE_VARIADIC_MACROS)
18975 const char *filename = duk_api_global_filename;
18977 va_list ap;
18978 duk_idx_t ret;
18979
18981
18984 va_start(ap, fmt);
18985 ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
18986 va_end(ap);
18987 return ret;
18988}
18989#endif /* DUK_USE_VARIADIC_MACROS */
18990
18992 duk_hthread *thr = (duk_hthread *) ctx;
18993 duk_tval *tv_slot;
18994 duk_hbuffer *h;
18995 void *buf_data;
18996
18998
18999 /* check stack first */
19000 if (thr->valstack_top >= thr->valstack_end) {
19002 }
19003
19004 /* Check for maximum buffer length. */
19007 }
19008
19009 h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
19010 if (!h) {
19012 }
19013
19014 tv_slot = thr->valstack_top;
19015 DUK_TVAL_SET_BUFFER(tv_slot, h);
19016 DUK_HBUFFER_INCREF(thr, h);
19017 thr->valstack_top++;
19018
19019 return (void *) buf_data;
19020}
19021
19023 duk_hthread *thr = (duk_hthread *) ctx;
19024 duk_idx_t ret;
19025
19027
19028 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
19029
19030 if (ptr == NULL) {
19031 goto push_undefined;
19032 }
19033
19034 switch ((int) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
19035 case DUK_HTYPE_STRING:
19036 duk_push_hstring(ctx, (duk_hstring *) ptr);
19037 break;
19038 case DUK_HTYPE_OBJECT:
19039 duk_push_hobject(ctx, (duk_hobject *) ptr);
19040 break;
19041 case DUK_HTYPE_BUFFER:
19042 duk_push_hbuffer(ctx, (duk_hbuffer *) ptr);
19043 break;
19044 default:
19045 goto push_undefined;
19046 }
19047 return ret;
19048
19049 push_undefined:
19050 duk_push_undefined(ctx);
19051 return ret;
19058 -1); /* no prototype */
19060
19062 duk_tval tv;
19064 DUK_ASSERT(h != NULL);
19065 DUK_TVAL_SET_STRING(&tv, h);
19066 duk_push_tval(ctx, &tv);
19068
19070 duk_hthread *thr = (duk_hthread *) ctx;
19071 DUK_UNREF(thr);
19072 DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
19073 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
19074}
19077 duk_tval tv;
19079 DUK_ASSERT(h != NULL);
19080 DUK_TVAL_SET_OBJECT(&tv, h);
19081 duk_push_tval(ctx, &tv);
19082}
19083
19085 duk_tval tv;
19087 DUK_ASSERT(h != NULL);
19089 duk_push_tval(ctx, &tv);
19090}
19091
19093 duk_hthread *thr = (duk_hthread *) ctx;
19095 DUK_ASSERT(thr != NULL);
19096 DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
19097 DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
19098 duk_push_hobject(ctx, thr->builtins[builtin_idx]);
19099}
19100
19101/*
19102 * Poppers
19103 */
19104
19105DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) {
19106 duk_hthread *thr = (duk_hthread *) ctx;
19107 duk_tval *tv;
19108
19110
19111 if (DUK_UNLIKELY(count < 0)) {
19113 return;
19114 }
19115
19117 if (DUK_UNLIKELY((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count)) {
19119 }
19120
19121 /*
19122 * Must be very careful here, every DECREF may cause reallocation
19123 * of our valstack.
19124 */
19125
19126 /* XXX: inlined DECREF macro would be nice here: no NULL check,
19127 * refzero queueing but no refzero algorithm run (= no pointer
19128 * instability), inline code.
19129 */
19130
19131 /* XXX: optimize loops */
19132
19133#if defined(DUK_USE_REFERENCE_COUNTING)
19134 while (count > 0) {
19135 count--;
19136 tv = --thr->valstack_top; /* tv points to element just below prev top */
19137 DUK_ASSERT(tv >= thr->valstack_bottom);
19138 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
19139 }
19140#else
19141 tv = thr->valstack_top;
19142 while (count > 0) {
19143 count--;
19144 tv--;
19145 DUK_ASSERT(tv >= thr->valstack_bottom);
19147 }
19148 thr->valstack_top = tv;
19149#endif
19150
19152}
19153
19154/* Popping one element is called so often that when footprint is not an issue,
19155 * compile a specialized function for it.
19156 */
19157#if defined(DUK_USE_PREFER_SIZE)
19158DUK_EXTERNAL void duk_pop(duk_context *ctx) {
19160 duk_pop_n(ctx, 1);
19161}
19162#else
19163DUK_EXTERNAL void duk_pop(duk_context *ctx) {
19164 duk_hthread *thr = (duk_hthread *) ctx;
19165 duk_tval *tv;
19171 }
19173 tv = --thr->valstack_top; /* tv points to element just below prev top */
19174 DUK_ASSERT(tv >= thr->valstack_bottom);
19175#ifdef DUK_USE_REFERENCE_COUNTING
19176 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
19177#else
19179#endif
19182#endif /* !DUK_USE_PREFER_SIZE */
19183
19186 duk_pop_n(ctx, 2);
19187}
19188
19191 duk_pop_n(ctx, 3);
19192}
19193
19194/*
19195 * Error throwing
19196 */
19197
19199 duk_hthread *thr = (duk_hthread *) ctx;
19200
19201 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
19203 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
19204
19205 if (thr->valstack_top == thr->valstack_bottom) {
19207 }
19208
19209 /* Errors are augmented when they are created, not when they are
19210 * thrown or re-thrown. The current error handler, however, runs
19211 * just before an error is thrown.
19212 */
19213
19214 /* Sync so that augmentation sees up-to-date activations, NULL
19215 * thr->ptr_curr_pc so that it's not used if side effects occur
19216 * in augmentation or longjmp handling.
19217 */
19219
19220#if defined(DUK_USE_AUGMENT_ERROR_THROW)
19221 DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
19223#endif
19224 DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
19225
19227
19228 /* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
19229 * need to check that here. If the value is NULL, a panic occurs because
19230 * we can't return.
19231 */
19232
19233 duk_err_longjmp(thr);
19235}
19236
19237DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg) {
19238 duk_hthread *thr = (duk_hthread *) ctx;
19239
19241 DUK_ASSERT(thr != NULL);
19242 DUK_ASSERT(thr->heap != NULL);
19243 DUK_ASSERT(thr->heap->fatal_func != NULL);
19244
19245 DUK_D(DUK_DPRINT("fatal error occurred, code %ld, message %s",
19246 (long) err_code, (const char *) err_msg));
19248 /* fatal_func should be noreturn, but noreturn declarations on function
19249 * pointers has a very spotty support apparently so it's not currently
19250 * done.
19251 */
19252 thr->heap->fatal_func(ctx, err_code, err_msg);
19253
19254 DUK_PANIC(DUK_ERR_API_ERROR, "fatal handler returned");
19255}
19256
19257DUK_EXTERNAL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
19260 duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19261 duk_throw(ctx);
19262}
19263
19264DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
19265 va_list ap;
19266
19268
19269 va_start(ap, fmt);
19270 duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19271 va_end(ap);
19272 duk_throw(ctx);
19273}
19274
19275#if !defined(DUK_USE_VARIADIC_MACROS)
19276DUK_EXTERNAL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
19277 const char *filename;
19278 duk_int_t line;
19279 va_list ap;
19280
19283 filename = duk_api_global_filename;
19284 line = duk_api_global_line;
19287
19288 va_start(ap, fmt);
19289 duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19290 va_end(ap);
19291 duk_throw(ctx);
19292}
19293#endif /* DUK_USE_VARIADIC_MACROS */
19294
19295/*
19296 * Comparison
19297 */
19298
19300 duk_hthread *thr = (duk_hthread *) ctx;
19301 duk_tval *tv1, *tv2;
19302
19304
19305 tv1 = duk_get_tval(ctx, index1);
19306 tv2 = duk_get_tval(ctx, index2);
19307 if ((tv1 == NULL) || (tv2 == NULL)) {
19308 return 0;
19309 }
19310
19311 /* Coercion may be needed, the helper handles that by pushing the
19312 * tagged values to the stack.
19313 */
19314 return duk_js_equals(thr, tv1, tv2);
19315}
19316
19318 duk_tval *tv1, *tv2;
19321
19322 tv1 = duk_get_tval(ctx, index1);
19323 tv2 = duk_get_tval(ctx, index2);
19324 if ((tv1 == NULL) || (tv2 == NULL)) {
19325 return 0;
19326 }
19327
19328 /* No coercions or other side effects, so safe */
19329 return duk_js_strict_equals(tv1, tv2);
19330}
19331
19332/*
19333 * instanceof
19334 */
19335
19337 duk_tval *tv1, *tv2;
19338
19340
19341 /* Index validation is strict, which differs from duk_equals().
19342 * The strict behavior mimics how instanceof itself works, e.g.
19343 * it is a TypeError if rval is not a -callable- object. It would
19344 * be somewhat inconsistent if rval would be allowed to be
19345 * non-existent without a TypeError.
19346 */
19347 tv1 = duk_require_tval(ctx, index1);
19348 DUK_ASSERT(tv1 != NULL);
19349 tv2 = duk_require_tval(ctx, index2);
19350 DUK_ASSERT(tv2 != NULL);
19351
19352 return duk_js_instanceof((duk_hthread *) ctx, tv1, tv2);
19353}
19354
19355/*
19356 * Lightfunc
19357 */
19358
19360 duk_c_function func;
19361
19363
19364 /* Lightfunc name, includes Duktape/C native function pointer, which
19365 * can often be used to locate the function from a symbol table.
19366 * The name also includes the 16-bit duk_tval flags field because it
19367 * includes the magic value. Because a single native function often
19368 * provides different functionality depending on the magic value, it
19369 * seems reasonably to include it in the name.
19370 *
19371 * On the other hand, a complicated name increases string table
19372 * pressure in low memory environments (but only when function name
19373 * is accessed).
19374 */
19375
19377 duk_push_sprintf(ctx, "light_");
19378 duk_push_string_funcptr(ctx, (duk_uint8_t *) &func, sizeof(func));
19379 duk_push_sprintf(ctx, "_%04x", (unsigned int) DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv));
19380 duk_concat(ctx, 3);
19381}
19385
19386 duk_push_string(ctx, "function ");
19387 duk_push_lightfunc_name(ctx, tv);
19388 duk_push_string(ctx, "() {\"light\"}");
19389 duk_concat(ctx, 3);
19390}
19391
19392/*
19393 * Function pointers
19394 *
19395 * Printing function pointers is non-portable, so we do that by hex printing
19396 * bytes from memory.
19397 */
19398
19399DUK_INTERNAL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz) {
19400 duk_uint8_t buf[32 * 2];
19401 duk_uint8_t *p, *q;
19404
19405 DUK_ASSERT(sz <= 32); /* sanity limit for function pointer size */
19406
19407 p = buf;
19408#if defined(DUK_USE_INTEGER_LE)
19409 q = ptr + sz;
19410#else
19411 q = ptr;
19412#endif
19413 for (i = 0; i < sz; i++) {
19414#if defined(DUK_USE_INTEGER_LE)
19415 t = *(--q);
19416#else
19417 t = *(q++);
19418#endif
19419 *p++ = duk_lc_digits[t >> 4];
19420 *p++ = duk_lc_digits[t & 0x0f];
19421 }
19422
19423 duk_push_lstring(ctx, (const char *) buf, sz * 2);
19425
19426#if !defined(DUK_USE_PARANOID_ERRORS)
19427/*
19428 * Push readable string summarizing duk_tval. The operation is side effect
19429 * free and will only throw from internal errors (e.g. out of memory).
19430 * This is used by e.g. property access code to summarize a key/base safely,
19431 * and is not intended to be fast (but small and safe).
19432 */
19433
19434#define DUK__READABLE_STRING_MAXCHARS 32
19435
19436/* String sanitizer which escapes ASCII control characters and a few other
19437 * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
19438 * question marks. No errors are thrown for any input string, except in out
19439 * of memory situations.
19440 */
19442 duk_hthread *thr;
19443 const duk_uint8_t *p, *p_start, *p_end;
19445 2 /*quotes*/ + 3 /*periods*/];
19446 duk_uint8_t *q;
19448 duk_small_uint_t nchars;
19449
19451 DUK_ASSERT(h_input != NULL);
19452 thr = (duk_hthread *) ctx;
19453
19454 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19455 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19456 p = p_start;
19457 q = buf;
19458
19459 nchars = 0;
19460 *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
19461 for (;;) {
19462 if (p >= p_end) {
19463 break;
19464 }
19465 if (nchars == DUK__READABLE_STRING_MAXCHARS) {
19466 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19467 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19468 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19469 break;
19470 }
19471 if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
19472 if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
19473 DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4); /* estimate is valid */
19474 DUK_ASSERT((cp >> 4) <= 0x0f);
19475 *q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
19476 *q++ = (duk_uint8_t) DUK_ASC_LC_X;
19477 *q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
19478 *q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
19479 } else {
19480 q += duk_unicode_encode_xutf8(cp, q);
19481 }
19482 } else {
19483 p++; /* advance manually */
19484 *q++ = (duk_uint8_t) DUK_ASC_QUESTION;
19485 }
19486 nchars++;
19487 }
19488 *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
19489
19490 duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (q - buf));
19491}
19492
19494 duk_hthread *thr;
19495
19497 thr = (duk_hthread *) ctx;
19498 DUK_UNREF(thr);
19499
19500 if (tv == NULL) {
19501 duk_push_string(ctx, "none");
19502 } else {
19503 switch (DUK_TVAL_GET_TAG(tv)) {
19504 case DUK_TAG_STRING: {
19506 break;
19507 }
19508 case DUK_TAG_OBJECT: {
19510 DUK_ASSERT(h != NULL);
19512 break;
19513 }
19514 case DUK_TAG_BUFFER: {
19515 /* XXX: Hex encoded, length limited buffer summary here? */
19517 DUK_ASSERT(h != NULL);
19518 duk_push_sprintf(ctx, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
19519 break;
19520 }
19521 case DUK_TAG_POINTER: {
19522 /* Surround with parentheses like in JX, ensures NULL pointer
19523 * is distinguishable from null value ("(null)" vs "null").
19524 */
19525 duk_push_tval(ctx, tv);
19526 duk_push_sprintf(ctx, "(%s)", duk_to_string(ctx, -1));
19527 duk_remove(ctx, -2);
19528 break;
19529 }
19530 default: {
19531 duk_push_tval(ctx, tv);
19532 break;
19533 }
19534 }
19535 }
19536
19537 return duk_to_string(ctx, -1);
19539
19543}
19544#endif /* !DUK_USE_PARANOID_ERRORS */
19545
19546#undef DUK__CHECK_SPACE
19547#undef DUK__PACK_ARGS
19548#undef DUK__READABLE_STRING_MAXCHARS
19549/*
19550 * String manipulation
19551 */
19552
19553/* include removed: duk_internal.h */
19554
19556 duk_hthread *thr = (duk_hthread *) ctx;
19557 duk_uint_t count;
19558 duk_uint_t i;
19559 duk_size_t idx;
19560 duk_size_t len;
19561 duk_hstring *h;
19562 duk_uint8_t *buf;
19563
19565
19566 if (DUK_UNLIKELY(count_in <= 0)) {
19567 if (count_in < 0) {
19569 return;
19570 }
19571 DUK_ASSERT(count_in == 0);
19573 return;
19574 }
19575 count = (duk_uint_t) count_in;
19576
19577 if (is_join) {
19578 duk_size_t t1, t2, limit;
19579 h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1);
19580 DUK_ASSERT(h != NULL);
19581
19582 /* A bit tricky overflow test, see doc/code-issues.rst. */
19584 t2 = (duk_size_t) (count - 1);
19586 if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
19587 /* Combined size of separators already overflows */
19588 goto error_overflow;
19589 }
19590 len = (duk_size_t) (t1 * t2);
19591 } else {
19592 len = (duk_size_t) 0;
19593 }
19594
19595 for (i = count; i >= 1; i--) {
19596 duk_size_t new_len;
19597 duk_to_string(ctx, -((duk_idx_t) i));
19598 h = duk_require_hstring(ctx, -((duk_idx_t) i));
19599 new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
19600
19601 /* Impose a string maximum length, need to handle overflow
19602 * correctly.
19603 */
19604 if (new_len < len || /* wrapped */
19605 new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
19606 goto error_overflow;
19607 }
19608 len = new_len;
19609 }
19610
19611 DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
19612 (unsigned long) count, (unsigned long) len));
19613
19614 /* use stack allocated buffer to ensure reachability in errors (e.g. intern error) */
19615 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len);
19616 DUK_ASSERT(buf != NULL);
19617
19618 /* [... (sep) str1 str2 ... strN buf] */
19619
19620 idx = 0;
19621 for (i = count; i >= 1; i--) {
19622 if (is_join && i != count) {
19623 h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2); /* extra -1 for buffer */
19625 idx += DUK_HSTRING_GET_BYTELEN(h);
19626 }
19627 h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1); /* extra -1 for buffer */
19629 idx += DUK_HSTRING_GET_BYTELEN(h);
19630 }
19631
19632 DUK_ASSERT(idx == len);
19633
19634 /* [... (sep) str1 str2 ... strN buf] */
19635
19636 /* get rid of the strings early to minimize memory use before intern */
19637
19638 if (is_join) {
19639 duk_replace(ctx, -((duk_idx_t) count) - 2); /* overwrite sep */
19640 duk_pop_n(ctx, count);
19641 } else {
19642 duk_replace(ctx, -((duk_idx_t) count) - 1); /* overwrite str1 */
19643 duk_pop_n(ctx, count-1);
19644 }
19645
19646 /* [... buf] */
19647
19648 (void) duk_to_string(ctx, -1);
19649
19650 /* [... res] */
19651 return;
19652
19653 error_overflow:
19655}
19657DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) {
19659
19660 duk__concat_and_join_helper(ctx, count, 0 /*is_join*/);
19661}
19662
19663DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) {
19665
19666 duk__concat_and_join_helper(ctx, count, 1 /*is_join*/);
19667}
19668
19669/* XXX: could map/decode be unified with duk_unicode_support.c code?
19670 * Case conversion needs also the character surroundings though.
19671 */
19672
19674 duk_hthread *thr = (duk_hthread *) ctx;
19675 duk_hstring *h_input;
19676 const duk_uint8_t *p, *p_start, *p_end;
19677 duk_codepoint_t cp;
19678
19681 h_input = duk_require_hstring(ctx, index);
19682 DUK_ASSERT(h_input != NULL);
19683
19684 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19685 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19686 p = p_start;
19687
19688 for (;;) {
19689 if (p >= p_end) {
19690 break;
19691 }
19692 cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
19693 callback(udata, cp);
19694 }
19695}
19696
19698 duk_hthread *thr = (duk_hthread *) ctx;
19699 duk_hstring *h_input;
19700 duk_bufwriter_ctx bw_alloc;
19702 const duk_uint8_t *p, *p_start, *p_end;
19703 duk_codepoint_t cp;
19704
19706
19708
19709 h_input = duk_require_hstring(ctx, index);
19710 DUK_ASSERT(h_input != NULL);
19711
19712 bw = &bw_alloc;
19713 DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* reasonable output estimate */
19714
19715 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19716 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19717 p = p_start;
19718
19719 for (;;) {
19720 /* XXX: could write output in chunks with fewer ensure calls,
19721 * but relative benefit would be small here.
19722 */
19723
19724 if (p >= p_end) {
19725 break;
19726 }
19727 cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
19728 cp = callback(udata, cp);
19729
19730 DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
19731 }
19732
19733 DUK_BW_COMPACT(thr, bw);
19734 duk_to_string(ctx, -1);
19735 duk_replace(ctx, index);
19736}
19737
19738DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset) {
19739 duk_hthread *thr = (duk_hthread *) ctx;
19740 duk_hstring *h;
19741 duk_hstring *res;
19742 duk_size_t start_byte_offset;
19743 duk_size_t end_byte_offset;
19744
19746
19748 h = duk_require_hstring(ctx, index);
19749 DUK_ASSERT(h != NULL);
19750
19751 if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
19752 end_offset = DUK_HSTRING_GET_CHARLEN(h);
19753 }
19754 if (start_offset > end_offset) {
19755 start_offset = end_offset;
19756 }
19757
19758 DUK_ASSERT_DISABLE(start_offset >= 0);
19759 DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
19760 DUK_ASSERT_DISABLE(end_offset >= 0);
19761 DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
19762
19763 /* guaranteed by string limits */
19764 DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
19765 DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
19766
19767 start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
19768 end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
19769
19770 DUK_ASSERT(end_byte_offset >= start_byte_offset);
19771 DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* guaranteed by string limits */
19772
19773 /* no size check is necessary */
19775 DUK_HSTRING_GET_DATA(h) + start_byte_offset,
19776 (duk_uint32_t) (end_byte_offset - start_byte_offset));
19777
19778 duk_push_hstring(ctx, res);
19779 duk_replace(ctx, index);
19780}
19781
19782/* XXX: this is quite clunky. Add Unicode helpers to scan backwards and
19783 * forwards with a callback to process codepoints?
19784 */
19786 duk_hthread *thr = (duk_hthread *) ctx;
19787 duk_hstring *h;
19788 const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */
19789 const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */
19790 duk_codepoint_t cp;
19791
19793
19795 h = duk_require_hstring(ctx, index);
19796 DUK_ASSERT(h != NULL);
19797
19798 p_start = DUK_HSTRING_GET_DATA(h);
19799 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
19800
19801 p = p_start;
19802 while (p < p_end) {
19803 p_tmp1 = p;
19804 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
19806 break;
19807 }
19808 p = p_tmp1;
19809 }
19810 q_start = p;
19811 if (p == p_end) {
19812 /* entire string is whitespace */
19813 q_end = p;
19814 goto scan_done;
19815 }
19816
19817 p = p_end;
19818 while (p > p_start) {
19819 p_tmp1 = p;
19820 while (p > p_start) {
19821 p--;
19822 if (((*p) & 0xc0) != 0x80) {
19823 break;
19824 }
19825 }
19826 p_tmp2 = p;
19827
19828 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
19830 p = p_tmp1;
19831 break;
19832 }
19833 }
19834 q_end = p;
19835
19836 scan_done:
19837 /* This may happen when forward and backward scanning disagree
19838 * (possible for non-extended-UTF-8 strings).
19839 */
19840 if (q_end < q_start) {
19841 q_end = q_start;
19842 }
19843
19844 DUK_ASSERT(q_start >= p_start && q_start <= p_end);
19845 DUK_ASSERT(q_end >= p_start && q_end <= p_end);
19846 DUK_ASSERT(q_end >= q_start);
19847
19848 DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
19849 (const void *) p_start, (const void *) p_end,
19850 (const void *) q_start, (const void *) q_end));
19851
19852 if (q_start == p_start && q_end == p_end) {
19853 DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
19854 return;
19855 }
19856
19857 duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start));
19858 duk_replace(ctx, index);
19859}
19860
19862 duk_hthread *thr = (duk_hthread *) ctx;
19863 duk_hstring *h;
19865
19867
19868 h = duk_require_hstring(ctx, index);
19870
19871 DUK_ASSERT_DISABLE(char_offset >= 0); /* always true, arg is unsigned */
19872 if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
19873 return 0;
19874 }
19875
19876 DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* guaranteed by string limits */
19877 cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset);
19878 return (duk_codepoint_t) cp;
19879}
19880/*
19881 * Variable access
19882 */
19883
19884/* include removed: duk_internal.h */
19885
19887 duk_hthread *thr = (duk_hthread *) ctx;
19888 duk_activation *act;
19889 duk_hstring *h_varname;
19890 duk_small_int_t throw_flag = 1; /* always throw ReferenceError for unresolvable */
19891
19893
19894 h_varname = duk_require_hstring(ctx, -1); /* XXX: tostring? */
19895 DUK_ASSERT(h_varname != NULL);
19896
19898 if (act) {
19899 (void) duk_js_getvar_activation(thr, act, h_varname, throw_flag); /* -> [ ... varname val this ] */
19900 } else {
19901 /* Outside any activation -> look up from global. */
19903 (void) duk_js_getvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, throw_flag);
19904 }
19905
19906 /* [ ... varname val this ] (because throw_flag == 1, always resolved) */
19907
19908 duk_pop(ctx);
19909 duk_remove(ctx, -2);
19910
19911 /* [ ... val ] */
19912
19913 /* Return value would be pointless: because throw_flag==1, we always
19914 * throw if the identifier doesn't resolve.
19915 */
19916 return;
19917}
19918
19920 duk_hthread *thr = (duk_hthread *) ctx;
19921 duk_activation *act;
19922 duk_hstring *h_varname;
19923 duk_tval *tv_val;
19924 duk_small_int_t throw_flag;
19925
19927
19928 h_varname = duk_require_hstring(ctx, -2); /* XXX: tostring? */
19929 DUK_ASSERT(h_varname != NULL);
19930
19931 tv_val = duk_require_tval(ctx, -1);
19932
19933 throw_flag = duk_is_strict_call(ctx);
19934
19936 if (act) {
19937 duk_js_putvar_activation(thr, act, h_varname, tv_val, throw_flag); /* -> [ ... varname val this ] */
19938 } else {
19939 /* Outside any activation -> put to global. */
19941 duk_js_putvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, tv_val, throw_flag);
19942 }
19944 /* [ ... varname val ] */
19945
19946 duk_pop_2(ctx);
19947
19948 /* [ ... ] */
19949
19950 return;
19951}
19952
19955
19957 return 0;
19958}
19959
19962
19964 return 0;
19965}
19966/*
19967 * Array built-ins
19968 *
19969 * Note that most Array built-ins are intentionally generic and work even
19970 * when the 'this' binding is not an Array instance. To ensure this,
19971 * Array algorithms do not assume "magical" Array behavior for the "length"
19972 * property, for instance.
19973 *
19974 * XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
19975 * [[Delete]] operations, but it's currently false throughout. Go through
19976 * all put/delete cases and check throw flag use. Need a new API primitive
19977 * which allows throws flag to be specified.
19978 *
19979 * XXX: array lengths above 2G won't work reliably. There are many places
19980 * where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
19981 * i.e. -33- bits). Although array 'length' cannot be written to be outside
19982 * the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
19983 * some intermediate values may be above 0xffffffff and this may not be always
19984 * correctly handled now (duk_uint32_t is not enough for all algorithms).
19985 *
19986 * For instance, push() can legitimately write entries beyond length 0xffffffff
19987 * and cause a RangeError only at the end. To do this properly, the current
19988 * push() implementation tracks the array index using a 'double' instead of a
19989 * duk_uint32_t (which is somewhat awkward). See test-bi-array-push-maxlen.js.
19990 *
19991 * On using "put" vs. "def" prop
19992 * =============================
19993 *
19994 * Code below must be careful to use the appropriate primitive as it matters
19995 * for compliance. When using "put" there may be inherited properties in
19996 * Array.prototype which cause side effects when values are written. When
19997 * using "define" there are no such side effects, and many test262 test cases
19998 * check for this (for real world code, such side effects are very rare).
19999 * Both "put" and "define" are used in the E5.1 specification; as a rule,
20000 * "put" is used when modifying an existing array (or a non-array 'this'
20001 * binding) and "define" for setting values into a fresh result array.
20003 * Also note that Array instance 'length' should be writable, but not
20004 * enumerable and definitely not configurable: even Duktape code internally
20005 * assumes that an Array instance will always have a 'length' property.
20006 * Preventing deletion of the property is critical.
20007 */
20008
20009/* include removed: duk_internal.h */
20010
20011/* Perform an intermediate join when this many elements have been pushed
20012 * on the value stack.
20014#define DUK__ARRAY_MID_JOIN_LIMIT 4096
20015
20016/* Shared entry code for many Array built-ins. Note that length is left
20017 * on stack (it could be popped, but that's not necessary).
20018 */
20020 duk_uint32_t len;
20021
20024 len = duk_to_uint32(ctx, -1);
20025
20026 /* -> [ ... ToObject(this) ToUint32(length) ] */
20027 return len;
20028}
20031 /* Range limited to [0, 0x7fffffff] range, i.e. range that can be
20032 * represented with duk_int32_t. Use this when the method doesn't
20033 * handle the full 32-bit unsigned range correctly.
20034 */
20035 duk_uint32_t ret = duk__push_this_obj_len_u32(ctx);
20036 if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
20038 }
20039 return ret;
20040}
20041
20042/*
20043 * Constructor
20044 */
20045
20047 duk_idx_t nargs;
20048 duk_double_t d;
20049 duk_uint32_t len;
20050 duk_idx_t i;
20051
20052 nargs = duk_get_top(ctx);
20053 duk_push_array(ctx);
20054
20055 if (nargs == 1 && duk_is_number(ctx, 0)) {
20056 /* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
20057 d = duk_get_number(ctx, 0);
20058 len = duk_to_uint32(ctx, 0);
20059 if (((duk_double_t) len) != d) {
20060 return DUK_RET_RANGE_ERROR;
20061 }
20062
20063 /* XXX: if 'len' is low, may want to ensure array part is kept:
20064 * the caller is likely to want a dense array.
20065 */
20066 duk_push_u32(ctx, len);
20067 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); /* [ ToUint32(len) array ToUint32(len) ] -> [ ToUint32(len) array ] */
20068 return 1;
20069 }
20070
20071 /* XXX: optimize by creating array into correct size directly, and
20072 * operating on the array part directly; values can be memcpy()'d from
20073 * value stack directly as long as refcounts are increased.
20074 */
20075 for (i = 0; i < nargs; i++) {
20076 duk_dup(ctx, i);
20078 }
20079
20080 duk_push_u32(ctx, (duk_uint32_t) nargs);
20082 return 1;
20083}
20085/*
20086 * isArray()
20087 */
20088
20090 duk_hobject *h;
20091
20093 duk_push_boolean(ctx, (h != NULL));
20094 return 1;
20095}
20096
20097/*
20098 * toString()
20099 */
20100
20104
20105 /* [ ... this func ] */
20106 if (!duk_is_callable(ctx, -1)) {
20107 /* Fall back to the initial (original) Object.toString(). We don't
20108 * currently have pointers to the built-in functions, only the top
20109 * level global objects (like "Array") so this is now done in a bit
20110 * of a hacky manner. It would be cleaner to push the (original)
20111 * function and use duk_call_method().
20112 */
20113
20114 /* XXX: 'this' will be ToObject() coerced twice, which is incorrect
20115 * but should have no visible side effects.
20116 */
20117 DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
20118 duk_set_top(ctx, 0);
20119 return duk_bi_object_prototype_to_string(ctx); /* has access to 'this' binding */
20120 }
20121
20122 /* [ ... this func ] */
20124 duk_insert(ctx, -2);
20125
20126 /* [ ... func this ] */
20127
20128 DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
20129 (duk_tval *) duk_get_tval(ctx, -2),
20130 (duk_tval *) duk_get_tval(ctx, -1)));
20131 duk_call_method(ctx, 0);
20132
20133 return 1;
20134}
20135
20136/*
20137 * concat()
20138 */
20139
20141 duk_idx_t i, n;
20142 duk_uarridx_t idx, idx_last;
20143 duk_uarridx_t j, len;
20144 duk_hobject *h;
20145
20146 /* XXX: the insert here is a bit expensive if there are a lot of items.
20147 * It could also be special cased in the outermost for loop quite easily
20148 * (as the element is dup()'d anyway).
20149 */
20150
20152 duk_insert(ctx, 0);
20153 n = duk_get_top(ctx);
20154 duk_push_array(ctx); /* -> [ ToObject(this) item1 ... itemN arr ] */
20155
20156 /* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
20157 * (which differs from the official algorithm). If no error is thrown, this
20158 * doesn't matter as the length is updated at the end. However, if an error
20159 * is thrown, the length will be unset. That shouldn't matter because the
20160 * caller won't get a reference to the intermediate value.
20161 */
20162
20163 idx = 0;
20164 idx_last = 0;
20165 for (i = 0; i < n; i++) {
20166 DUK_ASSERT_TOP(ctx, n + 1);
20167
20168 /* [ ToObject(this) item1 ... itemN arr ] */
20169
20170 duk_dup(ctx, i);
20172 if (!h) {
20173 duk_xdef_prop_index_wec(ctx, -2, idx++);
20174 idx_last = idx;
20175 continue;
20176 }
20177
20178 /* [ ToObject(this) item1 ... itemN arr item(i) ] */
20179
20180 /* XXX: an array can have length higher than 32 bits; this is not handled
20181 * correctly now.
20182 */
20183 len = (duk_uarridx_t) duk_get_length(ctx, -1);
20184 for (j = 0; j < len; j++) {
20185 if (duk_get_prop_index(ctx, -1, j)) {
20186 /* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
20187 duk_xdef_prop_index_wec(ctx, -3, idx++);
20188 idx_last = idx;
20189 } else {
20190 idx++;
20191 duk_pop(ctx);
20192#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)
20193 /* According to E5.1 Section 15.4.4.4 nonexistent trailing
20194 * elements do not affect 'length' of the result. Test262
20195 * and other engines disagree, so update idx_last here too.
20196 */
20197 idx_last = idx;
20198#else
20199 /* Strict standard behavior, ignore trailing elements for
20200 * result 'length'.
20201 */
20202#endif
20203 }
20204 }
20205 duk_pop(ctx);
20206 }
20207
20208 /* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly
20209 * in the end, but because we're operating with an internal value which
20210 * is known to be an array, this should be equivalent.
20211 */
20212 duk_push_uarridx(ctx, idx_last);
20214
20215 DUK_ASSERT_TOP(ctx, n + 1);
20216 return 1;
20217}
20218
20219/*
20220 * join(), toLocaleString()
20221 *
20222 * Note: checking valstack is necessary, but only in the per-element loop.
20223 *
20224 * Note: the trivial approach of pushing all the elements on the value stack
20225 * and then calling duk_join() fails when the array contains a large number
20226 * of elements. This problem can't be offloaded to duk_join() because the
20227 * elements to join must be handled here and have special handling. Current
20228 * approach is to do intermediate joins with very large number of elements.
20229 * There is no fancy handling; the prefix gets re-joined multiple times.
20230 */
20231
20233 duk_uint32_t len, count;
20234 duk_uint32_t idx;
20235 duk_small_int_t to_locale_string = duk_get_current_magic(ctx);
20236 duk_idx_t valstack_required;
20237
20238 /* For join(), nargs is 1. For toLocaleString(), nargs is 0 and
20239 * setting the top essentially pushes an undefined to the stack,
20240 * thus defaulting to a comma separator.
20241 */
20242 duk_set_top(ctx, 1);
20243 if (duk_is_undefined(ctx, 0)) {
20244 duk_pop(ctx);
20246 } else {
20247 duk_to_string(ctx, 0);
20248 }
20249
20250 len = duk__push_this_obj_len_u32(ctx);
20251
20252 /* [ sep ToObject(this) len ] */
20253
20254 DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
20255 (duk_tval *) duk_get_tval(ctx, 0),
20256 (duk_tval *) duk_get_tval(ctx, 1),
20257 (unsigned long) len));
20258
20259 /* The extra (+4) is tight. */
20260 valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ?
20261 DUK__ARRAY_MID_JOIN_LIMIT : len) + 4;
20262 duk_require_stack(ctx, valstack_required);
20263
20264 duk_dup(ctx, 0);
20265
20266 /* [ sep ToObject(this) len sep ] */
20267
20268 count = 0;
20269 idx = 0;
20270 for (;;) {
20271 if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */
20272 idx >= len) { /* end of loop (careful with len==0) */
20273 /* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
20274 DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
20275 (long) count, (long) idx, (long) len));
20276 duk_join(ctx, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */
20277 duk_dup(ctx, 0); /* -> [ sep ToObject(this) len str sep ] */
20278 duk_insert(ctx, -2); /* -> [ sep ToObject(this) len sep str ] */
20279 count = 1;
20280 }
20281 if (idx >= len) {
20282 /* if true, the stack already contains the final result */
20283 break;
20284 }
20285
20286 duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx);
20287 if (duk_is_null_or_undefined(ctx, -1)) {
20288 duk_pop(ctx);
20290 } else {
20291 if (to_locale_string) {
20292 duk_to_object(ctx, -1);
20294 duk_insert(ctx, -2); /* -> [ ... toLocaleString ToObject(val) ] */
20295 duk_call_method(ctx, 0);
20296 duk_to_string(ctx, -1);
20297 } else {
20299 }
20300 }
20301
20302 count++;
20303 idx++;
20304 }
20305
20306 /* [ sep ToObject(this) len sep result ] */
20307
20308 return 1;
20309}
20310
20311/*
20312 * pop(), push()
20313 */
20314
20316 duk_uint32_t len;
20317 duk_uint32_t idx;
20319 DUK_ASSERT_TOP(ctx, 0);
20320 len = duk__push_this_obj_len_u32(ctx);
20321 if (len == 0) {
20322 duk_push_int(ctx, 0);
20324 return 0;
20325 }
20326 idx = len - 1;
20327
20328 duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx);
20329 duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx);
20330 duk_push_u32(ctx, idx);
20332 return 1;
20333}
20334
20336 /* Note: 'this' is not necessarily an Array object. The push()
20337 * algorithm is supposed to work for other kinds of objects too,
20338 * so the algorithm has e.g. an explicit update for the 'length'
20339 * property which is normally "magical" in arrays.
20340 */
20341
20342 duk_uint32_t len;
20343 duk_idx_t i, n;
20344
20345 n = duk_get_top(ctx);
20346 len = duk__push_this_obj_len_u32(ctx);
20347
20348 /* [ arg1 ... argN obj length ] */
20349
20350 /* Technically Array.prototype.push() can create an Array with length
20351 * longer than 2^32-1, i.e. outside the 32-bit range. The final length
20352 * is *not* wrapped to 32 bits in the specification.
20353 *
20354 * This implementation tracks length with a uint32 because it's much
20355 * more practical.
20356 *
20357 * See: test-bi-array-push-maxlen.js.
20358 */
20359
20360 if (len + (duk_uint32_t) n < len) {
20361 DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
20362 return DUK_RET_RANGE_ERROR;
20363 }
20364
20365 for (i = 0; i < n; i++) {
20366 duk_dup(ctx, i);
20367 duk_put_prop_index(ctx, -3, len + i);
20368 }
20369 len += n;
20370
20371 duk_push_u32(ctx, len);
20374
20375 /* [ arg1 ... argN obj length new_length ] */
20376 return 1;
20377}
20378
20379/*
20380 * sort()
20381 *
20382 * Currently qsort with random pivot. This is now really, really slow,
20383 * because there is no fast path for array parts.
20384 *
20385 * Signed indices are used because qsort() leaves and degenerate cases
20386 * may use a negative offset.
20387 */
20388
20390 duk_bool_t have1, have2;
20391 duk_bool_t undef1, undef2;
20392 duk_small_int_t ret;
20393 duk_idx_t idx_obj = 1; /* fixed offsets in valstack */
20394 duk_idx_t idx_fn = 0;
20395 duk_hstring *h1, *h2;
20396
20397 /* Fast exit if indices are identical. This is valid for a non-existent property,
20398 * for an undefined value, and almost always for ToString() coerced comparison of
20399 * arbitrary values (corner cases where this is not the case include e.g. a an
20400 * object with varying ToString() coercion).
20401 *
20402 * The specification does not prohibit "caching" of values read from the array, so
20403 * assuming equality for comparing an index with itself falls into the category of
20404 * "caching".
20405 *
20406 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
20407 * have an effect on the final result. The specification does not require any
20408 * specific behavior for inconsistent compare functions, so again, this fast path
20409 * is OK.
20410 */
20411
20412 if (idx1 == idx2) {
20413 DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
20414 (long) idx1, (long) idx2));
20415 return 0;
20416 }
20417
20418 have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1);
20419 have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2);
20420
20421 DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
20422 (long) idx1, (long) idx2, (long) have1, (long) have2,
20423 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
20424
20425 if (have1) {
20426 if (have2) {
20427 ;
20428 } else {
20429 ret = -1;
20430 goto pop_ret;
20431 }
20432 } else {
20433 if (have2) {
20434 ret = 1;
20435 goto pop_ret;
20436 } else {
20437 ret = 0;
20438 goto pop_ret;
20439 }
20440 }
20441
20442 undef1 = duk_is_undefined(ctx, -2);
20443 undef2 = duk_is_undefined(ctx, -1);
20444 if (undef1) {
20445 if (undef2) {
20446 ret = 0;
20447 goto pop_ret;
20448 } else {
20449 ret = 1;
20450 goto pop_ret;
20451 }
20452 } else {
20453 if (undef2) {
20454 ret = -1;
20455 goto pop_ret;
20456 } else {
20457 ;
20458 }
20459 }
20460
20461 if (!duk_is_undefined(ctx, idx_fn)) {
20462 duk_double_t d;
20463
20464 /* no need to check callable; duk_call() will do that */
20465 duk_dup(ctx, idx_fn); /* -> [ ... x y fn ] */
20466 duk_insert(ctx, -3); /* -> [ ... fn x y ] */
20467 duk_call(ctx, 2); /* -> [ ... res ] */
20468
20469 /* The specification is a bit vague what to do if the return
20470 * value is not a number. Other implementations seem to
20471 * tolerate non-numbers but e.g. V8 won't apparently do a
20472 * ToNumber().
20473 */
20474
20475 /* XXX: best behavior for real world compatibility? */
20476
20477 d = duk_to_number(ctx, -1);
20478 if (d < 0.0) {
20479 ret = -1;
20480 } else if (d > 0.0) {
20481 ret = 1;
20482 } else {
20483 ret = 0;
20484 }
20485
20486 duk_pop(ctx);
20487 DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
20488 return ret;
20489 }
20491 /* string compare is the default (a bit oddly) */
20492
20493 h1 = duk_to_hstring(ctx, -2);
20494 h2 = duk_to_hstring(ctx, -1);
20495 DUK_ASSERT(h1 != NULL);
20496 DUK_ASSERT(h2 != NULL);
20497
20498 ret = duk_js_string_compare(h1, h2); /* retval is directly usable */
20499 goto pop_ret;
20500
20501 pop_ret:
20502 duk_pop_2(ctx);
20503 DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
20504 return ret;
20505}
20506
20508 duk_bool_t have_l, have_r;
20509 duk_idx_t idx_obj = 1; /* fixed offset in valstack */
20510
20511 if (l == r) {
20512 return;
20513 }
20514
20515 /* swap elements; deal with non-existent elements correctly */
20516 have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20517 have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20518
20519 if (have_r) {
20520 /* right exists, [[Put]] regardless whether or not left exists */
20521 duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20522 } else {
20523 duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20524 duk_pop(ctx);
20525 }
20526
20527 if (have_l) {
20528 duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20529 } else {
20530 duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20531 duk_pop(ctx);
20532 }
20533}
20534
20535#if defined(DUK_USE_DDDPRINT)
20536/* Debug print which visualizes the qsort partitioning process. */
20537DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
20538 char buf[4096];
20539 char *ptr = buf;
20540 duk_int_t i, n;
20541 n = (duk_int_t) duk_get_length(ctx, 1);
20542 if (n > 4000) {
20543 n = 4000;
20544 }
20545 *ptr++ = '[';
20546 for (i = 0; i < n; i++) {
20547 if (i == pivot) {
20548 *ptr++ = '|';
20549 } else if (i == lo) {
20550 *ptr++ = '<';
20551 } else if (i == hi) {
20552 *ptr++ = '>';
20553 } else if (i >= lo && i <= hi) {
20554 *ptr++ = '-';
20555 } else {
20556 *ptr++ = ' ';
20557 }
20558 }
20559 *ptr++ = ']';
20560 *ptr++ = '\0';
20561
20562 DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)",
20563 (const char *) buf, (long) lo, (long) hi, (long) pivot));
20564}
20565#endif
20566
20568 duk_hthread *thr = (duk_hthread *) ctx;
20569 duk_int_t p, l, r;
20570
20571 /* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
20572
20573 DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
20574 (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1)));
20575
20576 DUK_ASSERT_TOP(ctx, 3);
20577
20578 /* In some cases it may be that lo > hi, or hi < 0; these
20579 * degenerate cases happen e.g. for empty arrays, and in
20580 * recursion leaves.
20581 */
20582
20583 /* trivial cases */
20584 if (hi - lo < 1) {
20585 DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
20586 return;
20587 }
20588 DUK_ASSERT(hi > lo);
20589 DUK_ASSERT(hi - lo + 1 >= 2);
20590
20591 /* randomized pivot selection */
20592 p = lo + (duk_util_tinyrandom_get_bits(thr, 30) % (hi - lo + 1)); /* rnd in [lo,hi] */
20593 DUK_ASSERT(p >= lo && p <= hi);
20594 DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld",
20595 (long) lo, (long) hi, (long) p));
20596
20597 /* move pivot out of the way */
20598 duk__array_sort_swap(ctx, p, lo);
20599 p = lo;
20600 DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20601
20602 l = lo + 1;
20603 r = hi;
20604 for (;;) {
20605 /* find elements to swap */
20606 for (;;) {
20607 DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
20608 (long) l, (long) r, (long) p));
20609 if (l >= hi) {
20610 break;
20611 }
20612 if (duk__array_sort_compare(ctx, l, p) >= 0) { /* !(l < p) */
20613 break;
20614 }
20615 l++;
20616 }
20617 for (;;) {
20618 DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
20619 (long) l, (long) r, (long) p));
20620 if (r <= lo) {
20621 break;
20622 }
20623 if (duk__array_sort_compare(ctx, p, r) >= 0) { /* !(p < r) */
20624 break;
20625 }
20626 r--;
20627 }
20628 if (l >= r) {
20629 goto done;
20630 }
20631 DUK_ASSERT(l < r);
20632
20633 DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
20634
20635 duk__array_sort_swap(ctx, l, r);
20636
20637 DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20638 l++;
20639 r--;
20640 }
20641 done:
20642 /* Note that 'l' and 'r' may cross, i.e. r < l */
20643 DUK_ASSERT(l >= lo && l <= hi);
20644 DUK_ASSERT(r >= lo && r <= hi);
20645
20646 /* XXX: there's no explicit recursion bound here now. For the average
20647 * qsort recursion depth O(log n) that's not really necessary: e.g. for
20648 * 2**32 recursion depth would be about 32 which is OK. However, qsort
20649 * worst case recursion depth is O(n) which may be a problem.
20650 */
20651
20652 /* move pivot to its final place */
20653 DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20654 duk__array_sort_swap(ctx, lo, r);
20655
20656#if defined(DUK_USE_DDDPRINT)
20657 duk__debuglog_qsort_state(ctx, lo, hi, r);
20658#endif
20659
20660 DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1)));
20661 duk__array_qsort(ctx, lo, r - 1);
20662 duk__array_qsort(ctx, r + 1, hi);
20663}
20664
20666 duk_uint32_t len;
20667
20668 /* XXX: len >= 0x80000000 won't work below because a signed type
20669 * is needed by qsort.
20670 */
20672
20673 /* stack[0] = compareFn
20674 * stack[1] = ToObject(this)
20675 * stack[2] = ToUint32(length)
20676 */
20677
20678 if (len > 0) {
20679 /* avoid degenerate cases, so that (len - 1) won't underflow */
20680 duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1));
20681 }
20682
20683 DUK_ASSERT_TOP(ctx, 3);
20685 return 1; /* return ToObject(this) */
20686}
20687
20688/*
20689 * splice()
20690 */
20691
20692/* XXX: this compiles to over 500 bytes now, even without special handling
20693 * for an array part. Uses signed ints so does not handle full array range correctly.
20694 */
20695
20696/* XXX: can shift() / unshift() use the same helper?
20697 * shift() is (close to?) <--> splice(0, 1)
20698 * unshift is (close to?) <--> splice(0, 0, [items])?
20699 */
20700
20702 duk_idx_t nargs;
20703 duk_uint32_t len;
20704 duk_bool_t have_delcount;
20705 duk_int_t item_count;
20706 duk_int_t act_start;
20707 duk_int_t del_count;
20708 duk_int_t i, n;
20709
20710 DUK_UNREF(have_delcount);
20711
20712 nargs = duk_get_top(ctx);
20713 if (nargs < 2) {
20714 duk_set_top(ctx, 2);
20715 nargs = 2;
20716 have_delcount = 0;
20717 } else {
20718 have_delcount = 1;
20719 }
20720
20721 /* XXX: len >= 0x80000000 won't work below because we need to be
20722 * able to represent -len.
20723 */
20725
20726 act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
20727 if (act_start < 0) {
20728 act_start = len + act_start;
20729 }
20730 DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len);
20731
20732#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
20733 if (have_delcount) {
20734#endif
20735 del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start);
20736#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
20737 } else {
20738 /* E5.1 standard behavior when deleteCount is not given would be
20739 * to treat it just like if 'undefined' was given, which coerces
20740 * ultimately to 0. Real world behavior is to splice to the end
20741 * of array, see test-bi-array-proto-splice-no-delcount.js.
20742 */
20743 del_count = len - act_start;
20744 }
20745#endif
20746
20747 DUK_ASSERT(nargs >= 2);
20748 item_count = (duk_int_t) (nargs - 2);
20749
20750 DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start);
20751 DUK_ASSERT(del_count + act_start <= (duk_int_t) len);
20752
20753 /* For now, restrict result array into 32-bit length range. */
20754 if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
20755 DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
20756 return DUK_RET_RANGE_ERROR;
20757 }
20758
20759 duk_push_array(ctx);
20760
20761 /* stack[0] = start
20762 * stack[1] = deleteCount
20763 * stack[2...nargs-1] = items
20764 * stack[nargs] = ToObject(this) -3
20765 * stack[nargs+1] = ToUint32(length) -2
20766 * stack[nargs+2] = result array -1
20767 */
20768
20769 DUK_ASSERT_TOP(ctx, nargs + 3);
20770
20771 /* Step 9: copy elements-to-be-deleted into the result array */
20772
20773 for (i = 0; i < del_count; i++) {
20774 if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) {
20775 duk_xdef_prop_index_wec(ctx, -2, i); /* throw flag irrelevant (false in std alg) */
20776 } else {
20777 duk_pop(ctx);
20778 }
20779 }
20780 duk_push_u32(ctx, (duk_uint32_t) del_count);
20782
20783 /* Steps 12 and 13: reorganize elements to make room for itemCount elements */
20784
20785 if (item_count < del_count) {
20786 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 1
20787 * -> [ A B F G H ] (conceptual intermediate step)
20788 * -> [ A B . F G H ] (placeholder marked)
20789 * [ A B C F G H ] (actual result at this point, C will be replaced)
20790 */
20791
20792 DUK_ASSERT_TOP(ctx, nargs + 3);
20793
20794 n = len - del_count;
20795 for (i = act_start; i < n; i++) {
20796 if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
20797 duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
20798 } else {
20799 duk_pop(ctx);
20800 duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
20801 }
20802 }
20803
20804 DUK_ASSERT_TOP(ctx, nargs + 3);
20805
20806 /* loop iterator init and limit changed from standard algorithm */
20807 n = len - del_count + item_count;
20808 for (i = len - 1; i >= n; i--) {
20809 duk_del_prop_index(ctx, -3, (duk_uarridx_t) i);
20810 }
20811
20812 DUK_ASSERT_TOP(ctx, nargs + 3);
20813 } else if (item_count > del_count) {
20814 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 4
20815 * -> [ A B F G H ] (conceptual intermediate step)
20816 * -> [ A B . . . . F G H ] (placeholder marked)
20817 * [ A B C D E F F G H ] (actual result at this point)
20818 */
20819
20820 DUK_ASSERT_TOP(ctx, nargs + 3);
20821
20822 /* loop iterator init and limit changed from standard algorithm */
20823 for (i = len - del_count - 1; i >= act_start; i--) {
20824 if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
20825 duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
20826 } else {
20827 duk_pop(ctx);
20828 duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
20829 }
20830 }
20831
20832 DUK_ASSERT_TOP(ctx, nargs + 3);
20833 } else {
20834 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 3
20835 * -> [ A B F G H ] (conceptual intermediate step)
20836 * -> [ A B . . . F G H ] (placeholder marked)
20837 * [ A B C D E F G H ] (actual result at this point)
20838 */
20839 }
20840 DUK_ASSERT_TOP(ctx, nargs + 3);
20841
20842 /* Step 15: insert itemCount elements into the hole made above */
20843
20844 for (i = 0; i < item_count; i++) {
20845 duk_dup(ctx, i + 2); /* args start at index 2 */
20846 duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i));
20847 }
20849 /* Step 16: update length; note that the final length may be above 32 bit range
20850 * (but we checked above that this isn't the case here)
20851 */
20852
20853 duk_push_u32(ctx, len - del_count + item_count);
20855
20856 /* result array is already at the top of stack */
20857 DUK_ASSERT_TOP(ctx, nargs + 3);
20858 return 1;
20859}
20860
20861/*
20862 * reverse()
20863 */
20864
20866 duk_uint32_t len;
20867 duk_uint32_t middle;
20868 duk_uint32_t lower, upper;
20869 duk_bool_t have_lower, have_upper;
20870
20871 len = duk__push_this_obj_len_u32(ctx);
20872 middle = len / 2;
20873
20874 /* If len <= 1, middle will be 0 and for-loop bails out
20875 * immediately (0 < 0 -> false).
20876 */
20877
20878 for (lower = 0; lower < middle; lower++) {
20879 DUK_ASSERT(len >= 2);
20880 DUK_ASSERT_TOP(ctx, 2);
20881
20882 DUK_ASSERT(len >= lower + 1);
20883 upper = len - lower - 1;
20884
20885 have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower);
20886 have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper);
20887
20888 /* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
20889
20890 if (have_upper) {
20891 duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower);
20892 } else {
20893 duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower);
20894 duk_pop(ctx);
20895 }
20896
20897 if (have_lower) {
20898 duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper);
20899 } else {
20900 duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper);
20901 duk_pop(ctx);
20902 }
20903
20904 DUK_ASSERT_TOP(ctx, 2);
20905 }
20906
20907 DUK_ASSERT_TOP(ctx, 2);
20908 duk_pop(ctx); /* -> [ ToObject(this) ] */
20909 return 1;
20910}
20911
20912/*
20913 * slice()
20914 */
20915
20917 duk_uint32_t len;
20918 duk_int_t start, end;
20919 duk_int_t i;
20920 duk_uarridx_t idx;
20921 duk_uint32_t res_length = 0;
20922
20923 /* XXX: len >= 0x80000000 won't work below because we need to be
20924 * able to represent -len.
20925 */
20927 duk_push_array(ctx);
20928
20929 /* stack[0] = start
20930 * stack[1] = end
20931 * stack[2] = ToObject(this)
20932 * stack[3] = ToUint32(length)
20933 * stack[4] = result array
20934 */
20935
20936 start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
20937 if (start < 0) {
20938 start = len + start;
20939 }
20940 /* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
20941 * (the upper limit)?
20942 */
20943 if (duk_is_undefined(ctx, 1)) {
20944 end = len;
20945 } else {
20946 end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len);
20947 if (end < 0) {
20948 end = len + end;
20949 }
20950 }
20951 DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len);
20952 DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len);
20953
20954 idx = 0;
20955 for (i = start; i < end; i++) {
20956 DUK_ASSERT_TOP(ctx, 5);
20957 if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
20958 duk_xdef_prop_index_wec(ctx, 4, idx);
20959 res_length = idx + 1;
20960 } else {
20962 }
20963 idx++;
20964 DUK_ASSERT_TOP(ctx, 5);
20965 }
20966
20967 duk_push_u32(ctx, res_length);
20969
20970 DUK_ASSERT_TOP(ctx, 5);
20971 return 1;
20972}
20973
20974/*
20975 * shift()
20976 */
20977
20979 duk_uint32_t len;
20980 duk_uint32_t i;
20981
20982 len = duk__push_this_obj_len_u32(ctx);
20983 if (len == 0) {
20984 duk_push_int(ctx, 0);
20986 return 0;
20987 }
20988
20989 duk_get_prop_index(ctx, 0, 0);
20990
20991 /* stack[0] = object (this)
20992 * stack[1] = ToUint32(length)
20993 * stack[2] = elem at index 0 (retval)
20994 */
20995
20996 for (i = 1; i < len; i++) {
20997 DUK_ASSERT_TOP(ctx, 3);
20998 if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) {
20999 /* fromPresent = true */
21000 duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
21001 } else {
21002 /* fromPresent = false */
21004 duk_pop(ctx);
21005 }
21006 }
21007 duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1));
21008
21009 duk_push_u32(ctx, (duk_uint32_t) (len - 1));
21011
21012 DUK_ASSERT_TOP(ctx, 3);
21013 return 1;
21014}
21015
21016/*
21017 * unshift()
21018 */
21019
21021 duk_idx_t nargs;
21022 duk_uint32_t len;
21023 duk_uint32_t i;
21024
21025 nargs = duk_get_top(ctx);
21026 len = duk__push_this_obj_len_u32(ctx);
21027
21028 /* stack[0...nargs-1] = unshift args (vararg)
21029 * stack[nargs] = ToObject(this)
21030 * stack[nargs+1] = ToUint32(length)
21031 */
21032
21033 DUK_ASSERT_TOP(ctx, nargs + 2);
21034
21035 /* Note: unshift() may operate on indices above unsigned 32-bit range
21036 * and the final length may be >= 2**32. However, we restrict the
21037 * final result to 32-bit range for practicality.
21038 */
21039
21040 if (len + (duk_uint32_t) nargs < len) {
21041 DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
21042 return DUK_RET_RANGE_ERROR;
21043 }
21044
21045 i = len;
21046 while (i > 0) {
21047 DUK_ASSERT_TOP(ctx, nargs + 2);
21048 i--;
21049 /* k+argCount-1; note that may be above 32-bit range */
21050
21051 if (duk_get_prop_index(ctx, -2, (duk_uarridx_t) i)) {
21052 /* fromPresent = true */
21053 /* [ ... ToObject(this) ToUint32(length) val ] */
21054 duk_put_prop_index(ctx, -3, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
21055 } else {
21056 /* fromPresent = false */
21057 /* [ ... ToObject(this) ToUint32(length) val ] */
21058 duk_pop(ctx);
21059 duk_del_prop_index(ctx, -2, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
21060 }
21061 DUK_ASSERT_TOP(ctx, nargs + 2);
21062 }
21063
21064 for (i = 0; i < (duk_uint32_t) nargs; i++) {
21065 DUK_ASSERT_TOP(ctx, nargs + 2);
21066 duk_dup(ctx, i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
21067 duk_put_prop_index(ctx, -3, (duk_uarridx_t) i);
21068 DUK_ASSERT_TOP(ctx, nargs + 2);
21069 }
21070
21071 DUK_ASSERT_TOP(ctx, nargs + 2);
21072 duk_push_u32(ctx, len + nargs);
21073 duk_dup_top(ctx); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
21075 return 1;
21076}
21077
21078/*
21079 * indexOf(), lastIndexOf()
21080 */
21081
21083 duk_idx_t nargs;
21084 duk_int_t i, len;
21085 duk_int_t from_index;
21086 duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for indexOf, -1 for lastIndexOf */
21087
21088 /* lastIndexOf() needs to be a vararg function because we must distinguish
21089 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
21090 * made vararg for symmetry although it doesn't strictly need to be.
21091 */
21092
21093 nargs = duk_get_top(ctx);
21094 duk_set_top(ctx, 2);
21095
21096 /* XXX: must be able to represent -len */
21098 if (len == 0) {
21099 goto not_found;
21100 }
21101
21102 /* Index clamping is a bit tricky, we must ensure that we'll only iterate
21103 * through elements that exist and that the specific requirements from E5.1
21104 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
21105 *
21106 * - indexOf: clamp to [-len,len], negative handling -> [0,len],
21107 * if clamped result is len, for-loop bails out immediately
21108 *
21109 * - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
21110 * if clamped result is -1, for-loop bails out immediately
21111 *
21112 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
21113 * for indexOf() but incorrect for lastIndexOf(). Hence special handling,
21114 * and why lastIndexOf() needs to be a vararg function.
21115 */
21116
21117 if (nargs >= 2) {
21118 /* indexOf: clamp fromIndex to [-len, len]
21119 * (if fromIndex == len, for-loop terminates directly)
21120 *
21121 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
21122 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
21123 */
21124 from_index = duk_to_int_clamped(ctx,
21125 1,
21126 (idx_step > 0 ? -len : -len - 1),
21127 (idx_step > 0 ? len : len - 1));
21128 if (from_index < 0) {
21129 /* for lastIndexOf, result may be -1 (mark immediate termination) */
21130 from_index = len + from_index;
21131 }
21132 } else {
21133 /* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
21134 * handle both indexOf and lastIndexOf specially here.
21135 */
21136 if (idx_step > 0) {
21137 from_index = 0;
21138 } else {
21139 from_index = len - 1;
21140 }
21141 }
21142
21143 /* stack[0] = searchElement
21144 * stack[1] = fromIndex
21145 * stack[2] = object
21146 * stack[3] = length (not needed, but not popped above)
21147 */
21148
21149 for (i = from_index; i >= 0 && i < len; i += idx_step) {
21150 DUK_ASSERT_TOP(ctx, 4);
21151
21152 if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21153 DUK_ASSERT_TOP(ctx, 5);
21154 if (duk_strict_equals(ctx, 0, 4)) {
21156 return 1;
21160 duk_pop(ctx);
21161 }
21162
21163 not_found:
21164 duk_push_int(ctx, -1);
21165 return 1;
21167
21168/*
21169 * every(), some(), forEach(), map(), filter()
21170 */
21171
21172#define DUK__ITER_EVERY 0
21173#define DUK__ITER_SOME 1
21174#define DUK__ITER_FOREACH 2
21175#define DUK__ITER_MAP 3
21176#define DUK__ITER_FILTER 4
21177
21178/* XXX: This helper is a bit awkward because the handling for the different iteration
21179 * callers is quite different. This now compiles to a bit less than 500 bytes, so with
21180 * 5 callers the net result is about 100 bytes / caller.
21181 */
21182
21184 duk_uint32_t len;
21185 duk_uint32_t i;
21186 duk_uarridx_t k;
21187 duk_bool_t bval;
21188 duk_small_int_t iter_type = duk_get_current_magic(ctx);
21189 duk_uint32_t res_length = 0;
21190
21191 /* each call this helper serves has nargs==2 */
21192 DUK_ASSERT_TOP(ctx, 2);
21193
21194 len = duk__push_this_obj_len_u32(ctx);
21195 duk_require_callable(ctx, 0);
21196 /* if thisArg not supplied, behave as if undefined was supplied */
21197
21198 if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
21199 duk_push_array(ctx);
21200 } else {
21201 duk_push_undefined(ctx);
21202 }
21203
21204 /* stack[0] = callback
21205 * stack[1] = thisArg
21206 * stack[2] = object
21207 * stack[3] = ToUint32(length) (unused, but avoid unnecessary pop)
21208 * stack[4] = result array (or undefined)
21209 */
21210
21211 k = 0; /* result index for filter() */
21212 for (i = 0; i < len; i++) {
21213 DUK_ASSERT_TOP(ctx, 5);
21214
21215 if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21216#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER)
21217 /* Real world behavior for map(): trailing non-existent
21218 * elements don't invoke the user callback, but are still
21219 * counted towards result 'length'.
21220 */
21221 if (iter_type == DUK__ITER_MAP) {
21222 res_length = i + 1;
21223 }
21224#else
21225 /* Standard behavior for map(): trailing non-existent
21226 * elements don't invoke the user callback and are not
21227 * counted towards result 'length'.
21228 */
21229#endif
21230 duk_pop(ctx);
21231 continue;
21232 }
21233
21234 /* The original value needs to be preserved for filter(), hence
21235 * this funny order. We can't re-get the value because of side
21236 * effects.
21237 */
21238
21239 duk_dup(ctx, 0);
21240 duk_dup(ctx, 1);
21241 duk_dup(ctx, -3);
21242 duk_push_u32(ctx, i);
21243 duk_dup(ctx, 2); /* [ ... val callback thisArg val i obj ] */
21244 duk_call_method(ctx, 3); /* -> [ ... val retval ] */
21245
21246 switch (iter_type) {
21247 case DUK__ITER_EVERY:
21248 bval = duk_to_boolean(ctx, -1);
21249 if (!bval) {
21250 /* stack top contains 'false' */
21251 return 1;
21252 }
21253 break;
21254 case DUK__ITER_SOME:
21255 bval = duk_to_boolean(ctx, -1);
21256 if (bval) {
21257 /* stack top contains 'true' */
21258 return 1;
21259 }
21260 break;
21261 case DUK__ITER_FOREACH:
21262 /* nop */
21263 break;
21264 case DUK__ITER_MAP:
21265 duk_dup(ctx, -1);
21266 duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) i); /* retval to result[i] */
21267 res_length = i + 1;
21268 break;
21269 case DUK__ITER_FILTER:
21270 bval = duk_to_boolean(ctx, -1);
21271 if (bval) {
21272 duk_dup(ctx, -2); /* orig value */
21274 k++;
21275 res_length = k;
21276 }
21277 break;
21278 default:
21280 break;
21281 }
21282 duk_pop_2(ctx);
21283
21284 DUK_ASSERT_TOP(ctx, 5);
21285 }
21286
21287 switch (iter_type) {
21288 case DUK__ITER_EVERY:
21289 duk_push_true(ctx);
21290 break;
21291 case DUK__ITER_SOME:
21292 duk_push_false(ctx);
21293 break;
21294 case DUK__ITER_FOREACH:
21295 duk_push_undefined(ctx);
21296 break;
21297 case DUK__ITER_MAP:
21298 case DUK__ITER_FILTER:
21300 DUK_ASSERT(duk_is_array(ctx, -1)); /* topmost element is the result array already */
21301 duk_push_u32(ctx, res_length);
21303 break;
21304 default:
21306 break;
21307 }
21308
21309 return 1;
21310}
21311
21312/*
21313 * reduce(), reduceRight()
21314 */
21315
21317 duk_idx_t nargs;
21318 duk_bool_t have_acc;
21319 duk_uint32_t i, len;
21320 duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for reduce, -1 for reduceRight */
21321
21322 /* We're a varargs function because we need to detect whether
21323 * initialValue was given or not.
21324 */
21325 nargs = duk_get_top(ctx);
21326 DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
21327
21328 duk_set_top(ctx, 2);
21329 len = duk__push_this_obj_len_u32(ctx);
21330 if (!duk_is_callable(ctx, 0)) {
21331 goto type_error;
21332 }
21333
21334 /* stack[0] = callback fn
21335 * stack[1] = initialValue
21336 * stack[2] = object (coerced this)
21337 * stack[3] = length (not needed, but not popped above)
21338 * stack[4] = accumulator
21339 */
21340
21341 have_acc = 0;
21342 if (nargs >= 2) {
21343 duk_dup(ctx, 1);
21344 have_acc = 1;
21345 }
21346 DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
21347 (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3)));
21348
21349 /* For len == 0, i is initialized to len - 1 which underflows.
21350 * The condition (i < len) will then exit the for-loop on the
21351 * first round which is correct. Similarly, loop termination
21352 * happens by i underflowing.
21353 */
21354
21355 for (i = (idx_step >= 0 ? 0 : len - 1);
21356 i < len; /* i >= 0 would always be true */
21357 i += idx_step) {
21358 DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
21359 (long) i, (long) len, (long) have_acc,
21360 (long) duk_get_top(ctx),
21361 (duk_tval *) duk_get_tval(ctx, 4)));
21362
21363 DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) ||
21364 (!have_acc && duk_get_top(ctx) == 4));
21365
21366 if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21367 continue;
21368 }
21369
21370 if (!have_acc) {
21371 DUK_ASSERT_TOP(ctx, 4);
21372 duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
21373 have_acc = 1;
21374 DUK_ASSERT_TOP(ctx, 5);
21375 } else {
21376 DUK_ASSERT_TOP(ctx, 5);
21377 duk_dup(ctx, 0);
21378 duk_dup(ctx, 4);
21379 duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
21380 duk_push_u32(ctx, i);
21381 duk_dup(ctx, 2);
21382 DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
21383 (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4),
21384 (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
21385 (duk_tval *) duk_get_tval(ctx, -1)));
21386 duk_call(ctx, 4);
21387 DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
21388 duk_replace(ctx, 4);
21389 DUK_ASSERT_TOP(ctx, 5);
21390 }
21391 }
21392
21393 if (!have_acc) {
21394 goto type_error;
21395 }
21396
21397 DUK_ASSERT_TOP(ctx, 5);
21398 return 1;
21399
21400 type_error:
21401 return DUK_RET_TYPE_ERROR;
21402}
21404#undef DUK__ARRAY_MID_JOIN_LIMIT
21405
21406#undef DUK__ITER_EVERY
21407#undef DUK__ITER_SOME
21408#undef DUK__ITER_FOREACH
21409#undef DUK__ITER_MAP
21410#undef DUK__ITER_FILTER
21411/*
21412 * Boolean built-ins
21413 */
21414
21415/* include removed: duk_internal.h */
21416
21417/* Shared helper to provide toString() and valueOf(). Checks 'this', gets
21418 * the primitive value to stack top, and optionally coerces with ToString().
21419 */
21421 duk_tval *tv;
21422 duk_hobject *h;
21423 duk_small_int_t coerce_tostring = duk_get_current_magic(ctx);
21424
21425 /* XXX: there is room to use a shared helper here, many built-ins
21426 * check the 'this' type, and if it's an object, check its class,
21427 * then get its internal value, etc.
21428 */
21429
21430 duk_push_this(ctx);
21431 tv = duk_get_tval(ctx, -1);
21432 DUK_ASSERT(tv != NULL);
21433
21434 if (DUK_TVAL_IS_BOOLEAN(tv)) {
21435 goto type_ok;
21436 } else if (DUK_TVAL_IS_OBJECT(tv)) {
21437 h = DUK_TVAL_GET_OBJECT(tv);
21438 DUK_ASSERT(h != NULL);
21442 DUK_ASSERT(duk_is_boolean(ctx, -1));
21443 goto type_ok;
21444 }
21445 }
21446
21447 return DUK_RET_TYPE_ERROR;
21448
21449 type_ok:
21450 if (coerce_tostring) {
21451 duk_to_string(ctx, -1);
21452 }
21453 return 1;
21454}
21455
21457 duk_hthread *thr = (duk_hthread *) ctx;
21458 duk_hobject *h_this;
21459
21460 DUK_UNREF(thr);
21461
21462 duk_to_boolean(ctx, 0);
21463
21464 if (duk_is_constructor_call(ctx)) {
21465 /* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
21466 duk_push_this(ctx);
21467 h_this = duk_get_hobject(ctx, -1);
21468 DUK_ASSERT(h_this != NULL);
21470
21472
21473 duk_dup(ctx, 0); /* -> [ val obj val ] */
21474 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); /* XXX: proper flags? */
21475 } /* unbalanced stack */
21477 return 1;
21478}
21479/*
21480 * Duktape.Buffer, Node.js Buffer, and Khronos/ES6 TypedArray built-ins
21481 */
21482
21483/* include removed: duk_internal.h */
21484
21485/*
21486 * Misc helpers
21487 */
21488
21489#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21490/* Map DUK_HBUFFEROBJECT_ELEM_xxx to duk_hobject class number.
21491 * Sync with duk_hbufferobject.h and duk_hobject.h.
21492 */
21504#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21505
21506#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21507/* Map DUK_HBUFFEROBJECT_ELEM_xxx to prototype object built-in index.
21508 * Sync with duk_hbufferobject.h.
21520};
21521#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21522
21523#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21524/* Map DUK__FLX_xxx to byte size.
21525 */
21526static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
21527 1, /* DUK__FLD_8BIT */
21528 2, /* DUK__FLD_16BIT */
21529 4, /* DUK__FLD_32BIT */
21530 4, /* DUK__FLD_FLOAT */
21531 8, /* DUK__FLD_DOUBLE */
21532 0 /* DUK__FLD_VARINT; not relevant here */
21533};
21534#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21535
21536#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21537/* Bitfield for each DUK_HBUFFEROBJECT_ELEM_xxx indicating which element types
21538 * are compatible with a blind byte copy for the TypedArray set() method (also
21539 * used for TypedArray constructor). Array index is target buffer elem type,
21540 * bitfield indicates compatible source types. The types must have same byte
21541 * size and they must be coercion compatible.
21542 */
21543static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
21544 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8 */
21548
21549 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED
21550 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
21551 */
21554
21555 /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT8 */
21559
21560 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT16 */
21563
21564 /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT16 */
21567
21568 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT32 */
21571
21572 /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT32 */
21575
21576 /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT32 */
21578
21579 /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT64 */
21581};
21582#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21583
21584#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21585/* Shared helper. */
21587 duk_hthread *thr;
21588 duk_tval *tv;
21589 duk_hbufferobject *h_this;
21590
21591 DUK_ASSERT(ctx != NULL);
21592 thr = (duk_hthread *) ctx;
21593
21595 DUK_ASSERT(tv != NULL);
21596 if (DUK_TVAL_IS_OBJECT(tv)) {
21598 DUK_ASSERT(h_this != NULL);
21599 if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_this)) {
21601 return h_this;
21602 }
21603 }
21604
21605 if (throw_flag) {
21607 }
21608 return NULL;
21609}
21610#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21611
21612#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21613/* Check that 'this' is a duk_hbufferobject and return a pointer to it. */
21615 return duk__getrequire_bufobj_this(ctx, 0);
21616}
21617#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21618
21619#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21620/* Check that 'this' is a duk_hbufferobject and return a pointer to it
21621 * (NULL if not).
21622 */
21624 return duk__getrequire_bufobj_this(ctx, 1);
21625}
21626#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21627
21628#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21629/* Check that value is a duk_hbufferobject and return a pointer to it. */
21631 duk_hthread *thr;
21632 duk_tval *tv;
21633 duk_hbufferobject *h_obj;
21634
21635 thr = (duk_hthread *) ctx;
21636
21637 /* Don't accept relative indices now. */
21638 DUK_ASSERT(index >= 0);
21640 tv = duk_require_tval(ctx, index);
21641 DUK_ASSERT(tv != NULL);
21642 if (DUK_TVAL_IS_OBJECT(tv)) {
21643 h_obj = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv);
21644 DUK_ASSERT(h_obj != NULL);
21647 return h_obj;
21648 }
21649 }
21650
21652 return NULL; /* not reachable */
21653}
21654#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21655
21657 duk_hthread *thr;
21658
21659 thr = (duk_hthread *) ctx;
21660 DUK_UNREF(thr);
21662 DUK_ASSERT(ctx != NULL);
21663 DUK_ASSERT(h_bufobj != NULL);
21664 DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */
21665 DUK_ASSERT(h_val != NULL);
21667
21668 h_bufobj->buf = h_val;
21669 DUK_HBUFFER_INCREF(thr, h_val);
21670 h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
21671 DUK_ASSERT(h_bufobj->shift == 0);
21673
21675}
21676
21677#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21679 duk_hbuffer *h_val;
21680 duk_hbufferobject *h_bufobj;
21681
21682 (void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
21683 h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
21684 DUK_ASSERT(h_val != NULL);
21686 h_bufobj = duk_push_bufferobject_raw(ctx,
21691 DUK_ASSERT(h_bufobj != NULL);
21692
21693 duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
21695
21696 return h_bufobj;
21697}
21698#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21699
21700#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21701/* Shared offset/length coercion helper. */
21703 duk_hbufferobject *h_bufarg,
21704 duk_idx_t idx_offset,
21705 duk_idx_t idx_length,
21706 duk_uint_t *out_offset,
21707 duk_uint_t *out_length,
21708 duk_bool_t throw_flag) {
21709 duk_hthread *thr;
21710 duk_int_t offset_signed;
21711 duk_int_t length_signed;
21712 duk_uint_t offset;
21713 duk_uint_t length;
21714
21715 thr = (duk_hthread *) ctx;
21716 DUK_UNREF(thr);
21717
21718 offset_signed = duk_to_int(ctx, idx_offset);
21719 if (offset_signed < 0) {
21720 goto fail_range;
21721 }
21722 offset = (duk_uint_t) offset_signed;
21723 if (offset > h_bufarg->length) {
21724 goto fail_range;
21725 }
21726 DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */
21727 DUK_ASSERT(offset <= h_bufarg->length);
21728
21729 if (duk_is_undefined(ctx, idx_length)) {
21730 DUK_ASSERT(h_bufarg->length >= offset);
21731 length = h_bufarg->length - offset; /* >= 0 */
21732 } else {
21733 length_signed = duk_to_int(ctx, idx_length);
21734 if (length_signed < 0) {
21735 goto fail_range;
21736 }
21737 length = (duk_uint_t) length_signed;
21738 DUK_ASSERT(h_bufarg->length >= offset);
21739 if (length > h_bufarg->length - offset) {
21740 /* Unlike for negative arguments, some call sites
21741 * want length to be clamped if it's positive.
21742 */
21743 if (throw_flag) {
21744 goto fail_range;
21745 } else {
21746 length = h_bufarg->length - offset;
21747 }
21748 }
21750 DUK_ASSERT_DISABLE(length >= 0); /* unsigned */
21751 DUK_ASSERT(offset + length <= h_bufarg->length);
21752
21753 *out_offset = offset;
21754 *out_length = length;
21755 return;
21756
21757 fail_range:
21759}
21760#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21761
21762#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21763/* Shared lenient buffer length clamping helper. No negative indices, no
21764 * element/byte shifting.
21765 */
21767 duk_hbufferobject *h_bufobj,
21768 duk_idx_t idx_start,
21769 duk_idx_t idx_end,
21770 duk_int_t *out_start_offset,
21771 duk_int_t *out_end_offset) {
21772 duk_int_t buffer_length;
21773 duk_int_t start_offset;
21774 duk_int_t end_offset;
21775
21776 DUK_ASSERT(out_start_offset != NULL);
21777 DUK_ASSERT(out_end_offset != NULL);
21778
21779 buffer_length = (duk_int_t) h_bufobj->length;
21780
21781 /* undefined coerces to zero which is correct */
21782 start_offset = duk_to_int_clamped(ctx, idx_start, 0, buffer_length);
21783 if (duk_is_undefined(ctx, idx_end)) {
21784 end_offset = buffer_length;
21785 } else {
21786 end_offset = duk_to_int_clamped(ctx, idx_end, start_offset, buffer_length);
21787 }
21788
21789 DUK_ASSERT(start_offset >= 0);
21790 DUK_ASSERT(start_offset <= buffer_length);
21791 DUK_ASSERT(end_offset >= 0);
21792 DUK_ASSERT(end_offset <= buffer_length);
21793 DUK_ASSERT(start_offset <= end_offset);
21794
21795 *out_start_offset = start_offset;
21796 *out_end_offset = end_offset;
21797}
21798#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21799
21800#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21801/* Shared lenient buffer length clamping helper. Indices are treated as
21802 * element indices (though output values are byte offsets) which only
21803 * really matters for TypedArray views as other buffer object have a zero
21804 * shift. Negative indices are counted from end of input slice; crossed
21805 * indices are clamped to zero length; and final indices are clamped
21806 * against input slice. Used for e.g. ArrayBuffer slice().
21807 */
21809 duk_hbufferobject *h_bufobj,
21810 duk_idx_t idx_start,
21811 duk_idx_t idx_end,
21812 duk_int_t *out_start_offset,
21813 duk_int_t *out_end_offset) {
21814 duk_int_t buffer_length;
21815 duk_int_t start_offset;
21816 duk_int_t end_offset;
21817
21818 DUK_ASSERT(out_start_offset != NULL);
21819 DUK_ASSERT(out_end_offset != NULL);
21820
21821 buffer_length = (duk_int_t) h_bufobj->length;
21822 buffer_length >>= h_bufobj->shift; /* as elements */
21823
21824 /* Resolve start/end offset as element indices first; arguments
21825 * at idx_start/idx_end are element offsets. Working with element
21826 * indices first also avoids potential for wrapping.
21827 */
21828
21829 start_offset = duk_to_int(ctx, idx_start);
21830 if (start_offset < 0) {
21831 start_offset = buffer_length + start_offset;
21832 }
21833 if (duk_is_undefined(ctx, idx_end)) {
21834 end_offset = buffer_length;
21835 } else {
21836 end_offset = duk_to_int(ctx, idx_end);
21837 if (end_offset < 0) {
21838 end_offset = buffer_length + end_offset;
21839 }
21840 }
21841 /* Note: start_offset/end_offset can still be < 0 here. */
21842
21843 if (start_offset < 0) {
21844 start_offset = 0;
21845 } else if (start_offset > buffer_length) {
21846 start_offset = buffer_length;
21847 }
21848 if (end_offset < start_offset) {
21849 end_offset = start_offset;
21850 } else if (end_offset > buffer_length) {
21851 end_offset = buffer_length;
21852 }
21853 DUK_ASSERT(start_offset >= 0);
21854 DUK_ASSERT(start_offset <= buffer_length);
21855 DUK_ASSERT(end_offset >= 0);
21856 DUK_ASSERT(end_offset <= buffer_length);
21857 DUK_ASSERT(start_offset <= end_offset);
21858
21859 /* Convert indices to byte offsets. */
21860 start_offset <<= h_bufobj->shift;
21861 end_offset <<= h_bufobj->shift;
21862
21863 *out_start_offset = start_offset;
21864 *out_end_offset = end_offset;
21865}
21866#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21867
21868/*
21869 * Indexed read/write helpers (also used from outside this file)
21870 */
21871
21874
21875 DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);
21876
21877 switch (h_bufobj->elem_type) {
21879#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21881#endif
21882 duk_push_uint(ctx, (duk_uint_t) du.uc[0]);
21883 break;
21884#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21885 /* These are not needed when only Duktape.Buffer is supported. */
21887 duk_push_int(ctx, (duk_int_t) (duk_int8_t) du.uc[0]);
21888 break;
21890 duk_push_uint(ctx, (duk_uint_t) du.us[0]);
21891 break;
21893 duk_push_int(ctx, (duk_int_t) (duk_int16_t) du.us[0]);
21894 break;
21897 break;
21899 duk_push_int(ctx, (duk_int_t) (duk_int32_t) du.ui[0]);
21900 break;
21902 duk_push_number(ctx, (duk_double_t) du.f[0]);
21903 break;
21905 duk_push_number(ctx, (duk_double_t) du.d);
21906 break;
21907#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21908 default:
21910 }
21911}
21912
21913DUK_INTERNAL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
21915
21916 /* NOTE! Caller must ensure that any side effects from the
21917 * coercions below are safe. If that cannot be guaranteed
21918 * (which is normally the case), caller must coerce the
21919 * argument using duk_to_number() before any pointer
21920 * validations; the result of duk_to_number() always coerces
21921 * without side effects here.
21922 */
21923
21924 switch (h_bufobj->elem_type) {
21926 du.uc[0] = (duk_uint8_t) duk_to_uint32(ctx, -1);
21927 break;
21928#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21929 /* These are not needed when only Duktape.Buffer is supported. */
21931 du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(ctx, -1);
21932 break;
21934 du.uc[0] = (duk_uint8_t) duk_to_int32(ctx, -1);
21935 break;
21937 du.us[0] = (duk_uint16_t) duk_to_uint32(ctx, -1);
21938 break;
21940 du.us[0] = (duk_uint16_t) duk_to_int32(ctx, -1);
21941 break;
21943 du.ui[0] = (duk_uint32_t) duk_to_uint32(ctx, -1);
21944 break;
21946 du.ui[0] = (duk_uint32_t) duk_to_int32(ctx, -1);
21947 break;
21949 du.f[0] = (duk_float_t) duk_to_number(ctx, -1);
21950 break;
21952 du.d = (duk_double_t) duk_to_number(ctx, -1);
21953 break;
21954#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21955 default:
21957 }
21958
21959 DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);
21960}
21961
21962/*
21963 * Duktape.Buffer: constructor
21964 */
21965
21967 duk_hthread *thr;
21968 duk_size_t buf_size;
21969 duk_small_int_t buf_dynamic;
21970 duk_uint8_t *buf_data;
21971 const duk_uint8_t *src_data;
21972
21973 thr = (duk_hthread *) ctx;
21974 DUK_UNREF(thr);
21975
21976 /*
21977 * Constructor arguments are currently somewhat compatible with
21978 * (keep it that way if possible):
21979 *
21980 * http://nodejs.org/api/buffer.html
21981 *
21982 * Note that the ToBuffer() coercion (duk_to_buffer()) does NOT match
21983 * the constructor behavior.
21984 */
21985
21986 buf_dynamic = duk_get_boolean(ctx, 1); /* default to false */
21987
21988 switch (duk_get_type(ctx, 0)) {
21989 case DUK_TYPE_NUMBER: {
21990 /* new buffer of specified size */
21991 buf_size = (duk_size_t) duk_to_int(ctx, 0);
21992 (void) duk_push_buffer(ctx, buf_size, buf_dynamic);
21993 break;
21994 }
21995 case DUK_TYPE_BUFFER: {
21996 /* return input buffer, converted to a Duktape.Buffer object
21997 * if called as a constructor (no change if called as a
21998 * function).
21999 */
22000 duk_set_top(ctx, 1);
22001 break;
22002 }
22003 case DUK_TYPE_STRING: {
22004 /* new buffer with string contents */
22005 src_data = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &buf_size);
22006 DUK_ASSERT(src_data != NULL); /* even for zero-length string */
22007 buf_data = (duk_uint8_t *) duk_push_buffer(ctx, buf_size, buf_dynamic);
22008 DUK_MEMCPY((void *) buf_data, (const void *) src_data, (size_t) buf_size);
22009 break;
22010 }
22011 case DUK_TYPE_OBJECT: {
22012 /* For all duk_hbufferobjects, get the plain buffer inside
22013 * without making a copy. This is compatible with Duktape 1.2
22014 * but means that a slice/view information is ignored and the
22015 * full underlying buffer is returned.
22016 *
22017 * If called as a constructor, a new Duktape.Buffer object
22018 * pointing to the same plain buffer is created below.
22019 */
22020 duk_hbufferobject *h_bufobj;
22021 h_bufobj = (duk_hbufferobject *) duk_get_hobject(ctx, 0);
22022 DUK_ASSERT(h_bufobj != NULL);
22023 if (!DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)) {
22024 return DUK_RET_TYPE_ERROR;
22025 }
22026 if (h_bufobj->buf == NULL) {
22027 return DUK_RET_TYPE_ERROR;
22028 }
22029 duk_push_hbuffer(ctx, h_bufobj->buf);
22030 break;
22031 }
22032 case DUK_TYPE_NONE:
22033 default: {
22034 return DUK_RET_TYPE_ERROR;
22035 }
22036 }
22037 DUK_ASSERT(duk_is_buffer(ctx, -1));
22038
22039 /* stack is unbalanced, but: [ <something> buf ] */
22040
22041 if (duk_is_constructor_call(ctx)) {
22042 duk_hbufferobject *h_bufobj;
22043 duk_hbuffer *h_val;
22044
22045 h_val = duk_get_hbuffer(ctx, -1);
22046 DUK_ASSERT(h_val != NULL);
22047
22048 h_bufobj = duk_push_bufferobject_raw(ctx,
22053 DUK_ASSERT(h_bufobj != NULL);
22054
22055 duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
22056
22058 }
22059 /* Note: unbalanced stack on purpose */
22060
22061 return 1;
22062}
22063
22064/*
22065 * Node.js Buffer: constructor
22066 */
22067
22068#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22070 /* Internal class is Object: Object.prototype.toString.call(new Buffer(0))
22071 * prints "[object Object]".
22072 */
22073 duk_int_t len;
22074 duk_int_t i;
22075 duk_hbuffer *h_buf;
22076 duk_hbufferobject *h_bufobj;
22077 duk_size_t buf_size;
22078
22079 switch (duk_get_type(ctx, 0)) {
22080 case DUK_TYPE_BUFFER: {
22081 /* Custom behavior: plain buffer is used as internal buffer
22082 * without making a copy (matches Duktape.Buffer).
22083 */
22084 duk_set_top(ctx, 1); /* -> [ buffer ] */
22085 break;
22086 }
22087 case DUK_TYPE_NUMBER: {
22088 len = duk_to_int_clamped(ctx, 0, 0, DUK_INT_MAX);
22089 (void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22090 break;
22091 }
22092 case DUK_TYPE_OBJECT: {
22093 duk_uint8_t *buf;
22094
22095 (void) duk_get_prop_string(ctx, 0, "length");
22096 len = duk_to_int_clamped(ctx, -1, 0, DUK_INT_MAX);
22097 duk_pop(ctx);
22098 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22099 for (i = 0; i < len; i++) {
22100 /* XXX: fast path for array arguments? */
22101 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
22102 buf[i] = (duk_uint8_t) (duk_to_uint32(ctx, -1) & 0xffU);
22103 duk_pop(ctx);
22104 }
22105 break;
22106 }
22107 case DUK_TYPE_STRING: {
22108 /* ignore encoding for now */
22109 duk_dup(ctx, 0);
22110 (void) duk_to_buffer(ctx, -1, &buf_size);
22111 break;
22112 }
22113 default:
22114 return DUK_RET_TYPE_ERROR;
22115 }
22116
22117 DUK_ASSERT(duk_is_buffer(ctx, -1));
22118 h_buf = duk_get_hbuffer(ctx, -1);
22119 DUK_ASSERT(h_buf != NULL);
22120
22121 h_bufobj = duk_push_bufferobject_raw(ctx,
22126 DUK_ASSERT(h_bufobj != NULL);
22127
22128 h_bufobj->buf = h_buf;
22129 DUK_HBUFFER_INCREF(thr, h_buf);
22130 DUK_ASSERT(h_bufobj->offset == 0);
22131 h_bufobj->length = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_buf);
22135
22136 return 1;
22137}
22138#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22140 DUK_UNREF(ctx);
22142}
22143#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22144
22145/*
22146 * ArrayBuffer, DataView, and TypedArray constructors
22147 */
22148
22149#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22151 duk_hthread *thr;
22152 duk_hbufferobject *h_bufobj;
22153 duk_hbuffer *h_val;
22154
22156 thr = (duk_hthread *) ctx;
22157 DUK_UNREF(thr);
22158
22159 /* XXX: function flag to make this automatic? */
22160 if (!duk_is_constructor_call(ctx)) {
22161 return DUK_RET_TYPE_ERROR;
22162 }
22163
22164 if (duk_is_buffer(ctx, 0)) {
22165 /* Custom behavior: plain buffer is used as internal buffer
22166 * without making a copy (matches Duktape.Buffer).
22167 */
22168
22169 h_val = duk_get_hbuffer(ctx, 0);
22170 DUK_ASSERT(h_val != NULL);
22171
22172 /* XXX: accept any duk_hbufferobject type as an input also? */
22173 } else {
22174 duk_int_t len;
22175 len = duk_to_int(ctx, 0);
22176 if (len < 0) {
22177 goto fail_length;
22178 }
22179 (void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22180 h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
22181 DUK_ASSERT(h_val != NULL);
22182
22183#if !defined(DUK_USE_ZERO_BUFFER_DATA)
22184 /* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
22185 * is not set.
22186 */
22188 DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) len);
22189#endif
22190 }
22191
22192 h_bufobj = duk_push_bufferobject_raw(ctx,
22197 DUK_ASSERT(h_bufobj != NULL);
22198
22199 duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
22201
22202 return 1;
22203
22204 fail_length:
22205 return DUK_RET_RANGE_ERROR;
22206}
22207#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22209 DUK_UNREF(ctx);
22211}
22212#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22213
22214
22215/* Format of magic, bits:
22216 * 0...1: elem size shift (0-3)
22217 * 2...5: elem type (DUK_HBUFFEROBJECT_ELEM_xxx)
22218 */
22219
22220#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22222 duk_hthread *thr;
22223 duk_tval *tv;
22224 duk_hobject *h_obj;
22225 duk_hbufferobject *h_bufobj = NULL;
22226 duk_hbufferobject *h_bufarr = NULL;
22227 duk_hbufferobject *h_bufarg = NULL;
22228 duk_hbuffer *h_val;
22229 duk_small_uint_t magic;
22230 duk_small_uint_t shift;
22231 duk_small_uint_t elem_type;
22232 duk_small_uint_t elem_size;
22233 duk_small_uint_t class_num;
22234 duk_small_uint_t proto_bidx;
22235 duk_uint_t align_mask;
22236 duk_uint_t elem_length;
22237 duk_int_t elem_length_signed;
22238 duk_uint_t byte_length;
22239 duk_small_uint_t copy_mode;
22240
22241 thr = (duk_hthread *) ctx;
22242 DUK_UNREF(thr);
22243
22244 /* XXX: function flag to make this automatic? */
22245 if (!duk_is_constructor_call(ctx)) {
22246 return DUK_RET_TYPE_ERROR;
22247 }
22248
22249 /* We could fit built-in index into magic but that'd make the magic
22250 * number dependent on built-in numbering (genbuiltins.py doesn't
22251 * handle that yet). So map both class and prototype from the
22252 * element type.
22253 */
22254 magic = duk_get_current_magic(ctx);
22255 shift = magic & 0x03; /* bits 0...1: shift */
22256 elem_type = (magic >> 2) & 0x0f; /* bits 2...5: type */
22257 elem_size = 1 << shift;
22258 align_mask = elem_size - 1;
22259 DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
22260 proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
22261 DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
22262 DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
22263 class_num = duk__buffer_class_from_elemtype[elem_type];
22264
22265 DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
22266 "elem_size=%d, proto_bidx=%d, class_num=%d",
22267 (int) magic, (int) shift, (int) elem_type, (int) elem_size,
22268 (int) proto_bidx, (int) class_num));
22269
22270 /* Argument variants. When the argument is an ArrayBuffer a view to
22271 * the same buffer is created; otherwise a new ArrayBuffer is always
22272 * created.
22273 */
22274
22275 tv = duk_get_tval(ctx, 0);
22276 DUK_ASSERT(tv != NULL); /* arg count */
22277 if (DUK_TVAL_IS_OBJECT(tv)) {
22278 h_obj = DUK_TVAL_GET_OBJECT(tv);
22279 DUK_ASSERT(h_obj != NULL);
22280
22282 /* ArrayBuffer: unlike any other argument variant, create
22283 * a view into the existing buffer.
22284 */
22285
22286 duk_int_t byte_offset_signed;
22287 duk_uint_t byte_offset;
22288
22289 h_bufarg = (duk_hbufferobject *) h_obj;
22290
22291 byte_offset_signed = duk_to_int(ctx, 1);
22292 if (byte_offset_signed < 0) {
22293 goto fail_arguments;
22294 }
22295 byte_offset = (duk_uint_t) byte_offset_signed;
22296 if (byte_offset > h_bufarg->length ||
22297 (byte_offset & align_mask) != 0) {
22298 /* Must be >= 0 and multiple of element size. */
22299 goto fail_arguments;
22300 }
22301 if (duk_is_undefined(ctx, 2)) {
22302 DUK_ASSERT(h_bufarg->length >= byte_offset);
22303 byte_length = h_bufarg->length - byte_offset;
22304 if ((byte_length & align_mask) != 0) {
22305 /* Must be element size multiple from
22306 * start offset to end of buffer.
22307 */
22308 goto fail_arguments;
22309 }
22310 elem_length = (byte_length >> shift);
22311 } else {
22312 elem_length_signed = duk_to_int(ctx, 2);
22313 if (elem_length_signed < 0) {
22314 goto fail_arguments;
22315 }
22316 elem_length = (duk_uint_t) elem_length_signed;
22317 byte_length = elem_length << shift;
22318 if ((byte_length >> shift) != elem_length) {
22319 /* Byte length would overflow. */
22320 /* XXX: easier check with less code? */
22321 goto fail_arguments;
22322 }
22323 DUK_ASSERT(h_bufarg->length >= byte_offset);
22324 if (byte_length > h_bufarg->length - byte_offset) {
22325 /* Not enough data. */
22326 goto fail_arguments;
22327 }
22328 }
22329 DUK_UNREF(elem_length);
22330 DUK_ASSERT_DISABLE(byte_offset >= 0);
22331 DUK_ASSERT(byte_offset <= h_bufarg->length);
22332 DUK_ASSERT_DISABLE(byte_length >= 0);
22333 DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
22334 DUK_ASSERT((elem_length << shift) == byte_length);
22335
22336 h_bufobj = duk_push_bufferobject_raw(ctx,
22339 DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
22340 proto_bidx);
22341 h_val = h_bufarg->buf;
22342 if (h_val == NULL) {
22343 return DUK_RET_TYPE_ERROR;
22344 }
22345 h_bufobj->buf = h_val;
22346 DUK_HBUFFER_INCREF(thr, h_val);
22347 h_bufobj->offset = h_bufarg->offset + byte_offset;
22348 h_bufobj->length = byte_length;
22349 h_bufobj->shift = (duk_uint8_t) shift;
22350 h_bufobj->elem_type = (duk_uint8_t) elem_type;
22351 h_bufobj->is_view = 1;
22353
22354 /* Set .buffer to the argument ArrayBuffer. */
22355 duk_dup(ctx, 0);
22357 duk_compact(ctx, -1);
22358 return 1;
22359 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
22360 /* TypedArray (or other non-ArrayBuffer duk_hbufferobject).
22361 * Conceptually same behavior as for an Array-like argument,
22362 * with a few fast paths.
22363 */
22364
22365 h_bufarg = (duk_hbufferobject *) h_obj;
22367 elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
22368 if (h_bufarg->buf == NULL) {
22369 return DUK_RET_TYPE_ERROR;
22370 }
22371
22372 /* Select copy mode. Must take into account element
22373 * compatibility and validity of the underlying source
22374 * buffer.
22375 */
22376
22377 DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
22378 "src byte_length=%ld, src shift=%d, "
22379 "src/dst elem_length=%ld; "
22380 "dst shift=%d -> dst byte_length=%ld",
22381 (long) h_bufarg->length, (int) h_bufarg->shift,
22382 (long) elem_length_signed, (int) shift,
22383 (long) (elem_length_signed << shift)));
22384
22385 copy_mode = 2; /* default is explicit index read/write copy */
22386 DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
22387 if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
22388 if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
22389 DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
22390 DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */
22391 copy_mode = 0;
22392 } else {
22393 DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
22394 copy_mode = 1;
22395 }
22396 }
22397 } else {
22398 /* Array or Array-like */
22399 elem_length_signed = (duk_int_t) duk_get_length(ctx, 0);
22400 copy_mode = 2;
22401 }
22402 } else if (DUK_TVAL_IS_BUFFER(tv)) {
22403 /* Accept plain buffer values like array initializers
22404 * (new in Duktape 1.4.0).
22405 */
22406 duk_hbuffer *h_srcbuf;
22407 h_srcbuf = DUK_TVAL_GET_BUFFER(tv);
22408 elem_length_signed = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_srcbuf);
22409 copy_mode = 2; /* XXX: could add fast path for u8 compatible views */
22410 } else {
22411 /* Non-object argument is simply int coerced, matches
22412 * V8 behavior (except for "null", which we coerce to
22413 * 0 but V8 TypeErrors).
22414 */
22415 elem_length_signed = duk_to_int(ctx, 0);
22416 copy_mode = 3;
22417 }
22418 if (elem_length_signed < 0) {
22419 goto fail_arguments;
22420 }
22421 elem_length = (duk_uint_t) elem_length_signed;
22422 byte_length = (duk_uint_t) (elem_length << shift);
22423 if ((byte_length >> shift) != elem_length) {
22424 /* Byte length would overflow. */
22425 /* XXX: easier check with less code? */
22426 goto fail_arguments;
22427 }
22428
22429 DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
22430 (long) elem_length, (long) byte_length));
22431
22432 /* ArrayBuffer argument is handled specially above; the rest of the
22433 * argument variants are handled by shared code below.
22434 */
22435
22436 /* Push a new ArrayBuffer (becomes view .buffer) */
22437 h_bufarr = duk__push_arraybuffer_with_length(ctx, byte_length);
22438 DUK_ASSERT(h_bufarr != NULL);
22439 h_val = h_bufarr->buf;
22440 DUK_ASSERT(h_val != NULL);
22441
22442 /* Push the resulting view object and attach the ArrayBuffer. */
22443 h_bufobj = duk_push_bufferobject_raw(ctx,
22446 DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
22447 proto_bidx);
22448
22449 h_bufobj->buf = h_val;
22450 DUK_HBUFFER_INCREF(thr, h_val);
22451 DUK_ASSERT(h_bufobj->offset == 0);
22452 h_bufobj->length = byte_length;
22453 h_bufobj->shift = (duk_uint8_t) shift;
22454 h_bufobj->elem_type = (duk_uint8_t) elem_type;
22455 h_bufobj->is_view = 1;
22457
22458 /* Set .buffer */
22459 duk_dup(ctx, -2);
22461 duk_compact(ctx, -1);
22462
22463 /* Copy values, the copy method depends on the arguments.
22464 *
22465 * Copy mode decision may depend on the validity of the underlying
22466 * buffer of the source argument; there must be no harmful side effects
22467 * from there to here for copy_mode to still be valid.
22468 */
22469 DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
22470 switch (copy_mode) {
22471 case 0: {
22472 /* Use byte copy. */
22473
22474 duk_uint8_t *p_src;
22475 duk_uint8_t *p_dst;
22476
22477 DUK_ASSERT(h_bufobj != NULL);
22478 DUK_ASSERT(h_bufobj->buf != NULL);
22480 DUK_ASSERT(h_bufarg != NULL);
22481 DUK_ASSERT(h_bufarg->buf != NULL);
22483
22484 p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
22485 p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
22486
22487 DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
22488 (void *) p_src, (void *) p_dst, (long) byte_length));
22489
22490 DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length);
22491 break;
22492 }
22493 case 1: {
22494 /* Copy values through direct validated reads and writes. */
22495
22496 duk_small_uint_t src_elem_size;
22497 duk_small_uint_t dst_elem_size;
22498 duk_uint8_t *p_src;
22499 duk_uint8_t *p_src_end;
22500 duk_uint8_t *p_dst;
22501
22502 DUK_ASSERT(h_bufobj != NULL);
22503 DUK_ASSERT(h_bufobj->buf != NULL);
22505 DUK_ASSERT(h_bufarg != NULL);
22506 DUK_ASSERT(h_bufarg->buf != NULL);
22508
22509 src_elem_size = 1 << h_bufarg->shift;
22510 dst_elem_size = elem_size;
22511
22512 p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
22513 p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
22514 p_src_end = p_src + h_bufarg->length;
22515
22516 DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
22517 "src_elem_size=%d, dst_elem_size=%d",
22518 (void *) p_src, (void *) p_src_end, (void *) p_dst,
22519 (int) src_elem_size, (int) dst_elem_size));
22520
22521 while (p_src != p_src_end) {
22522 DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
22523 "p_src=%p, p_src_end=%p, p_dst=%p",
22524 (void *) p_src, (void *) p_src_end, (void *) p_dst));
22525 /* A validated read() is always a number, so it's write coercion
22526 * is always side effect free an won't invalidate pointers etc.
22527 */
22528 duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
22529 duk_hbufferobject_validated_write(ctx, h_bufobj, p_dst, dst_elem_size);
22530 duk_pop(ctx);
22531 p_src += src_elem_size;
22532 p_dst += dst_elem_size;
22533 }
22534 break;
22535 }
22536 case 2: {
22537 /* Copy values by index reads and writes. Let virtual
22538 * property handling take care of coercion.
22539 */
22540 duk_uint_t i;
22541
22542 DUK_DDD(DUK_DDDPRINT("using slow copy"));
22543
22544 for (i = 0; i < elem_length; i++) {
22545 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
22546 duk_put_prop_index(ctx, -2, (duk_uarridx_t) i);
22547 }
22548 break;
22549 }
22550 default:
22551 case 3: {
22552 /* No copy, leave zero bytes in the buffer. There's no
22553 * ambiguity with Float32/Float64 because zero bytes also
22554 * represent 0.0.
22555 */
22556#if !defined(DUK_USE_ZERO_BUFFER_DATA)
22557 /* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
22558 * is not set.
22559 */
22561 DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) byte_length);
22562#endif
22563
22564 DUK_DDD(DUK_DDDPRINT("using no copy"));
22565 break;
22566 }
22567 }
22568
22569 return 1;
22570
22571 fail_arguments:
22572 return DUK_RET_RANGE_ERROR;
22573}
22574#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22576 DUK_UNREF(ctx);
22578}
22579#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22580
22581#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22583 duk_hbufferobject *h_bufarg;
22584 duk_hbufferobject *h_bufobj;
22585 duk_hbuffer *h_val;
22586 duk_uint_t offset;
22587 duk_uint_t length;
22588
22589 /* XXX: function flag to make this automatic? */
22590 if (!duk_is_constructor_call(ctx)) {
22591 return DUK_RET_TYPE_ERROR;
22592 }
22593
22594 h_bufarg = duk__require_bufobj_value(ctx, 0);
22595 DUK_ASSERT(h_bufarg != NULL);
22596
22597 duk__resolve_offset_opt_length(ctx, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
22598 DUK_ASSERT(offset <= h_bufarg->length);
22599 DUK_ASSERT(offset + length <= h_bufarg->length);
22600
22601 h_bufobj = duk_push_bufferobject_raw(ctx,
22606
22607 h_val = h_bufarg->buf;
22608 if (h_val == NULL) {
22609 return DUK_RET_TYPE_ERROR;
22610 }
22611 h_bufobj->buf = h_val;
22612 DUK_HBUFFER_INCREF(thr, h_val);
22613 h_bufobj->offset = h_bufarg->offset + offset;
22614 h_bufobj->length = length;
22615 DUK_ASSERT(h_bufobj->shift == 0);
22617 h_bufobj->is_view = 1;
22618
22619 /* The DataView .buffer property is ordinarily set to the argument
22620 * which is an ArrayBuffer. We accept any duk_hbufferobject as
22621 * an argument and .buffer will be set to the argument regardless
22622 * of what it is. This may be a bit confusing if the argument
22623 * is e.g. a DataView or another TypedArray view.
22624 *
22625 * XXX: Copy .buffer property from a DataView/TypedArray argument?
22626 * Create a fresh ArrayBuffer for Duktape.Buffer and Node.js Buffer
22627 * arguments? See: test-bug-dataview-buffer-prop.js.
22628 */
22629
22630 duk_dup(ctx, 0);
22632 duk_compact(ctx, -1);
22633
22635 return 1;
22636}
22637#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22639 DUK_UNREF(ctx);
22641}
22642#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22643
22644/*
22645 * ArrayBuffer.isView()
22646 */
22647
22648#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22650 duk_hobject *h_obj;
22651 duk_bool_t ret = 0;
22652
22653 h_obj = duk_get_hobject(ctx, 0);
22654 if (h_obj != NULL && DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
22655 ret = ((duk_hbufferobject *) h_obj)->is_view;
22656 }
22657 duk_push_boolean(ctx, ret);
22658 return 1;
22659}
22660#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22662 DUK_UNREF(ctx);
22664}
22665#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22666
22667/*
22668 * Node.js Buffer: toString([encoding], [start], [end])
22669 */
22670
22671#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22673 duk_hthread *thr;
22674 duk_hbufferobject *h_this;
22675 duk_int_t start_offset, end_offset;
22676 duk_uint8_t *buf_slice;
22677 duk_size_t slice_length;
22678
22679 thr = (duk_hthread *) ctx;
22680 DUK_UNREF(thr);
22681
22682 h_this = duk__get_bufobj_this(ctx);
22683 if (h_this == NULL) {
22684 /* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
22685 duk_push_string(ctx, "[object Object]");
22686 return 1;
22687 }
22689
22690 /* ignore encoding for now */
22691
22692 duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &start_offset, &end_offset);
22693
22694 slice_length = (duk_size_t) (end_offset - start_offset);
22695 buf_slice = (duk_uint8_t *) duk_push_fixed_buffer(ctx, slice_length);
22696 DUK_ASSERT(buf_slice != NULL);
22697
22698 if (h_this->buf == NULL) {
22699 goto type_error;
22700 }
22701
22702 if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) {
22703 DUK_MEMCPY((void *) buf_slice,
22704 (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
22705 (size_t) slice_length);
22706 } else {
22707 /* not covered, return all zeroes */
22708 ;
22709 }
22710
22711 duk_to_string(ctx, -1);
22712 return 1;
22713
22714 type_error:
22715 return DUK_RET_TYPE_ERROR;
22716}
22717#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22719 DUK_UNREF(ctx);
22721}
22722#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22723
22724/*
22725 * Duktape.Buffer: toString(), valueOf()
22726 */
22727
22728#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22730 duk_hthread *thr;
22731 duk_tval *tv;
22732 duk_small_int_t to_string = duk_get_current_magic(ctx);
22733
22734 thr = (duk_hthread *) ctx;
22735 DUK_UNREF(thr);
22736
22738 DUK_ASSERT(tv != NULL);
22739
22740 if (DUK_TVAL_IS_BUFFER(tv)) {
22741 duk_hbuffer *h_buf;
22742 h_buf = DUK_TVAL_GET_BUFFER(tv);
22743 DUK_ASSERT(h_buf != NULL);
22744 duk_push_hbuffer(ctx, h_buf);
22745 } else if (DUK_TVAL_IS_OBJECT(tv)) {
22746 duk_hobject *h;
22747 duk_hbufferobject *h_bufobj;
22748
22749 /* Accept any duk_hbufferobject, though we're only normally
22750 * called for Duktape.Buffer values.
22751 */
22752 h = DUK_TVAL_GET_OBJECT(tv);
22753 DUK_ASSERT(h != NULL);
22755 DUK_DD(DUK_DDPRINT("toString/valueOf() called for a non-bufferobject object"));
22756 goto type_error;
22757 }
22758 h_bufobj = (duk_hbufferobject *) h;
22760
22761 if (h_bufobj->buf == NULL) {
22762 DUK_DD(DUK_DDPRINT("toString/valueOf() called for a bufferobject with NULL buf"));
22763 goto type_error;
22764 }
22765 duk_push_hbuffer(ctx, h_bufobj->buf);
22766 } else {
22767 goto type_error;
22768 }
22769
22770 if (to_string) {
22771 duk_to_string(ctx, -1);
22772 }
22773 return 1;
22774
22775 type_error:
22776 return DUK_RET_TYPE_ERROR;
22777}
22778#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22780 DUK_UNREF(ctx);
22782}
22783#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22784
22785/*
22786 * Node.js Buffer.prototype: toJSON()
22787 */
22788
22789#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22791 duk_hthread *thr;
22792 duk_hbufferobject *h_this;
22793 duk_uint8_t *buf;
22794 duk_uint_t i;
22795
22796 thr = (duk_hthread *) ctx;
22797 DUK_UNREF(thr);
22798 h_this = duk__require_bufobj_this(ctx);
22799 DUK_ASSERT(h_this != NULL);
22800
22801 if (h_this->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
22802 /* Serialize uncovered backing buffer as a null; doesn't
22803 * really matter as long we're memory safe.
22804 */
22805 duk_push_null(ctx);
22806 return 1;
22807 }
22808
22809 duk_push_object(ctx);
22812
22813 duk_push_array(ctx);
22814 for (i = 0; i < h_this->length; i++) {
22815 /* XXX: regetting the pointer may be overkill - we're writing
22816 * to a side-effect free array here.
22817 */
22818 DUK_ASSERT(h_this->buf != NULL);
22819 buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
22820 duk_push_uint(ctx, (duk_uint_t) buf[i]);
22821 duk_put_prop_index(ctx, -2, (duk_idx_t) i);
22822 }
22825 return 1;
22826}
22827#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22829 DUK_UNREF(ctx);
22831}
22832#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22833
22834/*
22835 * Node.js Buffer.prototype.equals()
22836 * Node.js Buffer.prototype.compare()
22837 * Node.js Buffer.compare()
22838 */
22839
22840#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22842 duk_hthread *thr;
22843 duk_small_uint_t magic;
22844 duk_hbufferobject *h_bufarg1;
22845 duk_hbufferobject *h_bufarg2;
22846 duk_small_int_t comp_res;
22847
22848 thr = (duk_hthread *) ctx;
22849 DUK_UNREF(thr);
22850
22851 magic = duk_get_current_magic(ctx);
22852 if (magic & 0x02) {
22853 /* Static call style. */
22854 h_bufarg1 = duk__require_bufobj_value(ctx, 0);
22855 h_bufarg2 = duk__require_bufobj_value(ctx, 1);
22856 } else {
22857 h_bufarg1 = duk__require_bufobj_this(ctx);
22858 h_bufarg2 = duk__require_bufobj_value(ctx, 0);
22859 }
22860 DUK_ASSERT(h_bufarg1 != NULL);
22861 DUK_ASSERT(h_bufarg2 != NULL);
22862
22863 /* We want to compare the slice/view areas of the arguments.
22864 * If either slice/view is invalid (underlying buffer is shorter)
22865 * ensure equals() is false, but otherwise the only thing that
22866 * matters is to be memory safe.
22867 */
22868
22869 if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg1) &&
22870 DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg2)) {
22871 comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
22872 (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
22873 (duk_size_t) h_bufarg1->length,
22874 (duk_size_t) h_bufarg2->length);
22875 } else {
22876 comp_res = -1; /* either nonzero value is ok */
22877 }
22878
22879 if (magic & 0x01) {
22880 /* compare: similar to string comparison but for buffer data. */
22881 duk_push_int(ctx, comp_res);
22882 } else {
22883 /* equals */
22884 duk_push_boolean(ctx, (comp_res == 0));
22885 }
22886
22887 return 1;
22888}
22889#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22891 DUK_UNREF(ctx);
22893}
22894#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22895
22896/*
22897 * Node.js Buffer.prototype.fill()
22898 */
22899
22900#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22902 duk_hthread *thr;
22903 duk_hbufferobject *h_this;
22904 const duk_uint8_t *fill_str_ptr;
22905 duk_size_t fill_str_len;
22906 duk_uint8_t fill_value;
22907 duk_int_t fill_offset;
22908 duk_int_t fill_end;
22909 duk_size_t fill_length;
22910 duk_uint8_t *p;
22911
22912 thr = (duk_hthread *) ctx;
22913 DUK_UNREF(thr);
22914
22915 h_this = duk__require_bufobj_this(ctx);
22916 DUK_ASSERT(h_this != NULL);
22917 if (h_this->buf == NULL) {
22918 return DUK_RET_TYPE_ERROR;
22919 }
22920
22921 /* [ value offset end ] */
22922
22923 if (duk_is_string(ctx, 0)) {
22924 fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &fill_str_len);
22925 DUK_ASSERT(fill_str_ptr != NULL);
22926 } else {
22927 fill_value = (duk_uint8_t) duk_to_uint32(ctx, 0);
22928 fill_str_ptr = (const duk_uint8_t *) &fill_value;
22929 fill_str_len = 1;
22930 }
22931
22932 /* Fill offset handling is more lenient than in Node.js. */
22933
22934 duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &fill_offset, &fill_end);
22935
22936 DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
22937 (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
22938
22939 DUK_ASSERT(fill_end - fill_offset >= 0);
22940 DUK_ASSERT(h_this->buf != NULL);
22941
22942 p = (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
22943 fill_length = (duk_size_t) (fill_end - fill_offset);
22944 if (fill_str_len == 1) {
22945 /* Handle single character fills as memset() even when
22946 * the fill data comes from a one-char argument.
22947 */
22948 DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
22949 } else if (fill_str_len > 1) {
22950 duk_size_t i, n, t;
22951
22952 for (i = 0, n = (fill_end - fill_offset), t = 0; i < n; i++) {
22953 p[i] = fill_str_ptr[t++];
22954 if (t >= fill_str_len) {
22955 t = 0;
22956 }
22957 }
22958 } else {
22959 DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
22960 }
22962 /* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
22963 duk_push_this(ctx);
22964 return 1;
22965}
22966#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22968 DUK_UNREF(ctx);
22970}
22971#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22972
22973/*
22974 * Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
22975 */
22976
22977#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22979 duk_hthread *thr;
22980 duk_hbufferobject *h_this;
22981 duk_uint_t offset;
22982 duk_uint_t length;
22983 const duk_uint8_t *str_data;
22985
22986 thr = (duk_hthread *) ctx;
22987 DUK_UNREF(thr);
22988
22989 h_this = duk__require_bufobj_this(ctx);
22990 DUK_ASSERT(h_this != NULL);
22991
22992 /* Argument must be a string, e.g. a buffer is not allowed. */
22993 str_data = (const duk_uint8_t *) duk_require_lstring(ctx, 0, &str_len);
22994
22995 duk__resolve_offset_opt_length(ctx, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
22996 DUK_ASSERT(offset <= h_this->length);
22997 DUK_ASSERT(offset + length <= h_this->length);
22998
22999 /* XXX: encoding is ignored now. */
23000
23001 if (length > str_len) {
23002 length = (duk_uint_t) str_len;
23003 }
23004
23005 if (DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
23006 /* Cannot overlap. */
23007 DUK_MEMCPY((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset),
23008 (const void *) str_data,
23009 (size_t) length);
23010 } else {
23011 DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
23013
23014 duk_push_uint(ctx, length);
23015 return 1;
23016}
23017#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23019 DUK_UNREF(ctx);
23021}
23022#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23023
23024/*
23025 * Node.js Buffer.prototype.copy()
23026 */
23027
23028#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23030 duk_hthread *thr;
23031 duk_hbufferobject *h_this;
23032 duk_hbufferobject *h_bufarg;
23033 duk_int_t source_length;
23034 duk_int_t target_length;
23035 duk_int_t target_start, source_start, source_end;
23036 duk_uint_t target_ustart, source_ustart, source_uend;
23037 duk_uint_t copy_size = 0;
23038
23039 /* [ targetBuffer targetStart sourceStart sourceEnd ] */
23040
23041 thr = (duk_hthread *) ctx;
23042 DUK_UNREF(thr);
23043
23044 h_this = duk__require_bufobj_this(ctx);
23045 h_bufarg = duk__require_bufobj_value(ctx, 0);
23046 DUK_ASSERT(h_this != NULL);
23047 DUK_ASSERT(h_bufarg != NULL);
23048 source_length = (duk_int_t) h_this->length;
23049 target_length = (duk_int_t) h_bufarg->length;
23050
23051 target_start = duk_to_int(ctx, 1);
23052 source_start = duk_to_int(ctx, 2);
23053 if (duk_is_undefined(ctx, 3)) {
23054 source_end = source_length;
23055 } else {
23056 source_end = duk_to_int(ctx, 3);
23057 }
23058
23059 DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
23060 "source_start=%ld, source_end=%ld, source_length=%ld",
23061 (long) target_start, (long) h_bufarg->length,
23062 (long) source_start, (long) source_end, (long) source_length));
23063
23064 /* This behavior mostly mimics Node.js now. */
23065
23066 if (source_start < 0 || source_end < 0 || target_start < 0) {
23067 /* Negative offsets cause a RangeError. */
23068 goto fail_bounds;
23069 }
23070 source_ustart = (duk_uint_t) source_start;
23071 source_uend = (duk_uint_t) source_end;
23072 target_ustart = (duk_uint_t) target_start;
23073 if (source_ustart >= source_uend || /* crossed offsets or zero size */
23074 source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */
23075 target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */
23076 goto silent_ignore;
23077 }
23078 if (source_uend >= (duk_uint_t) source_length) {
23079 /* Source end clamped silently to available length. */
23080 source_uend = source_length;
23081 }
23082 copy_size = source_uend - source_ustart;
23083 if (target_ustart + copy_size > (duk_uint_t) target_length) {
23084 /* Clamp to target's end if too long.
23085 *
23086 * NOTE: there's no overflow possibility in the comparison;
23087 * both target_ustart and copy_size are >= 0 and based on
23088 * values in duk_int_t range. Adding them as duk_uint_t
23089 * values is then guaranteed not to overflow.
23090 */
23091 DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */
23092 DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */
23093 copy_size = (duk_uint_t) target_length - target_ustart;
23094 }
23095
23096 DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
23097 (unsigned long) target_ustart, (unsigned long) source_ustart,
23098 (unsigned long) copy_size));
23099
23100 DUK_ASSERT(copy_size >= 1);
23101 DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
23102 DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
23103 DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
23104 DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
23105
23106 /* Ensure copy is covered by underlying buffers. */
23107 DUK_ASSERT(h_bufarg->buf != NULL); /* length check */
23108 DUK_ASSERT(h_this->buf != NULL); /* length check */
23109 if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
23110 DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
23111 /* Must use memmove() because copy area may overlap (source and target
23112 * buffer may be the same, or from different slices.
23113 */
23114 DUK_MEMMOVE((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
23115 (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
23116 (size_t) copy_size);
23117 } else {
23118 DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
23119 }
23120
23121 silent_ignore:
23122 /* Return value is like write(), number of bytes written.
23123 * The return value matters because of code like:
23124 * "off += buf.copy(...)".
23125 */
23126 duk_push_uint(ctx, copy_size);
23127 return 1;
23128
23129 fail_bounds:
23130 return DUK_RET_RANGE_ERROR;
23131}
23132#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23134 DUK_UNREF(ctx);
23136}
23137#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23138
23139/*
23140 * TypedArray.prototype.set()
23141 *
23142 * TypedArray set() is pretty interesting to implement because:
23143 *
23144 * - The source argument may be a plain array or a typedarray. If the
23145 * source is a TypedArray, values are decoded and re-encoded into the
23146 * target (not as a plain byte copy). This may happen even when the
23147 * element byte size is the same, e.g. integer values may be re-encoded
23148 * into floats.
23149 *
23150 * - Source and target may refer to the same underlying buffer, so that
23151 * the set() operation may overlap. The specification requires that this
23152 * must work as if a copy was made before the operation. Note that this
23153 * is NOT a simple memmove() situation because the source and target
23154 * byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
23155 * expand to a 16-byte target (Uint32Array) so that the target overlaps
23156 * the source both from beginning and the end (unlike in typical memmove).
23157 *
23158 * - Even if 'buf' pointers of the source and target differ, there's no
23159 * guarantee that their memory areas don't overlap. This may be the
23160 * case with external buffers.
23161 *
23162 * Even so, it is nice to optimize for the common case:
23163 *
23164 * - Source and target separate buffers or non-overlapping.
23165 *
23166 * - Source and target have a compatible type so that a plain byte copy
23167 * is possible. Note that while e.g. uint8 and int8 are compatible
23168 * (coercion one way or another doesn't change the byte representation),
23169 * e.g. int8 and uint8clamped are NOT compatible when writing int8
23170 * values into uint8clamped typedarray (-1 would clamp to 0 for instance).
23171 *
23172 * See test-bi-typedarray-proto-set.js.
23173 */
23174
23175#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23177 duk_hthread *thr;
23178 duk_hbufferobject *h_this;
23179 duk_hobject *h_obj;
23180 duk_uarridx_t i, n;
23181 duk_int_t offset_signed;
23182 duk_uint_t offset_elems;
23183 duk_uint_t offset_bytes;
23184
23185 thr = (duk_hthread *) ctx;
23186 DUK_UNREF(thr);
23187
23188 h_this = duk__require_bufobj_this(ctx);
23189 DUK_ASSERT(h_this != NULL);
23191
23192 if (h_this->buf == NULL) {
23193 DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
23194 return 0;
23195 }
23196
23197 h_obj = duk_require_hobject(ctx, 0);
23198 DUK_ASSERT(h_obj != NULL);
23199
23200 /* XXX: V8 throws a TypeError for negative values. Would it
23201 * be more useful to interpret negative offsets here from the
23202 * end of the buffer too?
23203 */
23204 offset_signed = duk_to_int(ctx, 1);
23205 if (offset_signed < 0) {
23206 return DUK_RET_TYPE_ERROR;
23207 }
23208 offset_elems = (duk_uint_t) offset_signed;
23209 offset_bytes = offset_elems << h_this->shift;
23210 if ((offset_bytes >> h_this->shift) != offset_elems) {
23211 /* Byte length would overflow. */
23212 /* XXX: easier check with less code? */
23213 return DUK_RET_RANGE_ERROR;
23214 }
23215 if (offset_bytes > h_this->length) {
23216 /* Equality may be OK but >length not. Checking
23217 * this explicitly avoids some overflow cases
23218 * below.
23219 */
23220 return DUK_RET_RANGE_ERROR;
23221 }
23222 DUK_ASSERT(offset_bytes <= h_this->length);
23223
23224 /* Fast path: source is a TypedArray (or any bufferobject). */
23225
23226 if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
23227 duk_hbufferobject *h_bufarg;
23228 duk_uint16_t comp_mask;
23229 duk_small_int_t no_overlap = 0;
23230 duk_uint_t src_length;
23231 duk_uint_t dst_length;
23232 duk_uint_t dst_length_elems;
23233 duk_uint8_t *p_src_base;
23234 duk_uint8_t *p_src_end;
23235 duk_uint8_t *p_src;
23236 duk_uint8_t *p_dst_base;
23237 duk_uint8_t *p_dst;
23238 duk_small_uint_t src_elem_size;
23239 duk_small_uint_t dst_elem_size;
23240
23241 h_bufarg = (duk_hbufferobject *) h_obj;
23243
23244 if (h_bufarg->buf == NULL) {
23245 DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
23246 return 0;
23247 }
23248
23249 /* Nominal size check. */
23250 src_length = h_bufarg->length; /* bytes in source */
23251 dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */
23252 dst_length = dst_length_elems << h_this->shift; /* bytes in dest */
23253 if ((dst_length >> h_this->shift) != dst_length_elems) {
23254 /* Byte length would overflow. */
23255 /* XXX: easier check with less code? */
23256 return DUK_RET_RANGE_ERROR;
23257 }
23258 DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
23259 (long) src_length, (long) dst_length));
23260 DUK_ASSERT(offset_bytes <= h_this->length);
23261 if (dst_length > h_this->length - offset_bytes) {
23262 /* Overflow not an issue because subtraction is used on the right
23263 * side and guaranteed to be >= 0.
23264 */
23265 DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
23266 return DUK_RET_RANGE_ERROR;
23267 }
23268 if (!DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
23269 DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
23270 return 0;
23271 }
23272
23273 p_src_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
23274 p_dst_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
23275
23276 /* Check actual underlying buffers for validity and that they
23277 * cover the copy. No side effects are allowed after the check
23278 * so that the validity status doesn't change.
23279 */
23280 if (!DUK_HBUFFEROBJECT_VALID_SLICE(h_this) ||
23281 !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
23282 /* The condition could be more narrow and check for the
23283 * copy area only, but there's no need for fine grained
23284 * behavior when the underlying buffer is misconfigured.
23285 */
23286 DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
23287 return 0;
23288 }
23289
23290 /* We want to do a straight memory copy if possible: this is
23291 * an important operation because .set() is the TypedArray
23292 * way to copy chunks of memory. However, because set()
23293 * conceptually works in terms of elements, not all views are
23294 * compatible with direct byte copying.
23295 *
23296 * If we do manage a direct copy, the "overlap issue" handled
23297 * below can just be solved using memmove() because the source
23298 * and destination element sizes are necessarily equal.
23299 */
23300
23301 DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
23303 if (comp_mask & (1 << h_bufarg->elem_type)) {
23304 DUK_ASSERT(src_length == dst_length);
23305
23306 DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
23307 DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
23308 return 0;
23309 }
23310 DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
23311
23312 /* We want to avoid making a copy to process set() but that's
23313 * not always possible: the source and the target may overlap
23314 * and because element sizes are different, the overlap cannot
23315 * always be handled with a memmove() or choosing the copy
23316 * direction in a certain way. For example, if source type is
23317 * uint8 and target type is uint32, the target area may exceed
23318 * the source area from both ends!
23319 *
23320 * Note that because external buffers may point to the same
23321 * memory areas, we must ultimately make this check using
23322 * pointers.
23323 *
23324 * NOTE: careful with side effects: any side effect may cause
23325 * a buffer resize (or external buffer pointer/length update)!
23326 */
23327
23328 DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
23329 "p_dst_base=%p, dst_length=%ld",
23330 (void *) p_src_base, (long) src_length,
23331 (void *) p_dst_base, (long) dst_length));
23332
23333 if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */
23334 p_src_base + src_length <= p_dst_base) { /* source ends before dest starts */
23335 no_overlap = 1;
23336 }
23337
23338 if (!no_overlap) {
23339 /* There's overlap: the desired end result is that
23340 * conceptually a copy is made to avoid "trampling"
23341 * of source data by destination writes. We make
23342 * an actual temporary copy to handle this case.
23343 */
23344 duk_uint8_t *p_src_copy;
23345
23346 DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
23347 p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_length);
23348 DUK_ASSERT(p_src_copy != NULL);
23349 DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
23350
23351 p_src_base = p_src_copy; /* use p_src_base from now on */
23352 }
23353 /* Value stack intentionally mixed size here. */
23354
23355 DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
23356 "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
23357 (void *) p_src_base, (long) src_length,
23358 (void *) p_dst_base, (long) dst_length,
23359 (long) duk_get_top(ctx)));
23360
23361 /* Ready to make the copy. We must proceed element by element
23362 * and must avoid any side effects that might cause the buffer
23363 * validity check above to become invalid.
23364 *
23365 * Although we work through the value stack here, only plain
23366 * numbers are handled which should be side effect safe.
23367 */
23368
23369 src_elem_size = 1 << h_bufarg->shift;
23370 dst_elem_size = 1 << h_this->shift;
23371 p_src = p_src_base;
23372 p_dst = p_dst_base;
23373 p_src_end = p_src_base + src_length;
23374
23375 while (p_src != p_src_end) {
23376 DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
23377 "p_src=%p, p_src_end=%p, p_dst=%p",
23378 (void *) p_src, (void *) p_src_end, (void *) p_dst));
23379 /* A validated read() is always a number, so it's write coercion
23380 * is always side effect free an won't invalidate pointers etc.
23381 */
23382 duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
23383 duk_hbufferobject_validated_write(ctx, h_this, p_dst, dst_elem_size);
23384 duk_pop(ctx);
23385 p_src += src_elem_size;
23386 p_dst += dst_elem_size;
23387 }
23388
23389 return 0;
23390 } else {
23391 /* Slow path: quite slow, but we save space by using the property code
23392 * to write coerce target values. We don't need to worry about overlap
23393 * here because the source is not a TypedArray.
23394 *
23395 * We could use the bufferobject write coercion helper but since the
23396 * property read may have arbitrary side effects, full validity checks
23397 * would be needed for every element anyway.
23398 */
23399
23400 n = (duk_uarridx_t) duk_get_length(ctx, 0);
23401 DUK_ASSERT(offset_bytes <= h_this->length);
23402 if ((n << h_this->shift) > h_this->length - offset_bytes) {
23403 /* Overflow not an issue because subtraction is used on the right
23404 * side and guaranteed to be >= 0.
23405 */
23406 DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
23407 return DUK_RET_RANGE_ERROR;
23408 }
23409
23410 /* There's no need to check for buffer validity status for the
23411 * target here: the property access code will do that for each
23412 * element. Moreover, if we did check the validity here, side
23413 * effects from reading the source argument might invalidate
23414 * the results anyway.
23415 */
23416
23417 DUK_ASSERT_TOP(ctx, 2);
23418 duk_push_this(ctx);
23419
23420 for (i = 0; i < n; i++) {
23421 duk_get_prop_index(ctx, 0, i);
23422 duk_put_prop_index(ctx, 2, offset_elems + i);
23423 }
23424 }
23425
23426 return 0;
23427}
23428#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23430 DUK_UNREF(ctx);
23432}
23433#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23434
23435/*
23436 * Node.js Buffer.prototype.slice([start], [end])
23437 * ArrayBuffer.prototype.slice(begin, [end])
23438 * TypedArray.prototype.slice(begin, [end])
23439 *
23440 * The API calls are almost identical; negative indices are counted from end
23441 * of buffer, and final indices are clamped (allowing crossed indices). Main
23442 * differences:
23443 *
23444 * - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
23445 * views, ArrayBuffer .slice() creates a copy
23446 *
23447 * - Resulting object has a different class and prototype depending on the
23448 * call (or 'this' argument)
23449 *
23450 * - TypedArray .subarray() arguments are element indices, not byte offsets
23451 */
23452
23453#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23455 duk_hthread *thr;
23456 duk_small_int_t magic;
23457 duk_small_uint_t res_class_num;
23458 duk_hobject *res_proto;
23459 duk_hbufferobject *h_this;
23460 duk_hbufferobject *h_bufobj;
23461 duk_hbuffer *h_val;
23462 duk_int_t start_offset, end_offset;
23463 duk_uint_t slice_length;
23464
23465 thr = (duk_hthread *) ctx;
23466 DUK_UNREF(thr);
23467
23468 /* [ start end ] */
23469
23470 magic = duk_get_current_magic(ctx);
23471 h_this = duk__require_bufobj_this(ctx);
23472
23473 /* Slice offsets are element (not byte) offsets, which only matters
23474 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
23475 * zero so byte and element offsets are the same. Negative indices
23476 * are counted from end of slice, crossed indices are allowed (and
23477 * result in zero length result), and final values are clamped
23478 * against the current slice. There's intentionally no check
23479 * against the underlying buffer here.
23480 */
23481
23482 duk__clamp_startend_negidx_shifted(ctx, h_this, 0 /*idx_start*/, 1 /*idx_end*/, &start_offset, &end_offset);
23483 DUK_ASSERT(end_offset >= start_offset);
23484 slice_length = (duk_uint_t) (end_offset - start_offset);
23485
23486 /* The resulting buffer object gets the same class and prototype as
23487 * the buffer in 'this', e.g. if the input is a Node.js Buffer the
23488 * result is a Node.js Buffer; if the input is a Float32Array, the
23489 * result is a Float32Array.
23490 *
23491 * For the class number this seems correct. The internal prototype
23492 * is not so clear: if 'this' is a bufferobject with a non-standard
23493 * prototype object, that value gets copied over into the result
23494 * (instead of using the standard prototype for that object type).
23495 */
23496
23497 res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
23498 h_bufobj = duk_push_bufferobject_raw(ctx,
23501 DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
23502 DUK_BIDX_OBJECT_PROTOTYPE); /* replaced */
23503 DUK_ASSERT(h_bufobj != NULL);
23504 res_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_this); /* may be NULL */
23505 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_bufobj, res_proto);
23506
23507 h_bufobj->length = slice_length;
23508 h_bufobj->shift = h_this->shift; /* inherit */
23509 h_bufobj->elem_type = h_this->elem_type; /* inherit */
23510 h_bufobj->is_view = magic & 0x01;
23511 DUK_ASSERT(h_bufobj->is_view == 0 || h_bufobj->is_view == 1);
23512
23513 h_val = h_this->buf;
23514 if (h_val == NULL) {
23515 return DUK_RET_TYPE_ERROR;
23516 }
23517
23518 if (magic & 0x02) {
23519 /* non-zero: make copy */
23520 duk_uint8_t *p_copy;
23521 duk_size_t copy_length;
23522
23523 p_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) slice_length);
23524 DUK_ASSERT(p_copy != NULL);
23525
23526 /* Copy slice, respecting underlying buffer limits; remainder
23527 * is left as zero.
23528 */
23529 copy_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, slice_length);
23530 DUK_MEMCPY((void *) p_copy,
23531 (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
23532 copy_length);
23533
23534 h_val = duk_get_hbuffer(ctx, -1);
23535 DUK_ASSERT(h_val != NULL);
23536
23537 h_bufobj->buf = h_val;
23538 DUK_HBUFFER_INCREF(thr, h_val);
23539 DUK_ASSERT(h_bufobj->offset == 0);
23540
23541 duk_pop(ctx); /* reachable so pop OK */
23542 } else {
23543 h_bufobj->buf = h_val;
23544 DUK_HBUFFER_INCREF(thr, h_val);
23545 h_bufobj->offset = (duk_uint_t) (h_this->offset + start_offset);
23546
23547 /* Copy the .buffer property, needed for TypedArray.prototype.subarray().
23548 *
23549 * XXX: limit copy only for TypedArray classes specifically?
23550 */
23551
23552 duk_push_this(ctx);
23555 duk_pop(ctx);
23556 } else {
23557 duk_pop_2(ctx);
23558 }
23559 }
23560 /* unbalanced stack on purpose */
23561
23563 return 1;
23564}
23565#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23567 DUK_UNREF(ctx);
23569}
23570#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23571
23572/*
23573 * Node.js Buffer.isEncoding()
23574 */
23575
23576#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23578 const char *encoding;
23579
23580 /* only accept lowercase 'utf8' now. */
23581
23582 encoding = duk_to_string(ctx, 0);
23583 DUK_ASSERT(duk_is_string(ctx, 0)); /* guaranteed by duk_to_string() */
23584 duk_push_boolean(ctx, DUK_STRCMP(encoding, "utf8") == 0);
23585 return 1;
23586}
23587#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23589 DUK_UNREF(ctx);
23591}
23592#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23593
23594/*
23595 * Node.js Buffer.isBuffer()
23596 */
23597
23598#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23600 duk_hthread *thr;
23601 duk_tval *tv;
23602 duk_hobject *h;
23603 duk_hobject *h_proto;
23604 duk_bool_t ret = 0;
23605
23606 thr = (duk_hthread *) ctx;
23607
23608 DUK_ASSERT(duk_get_top(ctx) >= 1); /* nargs */
23609 tv = duk_get_tval(ctx, 0);
23610 DUK_ASSERT(tv != NULL);
23611
23612 if (DUK_TVAL_IS_OBJECT(tv)) {
23613 h = DUK_TVAL_GET_OBJECT(tv);
23614 DUK_ASSERT(h != NULL);
23615
23617 DUK_ASSERT(h_proto != NULL);
23618
23619 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
23620 if (h) {
23621 ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
23622 }
23624
23625 duk_push_boolean(ctx, ret);
23626 return 1;
23627}
23628#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23630 DUK_UNREF(ctx);
23632}
23633#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23634
23635/*
23636 * Node.js Buffer.byteLength()
23637 */
23638
23639#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23641 const char *str;
23642 duk_size_t len;
23643
23644 /* At the moment Buffer(<str>) will just use the string bytes as
23645 * is (ignoring encoding), so we return the string length here
23646 * unconditionally.
23647 */
23648
23649 str = duk_to_lstring(ctx, 0, &len);
23650 DUK_UNREF(str);
23651 duk_push_size_t(ctx, len);
23652 return 1;
23653}
23654#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23656 DUK_UNREF(ctx);
23658}
23659#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23660
23661/*
23662 * Node.js Buffer.concat()
23663 */
23664
23665#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23667 duk_hthread *thr;
23668 duk_hobject *h_arg;
23669 duk_int_t total_length = 0;
23670 duk_hbufferobject *h_bufobj;
23671 duk_hbufferobject *h_bufres;
23672 duk_hbuffer *h_val;
23673 duk_uint_t i, n;
23674 duk_uint8_t *p;
23675 duk_size_t space_left;
23676 duk_size_t copy_size;
23677
23678 thr = (duk_hthread *) ctx;
23679 DUK_UNREF(thr);
23680
23681 /* Node.js accepts only actual Arrays. */
23682 h_arg = duk_require_hobject(ctx, 0);
23684 return DUK_RET_TYPE_ERROR;
23685 }
23686
23687 /* Compute result length and validate argument buffers. */
23688 n = (duk_uint_t) duk_get_length(ctx, 0);
23689 for (i = 0; i < n; i++) {
23690 /* Neutered checks not necessary here: neutered buffers have
23691 * zero 'length' so we'll effectively skip them.
23692 */
23693 DUK_ASSERT_TOP(ctx, 2); /* [ array totalLength ] */
23694 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */
23695 h_bufobj = duk__require_bufobj_value(ctx, 2);
23696 DUK_ASSERT(h_bufobj != NULL);
23697 total_length += h_bufobj->length;
23698 duk_pop(ctx);
23699 }
23700 if (n == 1) {
23701 /* For the case n==1 Node.js doesn't seem to type check
23702 * the sole member but we do it before returning it.
23703 * For this case only the original buffer object is
23704 * returned (not a copy).
23705 */
23706 duk_get_prop_index(ctx, 0, 0);
23707 return 1;
23708 }
23709
23710 /* User totalLength overrides a computed length, but we'll check
23711 * every copy in the copy loop. Note that duk_to_uint() can
23712 * technically have arbitrary side effects so we need to recheck
23713 * the buffers in the copy loop.
23714 */
23715 if (!duk_is_undefined(ctx, 1) && n > 0) {
23716 /* For n == 0, Node.js ignores totalLength argument and
23717 * returns a zero length buffer.
23718 */
23719 total_length = duk_to_int(ctx, 1);
23720 }
23721 if (total_length < 0) {
23722 return DUK_RET_RANGE_ERROR;
23723 }
23724
23725 h_bufres = duk_push_bufferobject_raw(ctx,
23730 DUK_ASSERT(h_bufres != NULL);
23731
23732 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, total_length);
23733 DUK_ASSERT(p != NULL);
23734 space_left = total_length;
23735
23736 for (i = 0; i < n; i++) {
23737 DUK_ASSERT_TOP(ctx, 4); /* [ array totalLength bufres buf ] */
23738
23739 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
23740 h_bufobj = duk__require_bufobj_value(ctx, 4);
23741 DUK_ASSERT(h_bufobj != NULL);
23742
23743 copy_size = h_bufobj->length;
23744 if (copy_size > space_left) {
23745 copy_size = space_left;
23746 }
23747
23748 if (h_bufobj->buf != NULL &&
23750 DUK_MEMCPY((void *) p,
23751 (const void *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj),
23752 copy_size);
23753 } else {
23754 /* Just skip, leaving zeroes in the result. */
23755 ;
23756 }
23757 p += copy_size;
23758 space_left -= copy_size;
23759
23760 duk_pop(ctx);
23761 }
23762
23763 h_val = duk_get_hbuffer(ctx, -1);
23764 DUK_ASSERT(h_val != NULL);
23765
23766 duk__set_bufobj_buffer(ctx, h_bufres, h_val);
23768
23769 duk_pop(ctx); /* pop plain buffer, now reachable through h_bufres */
23770
23771 return 1; /* return h_bufres */
23772}
23773#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23775 DUK_UNREF(ctx);
23778#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23781 * Shared readfield and writefield methods
23783 * The readfield/writefield methods need support for endianness and field
23784 * types. All offsets are byte based so no offset shifting is needed.
23786
23787#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23788/* Format of magic, bits:
23789 * 0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
23790 * 3: endianness: 0=little, 1=big
23791 * 4: signed: 1=yes, 0=no
23792 * 5: typedarray: 1=yes, 0=no
23793 */
23794#define DUK__FLD_8BIT 0
23795#define DUK__FLD_16BIT 1
23796#define DUK__FLD_32BIT 2
23797#define DUK__FLD_FLOAT 3
23798#define DUK__FLD_DOUBLE 4
23799#define DUK__FLD_VARINT 5
23800#define DUK__FLD_BIGENDIAN (1 << 3)
23801#define DUK__FLD_SIGNED (1 << 4)
23802#define DUK__FLD_TYPEDARRAY (1 << 5)
23803
23804/* XXX: split into separate functions for each field type? */
23806 duk_hthread *thr;
23808 duk_small_int_t magic_ftype;
23809 duk_small_int_t magic_bigendian;
23810 duk_small_int_t magic_signed;
23811 duk_small_int_t magic_typedarray;
23812 duk_small_int_t endswap;
23813 duk_hbufferobject *h_this;
23814 duk_bool_t no_assert;
23815 duk_int_t offset_signed;
23816 duk_uint_t offset;
23817 duk_uint_t buffer_length;
23818 duk_uint_t check_length;
23819 duk_uint8_t *buf;
23821
23822 thr = (duk_hthread *) ctx;
23823 DUK_UNREF(thr);
23824
23825 magic_ftype = magic & 0x0007;
23826 magic_bigendian = magic & 0x0008;
23827 magic_signed = magic & 0x0010;
23828 magic_typedarray = magic & 0x0020;
23829
23830 h_this = duk__require_bufobj_this(ctx);
23831 DUK_ASSERT(h_this != NULL);
23832 buffer_length = h_this->length;
23833
23834 /* [ offset noAssert ], when ftype != DUK__FLD_VARINT */
23835 /* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
23836 /* [ offset littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
23837
23838 /* Handle TypedArray vs. Node.js Buffer arg differences */
23839 if (magic_typedarray) {
23840 no_assert = 0;
23841#if defined(DUK_USE_INTEGER_LE)
23842 endswap = !duk_to_boolean(ctx, 1); /* 1=little endian */
23843#else
23844 endswap = duk_to_boolean(ctx, 1); /* 1=little endian */
23845#endif
23846 } else {
23847 no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
23848#if defined(DUK_USE_INTEGER_LE)
23849 endswap = magic_bigendian;
23850#else
23851 endswap = !magic_bigendian;
23852#endif
23853 }
23854
23855 /* Offset is coerced first to signed integer range and then to unsigned.
23856 * This ensures we can add a small byte length (1-8) to the offset in
23857 * bound checks and not wrap.
23858 */
23859 offset_signed = duk_to_int(ctx, 0);
23860 offset = (duk_uint_t) offset_signed;
23861 if (offset_signed < 0) {
23862 goto fail_bounds;
23863 }
23864
23865 DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
23866 "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
23867 "endswap=%d",
23868 (long) buffer_length, (long) offset, (int) no_assert,
23869 (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
23870 (int) (magic_signed >> 4), (int) endswap));
23871
23872 /* Update 'buffer_length' to be the effective, safe limit which
23873 * takes into account the underlying buffer. This value will be
23874 * potentially invalidated by any side effect.
23875 */
23876 check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
23877 DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
23878 (long) buffer_length, (long) check_length));
23879
23880 if (h_this->buf) {
23881 buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
23882 } else {
23883 /* Neutered. We could go into the switch-case safely with
23884 * buf == NULL because check_length == 0. To avoid scanbuild
23885 * warnings, fail directly instead.
23886 */
23887 DUK_ASSERT(check_length == 0);
23888 goto fail_neutered;
23889 }
23890 DUK_ASSERT(buf != NULL);
23891
23892 switch (magic_ftype) {
23893 case DUK__FLD_8BIT: {
23894 duk_uint8_t tmp;
23895 if (offset + 1U > check_length) {
23896 goto fail_bounds;
23897 }
23898 tmp = buf[offset];
23899 if (magic_signed) {
23900 duk_push_int(ctx, (duk_int_t) ((duk_int8_t) tmp));
23901 } else {
23902 duk_push_uint(ctx, (duk_uint_t) tmp);
23903 }
23904 break;
23905 }
23906 case DUK__FLD_16BIT: {
23907 duk_uint16_t tmp;
23908 if (offset + 2U > check_length) {
23909 goto fail_bounds;
23910 }
23911 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2);
23912 tmp = du.us[0];
23913 if (endswap) {
23914 tmp = DUK_BSWAP16(tmp);
23915 }
23916 if (magic_signed) {
23917 duk_push_int(ctx, (duk_int_t) ((duk_int16_t) tmp));
23918 } else {
23919 duk_push_uint(ctx, (duk_uint_t) tmp);
23920 }
23921 break;
23922 }
23923 case DUK__FLD_32BIT: {
23924 duk_uint32_t tmp;
23925 if (offset + 4U > check_length) {
23926 goto fail_bounds;
23927 }
23928 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
23929 tmp = du.ui[0];
23930 if (endswap) {
23931 tmp = DUK_BSWAP32(tmp);
23932 }
23933 if (magic_signed) {
23934 duk_push_int(ctx, (duk_int_t) ((duk_int32_t) tmp));
23935 } else {
23936 duk_push_uint(ctx, (duk_uint_t) tmp);
23937 }
23938 break;
23939 }
23940 case DUK__FLD_FLOAT: {
23941 duk_uint32_t tmp;
23942 if (offset + 4U > check_length) {
23943 goto fail_bounds;
23944 }
23945 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
23946 if (endswap) {
23947 tmp = du.ui[0];
23948 tmp = DUK_BSWAP32(tmp);
23949 du.ui[0] = tmp;
23950 }
23951 duk_push_number(ctx, (duk_double_t) du.f[0]);
23952 break;
23953 }
23954 case DUK__FLD_DOUBLE: {
23955 if (offset + 8U > check_length) {
23956 goto fail_bounds;
23957 }
23958 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8);
23959 if (endswap) {
23961 }
23962 duk_push_number(ctx, (duk_double_t) du.d);
23963 break;
23964 }
23965 case DUK__FLD_VARINT: {
23966 /* Node.js Buffer variable width integer field. We don't really
23967 * care about speed here, so aim for shortest algorithm.
23968 */
23969 duk_int_t field_bytelen;
23970 duk_int_t i, i_step, i_end;
23971#if defined(DUK_USE_64BIT_OPS)
23972 duk_int64_t tmp;
23973 duk_small_uint_t shift_tmp;
23974#else
23975 duk_double_t tmp;
23976 duk_small_int_t highbyte;
23977#endif
23978 const duk_uint8_t *p;
23979
23980 field_bytelen = duk_get_int(ctx, 1); /* avoid side effects! */
23981 if (field_bytelen < 1 || field_bytelen > 6) {
23982 goto fail_field_length;
23983 }
23984 if (offset + (duk_uint_t) field_bytelen > check_length) {
23985 goto fail_bounds;
23986 }
23987 p = (const duk_uint8_t *) (buf + offset);
23988
23989 /* Slow gathering of value using either 64-bit arithmetic
23990 * or IEEE doubles if 64-bit types not available. Handling
23991 * of negative numbers is a bit non-obvious in both cases.
23992 */
23993
23994 if (magic_bigendian) {
23995 /* Gather in big endian */
23996 i = 0;
23997 i_step = 1;
23998 i_end = field_bytelen; /* one i_step over */
23999 } else {
24000 /* Gather in little endian */
24001 i = field_bytelen - 1;
24002 i_step = -1;
24003 i_end = -1; /* one i_step over */
24004 }
24005
24006#if defined(DUK_USE_64BIT_OPS)
24007 tmp = 0;
24008 do {
24009 DUK_ASSERT(i >= 0 && i < field_bytelen);
24010 tmp = (tmp << 8) + (duk_int64_t) p[i];
24011 i += i_step;
24012 } while (i != i_end);
24013
24014 if (magic_signed) {
24015 /* Shift to sign extend. */
24016 shift_tmp = 64 - (field_bytelen * 8);
24017 tmp = (tmp << shift_tmp) >> shift_tmp;
24018 }
24019
24020 duk_push_i64(ctx, tmp);
24021#else
24022 highbyte = p[i];
24023 if (magic_signed && (highbyte & 0x80) != 0) {
24024 /* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
24025 tmp = (duk_double_t) (highbyte - 256);
24026 } else {
24027 tmp = (duk_double_t) highbyte;
24028 }
24029 for (;;) {
24030 i += i_step;
24031 if (i == i_end) {
24032 break;
24033 }
24034 DUK_ASSERT(i >= 0 && i < field_bytelen);
24035 tmp = (tmp * 256.0) + (duk_double_t) p[i];
24036 }
24037
24038 duk_push_number(ctx, tmp);
24039#endif
24040 break;
24041 }
24042 default: { /* should never happen but default here */
24043 goto fail_bounds;
24044 }
24045 }
24046
24047 return 1;
24048
24049 fail_neutered:
24050 fail_field_length:
24051 fail_bounds:
24052 if (no_assert) {
24053 /* Node.js return value for noAssert out-of-bounds reads is
24054 * usually (but not always) NaN. Return NaN consistently.
24055 */
24056 duk_push_nan(ctx);
24057 return 1;
24058 }
24059
24060 return DUK_RET_RANGE_ERROR;
24061}
24062#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
24064 DUK_UNREF(ctx);
24066}
24067#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24068
24069#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24070/* XXX: split into separate functions for each field type? */
24072 duk_hthread *thr;
24074 duk_small_int_t magic_ftype;
24075 duk_small_int_t magic_bigendian;
24076 duk_small_int_t magic_signed;
24077 duk_small_int_t magic_typedarray;
24078 duk_small_int_t endswap;
24079 duk_hbufferobject *h_this;
24080 duk_bool_t no_assert;
24081 duk_int_t offset_signed;
24082 duk_uint_t offset;
24083 duk_uint_t buffer_length;
24084 duk_uint_t check_length;
24085 duk_uint8_t *buf;
24087 duk_int_t nbytes = 0;
24088
24089 thr = (duk_hthread *) ctx;
24090 DUK_UNREF(thr);
24091
24092 magic_ftype = magic & 0x0007;
24093 magic_bigendian = magic & 0x0008;
24094 magic_signed = magic & 0x0010;
24095 magic_typedarray = magic & 0x0020;
24096 DUK_UNREF(magic_signed);
24097
24098 h_this = duk__require_bufobj_this(ctx);
24099 DUK_ASSERT(h_this != NULL);
24100 buffer_length = h_this->length;
24101
24102 /* [ value offset noAssert ], when ftype != DUK__FLD_VARINT */
24103 /* [ value offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
24104 /* [ offset value littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
24105
24106 /* Handle TypedArray vs. Node.js Buffer arg differences */
24107 if (magic_typedarray) {
24108 no_assert = 0;
24109#if defined(DUK_USE_INTEGER_LE)
24110 endswap = !duk_to_boolean(ctx, 2); /* 1=little endian */
24111#else
24112 endswap = duk_to_boolean(ctx, 2); /* 1=little endian */
24113#endif
24114 duk_swap(ctx, 0, 1); /* offset/value order different from Node.js */
24115 } else {
24116 no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
24117#if defined(DUK_USE_INTEGER_LE)
24118 endswap = magic_bigendian;
24119#else
24120 endswap = !magic_bigendian;
24121#endif
24122 }
24123
24124 /* Offset is coerced first to signed integer range and then to unsigned.
24125 * This ensures we can add a small byte length (1-8) to the offset in
24126 * bound checks and not wrap.
24127 */
24128 offset_signed = duk_to_int(ctx, 1);
24129 offset = (duk_uint_t) offset_signed;
24130
24131 /* We need 'nbytes' even for a failed offset; return value must be
24132 * (offset + nbytes) even when write fails due to invalid offset.
24133 */
24134 if (magic_ftype != DUK__FLD_VARINT) {
24135 DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
24136 nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
24137 } else {
24138 nbytes = duk_get_int(ctx, 2);
24139 if (nbytes < 1 || nbytes > 6) {
24140 goto fail_field_length;
24141 }
24142 }
24143 DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
24144
24145 /* Now we can check offset validity. */
24146 if (offset_signed < 0) {
24147 goto fail_bounds;
24148 }
24149
24150 DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
24151 "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
24152 "endswap=%d",
24153 duk_get_tval(ctx, 0), (long) buffer_length, (long) offset, (int) no_assert,
24154 (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
24155 (int) (magic_signed >> 4), (int) endswap));
24156
24157 /* Coerce value to a number before computing check_length, so that
24158 * the field type specific coercion below can't have side effects
24159 * that would invalidate check_length.
24160 */
24161 duk_to_number(ctx, 0);
24162
24163 /* Update 'buffer_length' to be the effective, safe limit which
24164 * takes into account the underlying buffer. This value will be
24165 * potentially invalidated by any side effect.
24166 */
24167 check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
24168 DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
24169 (long) buffer_length, (long) check_length));
24170
24171 if (h_this->buf) {
24172 buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
24173 } else {
24174 /* Neutered. We could go into the switch-case safely with
24175 * buf == NULL because check_length == 0. To avoid scanbuild
24176 * warnings, fail directly instead.
24177 */
24178 DUK_ASSERT(check_length == 0);
24179 goto fail_neutered;
24180 }
24181 DUK_ASSERT(buf != NULL);
24182
24183 switch (magic_ftype) {
24184 case DUK__FLD_8BIT: {
24185 if (offset + 1U > check_length) {
24186 goto fail_bounds;
24187 }
24188 /* sign doesn't matter when writing */
24189 buf[offset] = (duk_uint8_t) duk_to_uint32(ctx, 0);
24190 break;
24191 }
24192 case DUK__FLD_16BIT: {
24193 duk_uint16_t tmp;
24194 if (offset + 2U > check_length) {
24195 goto fail_bounds;
24196 }
24197 tmp = (duk_uint16_t) duk_to_uint32(ctx, 0);
24198 if (endswap) {
24199 tmp = DUK_BSWAP16(tmp);
24200 }
24201 du.us[0] = tmp;
24202 /* sign doesn't matter when writing */
24203 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2);
24204 break;
24205 }
24206 case DUK__FLD_32BIT: {
24207 duk_uint32_t tmp;
24208 if (offset + 4U > check_length) {
24209 goto fail_bounds;
24210 }
24211 tmp = (duk_uint32_t) duk_to_uint32(ctx, 0);
24212 if (endswap) {
24213 tmp = DUK_BSWAP32(tmp);
24214 }
24215 du.ui[0] = tmp;
24216 /* sign doesn't matter when writing */
24217 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
24218 break;
24219 }
24220 case DUK__FLD_FLOAT: {
24221 duk_uint32_t tmp;
24222 if (offset + 4U > check_length) {
24223 goto fail_bounds;
24224 }
24225 du.f[0] = (duk_float_t) duk_to_number(ctx, 0);
24226 if (endswap) {
24227 tmp = du.ui[0];
24228 tmp = DUK_BSWAP32(tmp);
24229 du.ui[0] = tmp;
24230 }
24231 /* sign doesn't matter when writing */
24232 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
24233 break;
24234 }
24235 case DUK__FLD_DOUBLE: {
24236 if (offset + 8U > check_length) {
24237 goto fail_bounds;
24238 }
24239 du.d = (duk_double_t) duk_to_number(ctx, 0);
24240 if (endswap) {
24242 }
24243 /* sign doesn't matter when writing */
24244 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8);
24245 break;
24246 }
24247 case DUK__FLD_VARINT: {
24248 /* Node.js Buffer variable width integer field. We don't really
24249 * care about speed here, so aim for shortest algorithm.
24250 */
24251 duk_int_t field_bytelen;
24252 duk_int_t i, i_step, i_end;
24253#if defined(DUK_USE_64BIT_OPS)
24254 duk_int64_t tmp;
24255#else
24256 duk_double_t tmp;
24257#endif
24258 duk_uint8_t *p;
24259
24260 field_bytelen = (duk_int_t) nbytes;
24261 if (offset + (duk_uint_t) field_bytelen > check_length) {
24262 goto fail_bounds;
24263 }
24264
24265 /* Slow writing of value using either 64-bit arithmetic
24266 * or IEEE doubles if 64-bit types not available. There's
24267 * no special sign handling when writing varints.
24268 */
24269
24270 if (magic_bigendian) {
24271 /* Write in big endian */
24272 i = field_bytelen; /* one i_step added at top of loop */
24273 i_step = -1;
24274 i_end = 0;
24275 } else {
24276 /* Write in little endian */
24277 i = -1; /* one i_step added at top of loop */
24278 i_step = 1;
24279 i_end = field_bytelen - 1;
24280 }
24281
24282 /* XXX: The duk_to_number() cast followed by integer coercion
24283 * is platform specific so NaN, +/- Infinity, and out-of-bounds
24284 * values result in platform specific output now.
24285 * See: test-bi-nodejs-buffer-proto-varint-special.js
24286 */
24287
24288#if defined(DUK_USE_64BIT_OPS)
24289 tmp = (duk_int64_t) duk_to_number(ctx, 0);
24290 p = (duk_uint8_t *) (buf + offset);
24291 do {
24292 i += i_step;
24293 DUK_ASSERT(i >= 0 && i < field_bytelen);
24294 p[i] = (duk_uint8_t) (tmp & 0xff);
24295 tmp = tmp >> 8; /* unnecessary shift for last byte */
24296 } while (i != i_end);
24297#else
24298 tmp = duk_to_number(ctx, 0);
24299 p = (duk_uint8_t *) (buf + offset);
24300 do {
24301 i += i_step;
24302 tmp = DUK_FLOOR(tmp);
24303 DUK_ASSERT(i >= 0 && i < field_bytelen);
24304 p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
24305 tmp = tmp / 256.0; /* unnecessary div for last byte */
24306 } while (i != i_end);
24307#endif
24308 break;
24309 }
24310 default: { /* should never happen but default here */
24311 goto fail_bounds;
24312 }
24313 }
24314
24315 /* Node.js Buffer: return offset + #bytes written (i.e. next
24316 * write offset).
24317 */
24318 if (magic_typedarray) {
24319 /* For TypedArrays 'undefined' return value is specified
24320 * by ES6 (matches V8).
24321 */
24322 return 0;
24323 }
24324 duk_push_uint(ctx, offset + nbytes);
24325 return 1;
24326
24327 fail_neutered:
24328 fail_field_length:
24329 fail_bounds:
24330 if (no_assert) {
24331 /* Node.js return value for failed writes is offset + #bytes
24332 * that would have been written.
24333 */
24334 /* XXX: for negative input offsets, 'offset' will be a large
24335 * positive value so the result here is confusing.
24336 */
24337 if (magic_typedarray) {
24338 return 0;
24339 }
24340 duk_push_uint(ctx, offset + nbytes);
24341 return 1;
24342 }
24343 return DUK_RET_RANGE_ERROR;
24344}
24345#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
24347 DUK_UNREF(ctx);
24349}
24350#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24351
24352#undef DUK__FLD_8BIT
24353#undef DUK__FLD_16BIT
24354#undef DUK__FLD_32BIT
24355#undef DUK__FLD_FLOAT
24356#undef DUK__FLD_DOUBLE
24357#undef DUK__FLD_VARINT
24358#undef DUK__FLD_BIGENDIAN
24359#undef DUK__FLD_SIGNED
24360#undef DUK__FLD_TYPEDARRAY
24361/*
24362 * Date built-ins
24363 *
24364 * Unlike most built-ins, Date has some platform dependencies for getting
24365 * UTC time, converting between UTC and local time, and parsing and
24366 * formatting time values. These are all abstracted behind DUK_USE_xxx
24367 * config options. There are built-in platform specific providers for
24368 * POSIX and Windows, but external providers can also be used.
24369 *
24370 * See doc/datetime.rst.
24371 *
24372 */
24374/* include removed: duk_internal.h */
24375
24376/*
24377 * Forward declarations
24378 */
24379
24385/*
24386 * Other file level defines
24387 */
24388
24389/* Debug macro to print all parts and dparts (used manually because of debug level). */
24390#define DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts) do { \
24391 DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
24392 (long) (parts)[0], (long) (parts)[1], \
24393 (long) (parts)[2], (long) (parts)[3], \
24394 (long) (parts)[4], (long) (parts)[5], \
24395 (long) (parts)[6], (long) (parts)[7], \
24396 (double) (dparts)[0], (double) (dparts)[1], \
24397 (double) (dparts)[2], (double) (dparts)[3], \
24398 (double) (dparts)[4], (double) (dparts)[5], \
24399 (double) (dparts)[6], (double) (dparts)[7])); \
24400 } while (0)
24401#define DUK__DPRINT_PARTS(parts) do { \
24402 DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
24403 (long) (parts)[0], (long) (parts)[1], \
24404 (long) (parts)[2], (long) (parts)[3], \
24405 (long) (parts)[4], (long) (parts)[5], \
24406 (long) (parts)[6], (long) (parts)[7])); \
24407 } while (0)
24408#define DUK__DPRINT_DPARTS(dparts) do { \
24409 DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
24410 (double) (dparts)[0], (double) (dparts)[1], \
24411 (double) (dparts)[2], (double) (dparts)[3], \
24412 (double) (dparts)[4], (double) (dparts)[5], \
24413 (double) (dparts)[6], (double) (dparts)[7])); \
24414 } while (0)
24415
24416/* Equivalent year for DST calculations outside [1970,2038[ range, see
24417 * E5 Section 15.9.1.8. Equivalent year has the same leap-year-ness and
24418 * starts with the same weekday on Jan 1.
24419 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
24420 */
24421#define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
24422DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
24423#if 1
24424 /* This is based on V8 EquivalentYear() algorithm (see src/genequivyear.py):
24425 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
24426 */
24427
24428 /* non-leap year: sunday, monday, ... */
24429 DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
24430 DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
24431
24432 /* leap year: sunday, monday, ... */
24433 DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
24434 DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
24435#endif
24436
24437#if 0
24438 /* This is based on Rhino EquivalentYear() algorithm:
24439 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
24440 */
24442 /* non-leap year: sunday, monday, ... */
24443 DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
24444 DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
24446 /* leap year: sunday, monday, ... */
24447 DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
24448 DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
24449#endif
24451#undef DUK__YEAR
24453/*
24454 * ISO 8601 subset parser.
24457/* Parser part count. */
24458#define DUK__NUM_ISO8601_PARSER_PARTS 9
24460/* Parser part indices. */
24461#define DUK__PI_YEAR 0
24462#define DUK__PI_MONTH 1
24463#define DUK__PI_DAY 2
24464#define DUK__PI_HOUR 3
24465#define DUK__PI_MINUTE 4
24466#define DUK__PI_SECOND 5
24467#define DUK__PI_MILLISECOND 6
24468#define DUK__PI_TZHOUR 7
24469#define DUK__PI_TZMINUTE 8
24471/* Parser part masks. */
24472#define DUK__PM_YEAR (1 << DUK__PI_YEAR)
24473#define DUK__PM_MONTH (1 << DUK__PI_MONTH)
24474#define DUK__PM_DAY (1 << DUK__PI_DAY)
24475#define DUK__PM_HOUR (1 << DUK__PI_HOUR)
24476#define DUK__PM_MINUTE (1 << DUK__PI_MINUTE)
24477#define DUK__PM_SECOND (1 << DUK__PI_SECOND)
24478#define DUK__PM_MILLISECOND (1 << DUK__PI_MILLISECOND)
24479#define DUK__PM_TZHOUR (1 << DUK__PI_TZHOUR)
24480#define DUK__PM_TZMINUTE (1 << DUK__PI_TZMINUTE)
24482/* Parser separator indices. */
24483#define DUK__SI_PLUS 0
24484#define DUK__SI_MINUS 1
24485#define DUK__SI_T 2
24486#define DUK__SI_SPACE 3
24487#define DUK__SI_COLON 4
24488#define DUK__SI_PERIOD 5
24489#define DUK__SI_Z 6
24490#define DUK__SI_NUL 7
24491
24492/* Parser separator masks. */
24493#define DUK__SM_PLUS (1 << DUK__SI_PLUS)
24494#define DUK__SM_MINUS (1 << DUK__SI_MINUS)
24495#define DUK__SM_T (1 << DUK__SI_T)
24496#define DUK__SM_SPACE (1 << DUK__SI_SPACE)
24497#define DUK__SM_COLON (1 << DUK__SI_COLON)
24498#define DUK__SM_PERIOD (1 << DUK__SI_PERIOD)
24499#define DUK__SM_Z (1 << DUK__SI_Z)
24500#define DUK__SM_NUL (1 << DUK__SI_NUL)
24502/* Rule control flags. */
24503#define DUK__CF_NEG (1 << 0) /* continue matching, set neg_tzoffset flag */
24504#define DUK__CF_ACCEPT (1 << 1) /* accept string */
24505#define DUK__CF_ACCEPT_NUL (1 << 2) /* accept string if next char is NUL (otherwise reject) */
24506
24507#define DUK__PACK_RULE(partmask,sepmask,nextpart,flags) \
24508 ((duk_uint32_t) (partmask) + \
24509 (((duk_uint32_t) (sepmask)) << 9) + \
24510 (((duk_uint32_t) (nextpart)) << 17) + \
24511 (((duk_uint32_t) (flags)) << 21))
24512
24513#define DUK__UNPACK_RULE(rule,var_nextidx,var_flags) do { \
24514 (var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
24515 (var_flags) = (duk_small_uint_t) ((rule) >> 21); \
24516 } while (0)
24517
24518#define DUK__RULE_MASK_PART_SEP 0x1ffffUL
24519
24520/* Matching separator index is used in the control table */
24521DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
24522 DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
24523 DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
24524};
24525
24526/* Rule table: first matching rule is used to determine what to do next. */
24527DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
24539
24540 /* Note1: the specification doesn't require matching a time form with
24541 * just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
24542 *
24543 * Note2: the specification doesn't require matching a timezone offset
24544 * with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
24545 */
24546};
24547
24551 duk_double_t d;
24552 const duk_uint8_t *p;
24553 duk_small_uint_t part_idx = 0;
24554 duk_int_t accum = 0;
24555 duk_small_uint_t ndigits = 0;
24556 duk_bool_t neg_year = 0;
24557 duk_bool_t neg_tzoffset = 0;
24560
24561 /* During parsing, month and day are one-based; set defaults here. */
24562 DUK_MEMZERO(parts, sizeof(parts));
24563 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */
24564 parts[DUK_DATE_IDX_MONTH] = 1;
24565 parts[DUK_DATE_IDX_DAY] = 1;
24566
24567 /* Special handling for year sign. */
24568 p = (const duk_uint8_t *) str;
24569 ch = p[0];
24570 if (ch == DUK_ASC_PLUS) {
24571 p++;
24572 } else if (ch == DUK_ASC_MINUS) {
24573 neg_year = 1;
24574 p++;
24575 }
24576
24577 for (;;) {
24578 ch = *p++;
24579 DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
24580 (long) part_idx, (long) ch,
24581 (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
24582
24583 if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
24584 if (ndigits >= 9) {
24585 DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
24586 goto reject;
24587 }
24588 if (part_idx == DUK__PI_MILLISECOND /*msec*/ && ndigits >= 3) {
24589 /* ignore millisecond fractions after 3 */
24590 } else {
24591 accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
24592 ndigits++;
24593 }
24594 } else {
24595 duk_uint_fast32_t match_val;
24596 duk_small_int_t sep_idx;
24597
24598 if (ndigits <= 0) {
24599 goto reject;
24600 }
24601 if (part_idx == DUK__PI_MILLISECOND) {
24602 /* complete the millisecond field */
24603 while (ndigits < 3) {
24604 accum *= 10;
24605 ndigits++;
24606 }
24607 }
24608 parts[part_idx] = accum;
24609 DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
24610
24611 accum = 0;
24612 ndigits = 0;
24613
24614 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
24615 if (duk__parse_iso8601_seps[i] == ch) {
24616 break;
24617 }
24618 }
24619 if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
24620 DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
24621 goto reject;
24622 }
24623
24624 sep_idx = i;
24625 match_val = (1UL << part_idx) + (1UL << (sep_idx + 9)); /* match against rule part/sep bits */
24626
24627 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
24629 duk_small_uint_t nextpart;
24630 duk_small_uint_t cflags;
24631
24632 DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
24633 (long) part_idx, (long) sep_idx,
24634 (unsigned long) match_val, (unsigned long) rule));
24635
24636 if ((rule & match_val) != match_val) {
24637 continue;
24638 }
24639
24640 DUK__UNPACK_RULE(rule, nextpart, cflags);
24641
24642 DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
24643 "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
24644 (long) part_idx, (long) sep_idx,
24645 (unsigned long) match_val, (unsigned long) rule,
24646 (long) nextpart, (unsigned long) cflags));
24647
24648 if (cflags & DUK__CF_NEG) {
24649 neg_tzoffset = 1;
24650 }
24651
24652 if (cflags & DUK__CF_ACCEPT) {
24653 goto accept;
24654 }
24655
24656 if (cflags & DUK__CF_ACCEPT_NUL) {
24657 DUK_ASSERT(*(p - 1) != (char) 0);
24658 if (*p == DUK_ASC_NUL) {
24659 goto accept;
24660 }
24661 goto reject;
24662 }
24663
24664 part_idx = nextpart;
24665 break;
24666 } /* rule match */
24667
24668 if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
24669 DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
24670 goto reject;
24671 }
24672
24673 if (ch == 0) {
24674 /* This shouldn't be necessary, but check just in case
24675 * to avoid any chance of overruns.
24676 */
24677 DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
24678 goto reject;
24679 }
24680 } /* if-digit-else-ctrl */
24681 } /* char loop */
24682
24683 /* We should never exit the loop above. */
24685
24686 reject:
24687 DUK_DDD(DUK_DDDPRINT("reject"));
24688 return 0;
24689
24690 accept:
24691 DUK_DDD(DUK_DDDPRINT("accept"));
24692
24693 /* Apply timezone offset to get the main parts in UTC */
24694 if (neg_year) {
24695 parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
24696 }
24697 if (neg_tzoffset) {
24698 parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
24699 parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
24700 } else {
24701 parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
24702 parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
24703 }
24704 parts[DUK__PI_MONTH] -= 1; /* zero-based month */
24705 parts[DUK__PI_DAY] -= 1; /* zero-based day */
24706
24707 /* Use double parts, they tolerate unnormalized time.
24708 *
24709 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
24710 * on purpose. It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
24711 * but will make the value initialized just in case, and avoid any
24712 * potential for Valgrind issues.
24713 */
24714 for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
24715 DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
24716 dparts[i] = parts[i];
24717 }
24718
24719 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
24720 duk_push_number(ctx, d);
24721 return 1;
24722}
24723
24724/*
24725 * Date/time parsing helper.
24727 * Parse a datetime string into a time value. We must first try to parse
24728 * the input according to the standard format in E5.1 Section 15.9.1.15.
24729 * If that fails, we can try to parse using custom parsing, which can
24730 * either be platform neutral (custom code) or platform specific (using
24731 * existing platform API calls).
24732 *
24733 * Note in particular that we must parse whatever toString(), toUTCString(),
24734 * and toISOString() can produce; see E5.1 Section 15.9.4.2.
24735 *
24736 * Returns 1 to allow tail calling.
24737 *
24738 * There is much room for improvement here with respect to supporting
24739 * alternative datetime formats. For instance, V8 parses '2012-01-01' as
24740 * UTC and '2012/01/01' as local time.
24741 */
24742
24743DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
24744 /* XXX: there is a small risk here: because the ISO 8601 parser is
24745 * very loose, it may end up parsing some datetime values which
24746 * would be better parsed with a platform specific parser.
24747 */
24748
24749 DUK_ASSERT(str != NULL);
24750 DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
24751
24752 if (duk__parse_string_iso8601_subset(ctx, str) != 0) {
24753 return 1;
24754 }
24755
24756#if defined(DUK_USE_DATE_PARSE_STRING)
24757 /* Contract, either:
24758 * - Push value on stack and return 1
24759 * - Don't push anything on stack and return 0
24760 */
24761
24762 if (DUK_USE_DATE_PARSE_STRING(ctx, str) != 0) {
24763 return 1;
24764 }
24765#else
24766 /* No platform-specific parsing, this is not an error. */
24767#endif
24768
24769 duk_push_nan(ctx);
24770 return 1;
24771}
24772
24773/*
24774 * Calendar helpers
24775 *
24776 * Some helpers are used for getters and can operate on normalized values
24777 * which can be represented with 32-bit signed integers. Other helpers are
24778 * needed by setters and operate on un-normalized double values, must watch
24779 * out for non-finite numbers etc.
24780 */
24781
24783 (duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
24784 (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
24785 (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
24786};
24787
24788/* Maximum iteration count for computing UTC-to-local time offset when
24789 * creating an Ecmascript time value from local parts.
24790 */
24791#define DUK__LOCAL_TZOFFSET_MAXITER 4
24792
24793/* Because 'day since epoch' can be negative and is used to compute weekday
24794 * using a modulo operation, add this multiple of 7 to avoid negative values
24795 * when year is below 1970 epoch. Ecmascript time values are restricted to
24796 * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
24797 * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
24798 */
24799#define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */
24800
24802 if ((year % 4) != 0) {
24803 return 0;
24804 }
24805 if ((year % 100) != 0) {
24806 return 1;
24807 }
24808 if ((year % 400) != 0) {
24823 return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
24824}
24827 if (!DUK_ISFINITE(x)) {
24828 return DUK_DOUBLE_NAN;
24829 }
24830
24832 return DUK_DOUBLE_NAN;
24833 }
24834
24836
24837 /* Here we'd have the option to normalize -0 to +0. */
24838 return x;
24840
24841/* Integer division which floors also negative values correctly. */
24843 DUK_ASSERT(b > 0);
24844 if (a >= 0) {
24845 return a / b;
24846 } else {
24847 /* e.g. a = -4, b = 5 --> -4 - 5 + 1 / 5 --> -8 / 5 --> -1
24848 * a = -5, b = 5 --> -5 - 5 + 1 / 5 --> -9 / 5 --> -1
24849 * a = -6, b = 5 --> -6 - 5 + 1 / 5 --> -10 / 5 --> -2
24851 return (a - b + 1) / b;
24852 }
24853}
24854
24855/* Compute day number of the first day of a given year. */
24857 /* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
24858 * values, but is incorrect for negative ones.
24859 */
24860 return 365 * (year - 1970)
24861 + duk__div_floor(year - 1969, 4)
24862 - duk__div_floor(year - 1901, 100)
24863 + duk__div_floor(year - 1601, 400);
24864}
24865
24866/* Given a day number, determine year and day-within-year. */
24868 duk_int_t year;
24869 duk_int_t diff_days;
24870
24871 /* estimate year upwards (towards positive infinity), then back down;
24872 * two iterations should be enough
24873 */
24874
24875 if (day >= 0) {
24876 year = 1970 + day / 365;
24877 } else {
24878 year = 1970 + day / 366;
24879 }
24880
24881 for (;;) {
24882 diff_days = duk__day_from_year(year) - day;
24883 DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
24884 if (diff_days <= 0) {
24885 DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */
24886 *out_day_within_year = -diff_days;
24887 DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
24888 (long) year, (long) *out_day_within_year));
24889 DUK_ASSERT(*out_day_within_year >= 0);
24890 DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
24891 return year;
24892 }
24893
24894 /* Note: this is very tricky; we must never 'overshoot' the
24895 * correction downwards.
24896 */
24897 year -= 1 + (diff_days - 1) / 366; /* conservative */
24898 }
24899}
24900
24901/* Given a (year, month, day-within-month) triple, compute day number.
24902 * The input triple is un-normalized and may contain non-finite values.
24903 */
24905 duk_int_t day_num;
24906 duk_bool_t is_leap;
24907 duk_small_int_t i, n;
24908
24909 /* Assume that year, month, day are all coerced to whole numbers.
24910 * They may also be NaN or infinity, in which case this function
24911 * must return NaN or infinity to ensure time value becomes NaN.
24912 * If 'day' is NaN, the final return will end up returning a NaN,
24913 * so it doesn't need to be checked here.
24914 */
24915
24916 if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
24917 return DUK_DOUBLE_NAN;
24918 }
24919
24920 year += DUK_FLOOR(month / 12.0);
24921
24922 month = DUK_FMOD(month, 12.0);
24923 if (month < 0.0) {
24924 /* handle negative values */
24925 month += 12.0;
24926 }
24927
24928 /* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
24929 * does not normalize the day-of-month (nor check whether or not
24930 * it is finite) because it's not necessary for finding the day
24931 * number which matches the (year,month) pair.
24932 *
24933 * We assume that duk__day_from_year() is exact here.
24934 *
24935 * Without an explicit infinity / NaN check in the beginning,
24936 * day_num would be a bogus integer here.
24937 *
24938 * It's possible for 'year' to be out of integer range here.
24939 * If so, we need to return NaN without integer overflow.
24940 * This fixes test-bug-setyear-overflow.js.
24941 */
24942
24944 DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
24945 return DUK_DOUBLE_NAN;
24946 }
24947 day_num = duk__day_from_year((duk_int_t) year);
24948 is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
24950 n = (duk_small_int_t) month;
24951 for (i = 0; i < n; i++) {
24952 day_num += duk__days_in_month[i];
24953 if (i == 1 && is_leap) {
24954 day_num++;
24955 }
24956 }
24957
24958 /* If 'day' is NaN, returns NaN. */
24959 return (duk_double_t) day_num + day;
24960}
24961
24962/* Split time value into parts. The time value is assumed to be an internal
24963 * one, i.e. finite, no fractions. Possible local time adjustment has already
24964 * been applied when reading the time value.
24965 */
24967 duk_double_t d1, d2;
24968 duk_int_t t1, t2;
24969 duk_int_t day_since_epoch;
24970 duk_int_t year; /* does not fit into 16 bits */
24971 duk_small_int_t day_in_year;
24972 duk_small_int_t month;
24973 duk_small_int_t day;
24974 duk_small_int_t dim;
24975 duk_int_t jan1_since_epoch;
24976 duk_small_int_t jan1_weekday;
24977 duk_int_t equiv_year;
24979 duk_bool_t is_leap;
24980 duk_small_int_t arridx;
24981
24982 DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */
24983 DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions in internal time */
24984
24985 /* The timevalue must be in valid Ecmascript range, but since a local
24986 * time offset can be applied, we need to allow a +/- 24h leeway to
24987 * the value. In other words, although the UTC time is within the
24988 * Ecmascript range, the local part values can be just outside of it.
24989 */
24992
24993 /* these computations are guaranteed to be exact for the valid
24994 * E5 time value range, assuming milliseconds without fractions.
24995 */
24996 d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
24997 if (d1 < 0.0) {
24998 /* deal with negative values */
25000 }
25001 d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
25002 DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
25003 /* now expected to fit into a 32-bit integer */
25004 t1 = (duk_int_t) d1;
25005 t2 = (duk_int_t) d2;
25006 day_since_epoch = t2;
25007 DUK_ASSERT((duk_double_t) t1 == d1);
25008 DUK_ASSERT((duk_double_t) t2 == d2);
25009
25010 /* t1 = milliseconds within day (fits 32 bit)
25011 * t2 = day number from epoch (fits 32 bit, may be negative)
25012 */
25013
25014 parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
25015 parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
25016 parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
25017 parts[DUK_DATE_IDX_HOUR] = t1;
25018 DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
25019 DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
25020 DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
25021 DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
25022
25023 DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
25024 (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
25025 (long) parts[DUK_DATE_IDX_HOUR],
25026 (long) parts[DUK_DATE_IDX_MINUTE],
25027 (long) parts[DUK_DATE_IDX_SECOND],
25028 (long) parts[DUK_DATE_IDX_MILLISECOND]));
25029
25030 /* This assert depends on the input parts representing time inside
25031 * the Ecmascript range.
25032 */
25034 parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
25035 DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
25036
25037 year = duk__year_from_day(t2, &day_in_year);
25038 day = day_in_year;
25039 is_leap = duk_bi_date_is_leap_year(year);
25040 for (month = 0; month < 12; month++) {
25041 dim = duk__days_in_month[month];
25042 if (month == 1 && is_leap) {
25043 dim++;
25044 }
25045 DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
25046 (long) month, (long) dim, (long) day));
25047 if (day < dim) {
25048 break;
25049 }
25050 day -= dim;
25051 }
25052 DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
25053 DUK_ASSERT(month >= 0 && month <= 11);
25054 DUK_ASSERT(day >= 0 && day <= 31);
25055
25056 /* Equivalent year mapping, used to avoid DST trouble when platform
25057 * may fail to provide reasonable DST answers for dates outside the
25058 * ordinary range (e.g. 1970-2038). An equivalent year has the same
25059 * leap-year-ness as the original year and begins on the same weekday
25060 * (Jan 1).
25061 *
25062 * The year 2038 is avoided because there seem to be problems with it
25063 * on some platforms. The year 1970 is also avoided as there were
25064 * practical problems with it; an equivalent year is used for it too,
25065 * which breaks some DST computations for 1970 right now, see e.g.
25066 * test-bi-date-tzoffset-brute-fi.js.
25067 */
25068 if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
25069 DUK_ASSERT(is_leap == 0 || is_leap == 1);
25070
25071 jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */
25072 DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
25073 jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
25074 DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
25075 arridx = jan1_weekday;
25076 if (is_leap) {
25077 arridx += 7;
25078 }
25079 DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
25080
25081 equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
25082 year = equiv_year;
25083 DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
25084 "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
25085 (long) year, (long) day_in_year, (long) day_since_epoch,
25086 (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
25087 }
25088
25089 parts[DUK_DATE_IDX_YEAR] = year;
25090 parts[DUK_DATE_IDX_MONTH] = month;
25091 parts[DUK_DATE_IDX_DAY] = day;
25092
25093 if (flags & DUK_DATE_FLAG_ONEBASED) {
25094 parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */
25095 parts[DUK_DATE_IDX_DAY]++; /* -""- */
25096 }
25097
25098 if (dparts != NULL) {
25099 for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
25100 dparts[i] = (duk_double_t) parts[i];
25101 }
25102 }
25103}
25104
25105/* Compute time value from (double) parts. The parts can be either UTC
25106 * or local time; if local, they need to be (conceptually) converted into
25107 * UTC time. The parts may represent valid or invalid time, and may be
25108 * wildly out of range (but may cancel each other and still come out in
25109 * the valid Date range).
25110 */
25112#if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
25113 /* See comments below on MakeTime why these are volatile. */
25114 volatile duk_double_t tmp_time;
25115 volatile duk_double_t tmp_day;
25116 volatile duk_double_t d;
25117#else
25118 duk_double_t tmp_time;
25119 duk_double_t tmp_day;
25120 duk_double_t d;
25121#endif
25123 duk_int_t tzoff, tzoffprev1, tzoffprev2;
25124
25125 /* Expects 'this' at top of stack on entry. */
25126
25127 /* Coerce all finite parts with ToInteger(). ToInteger() must not
25128 * be called for NaN/Infinity because it will convert e.g. NaN to
25129 * zero. If ToInteger() has already been called, this has no side
25130 * effects and is idempotent.
25131 *
25132 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
25133 * issues if the value is uninitialized.
25134 */
25135 for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
25136 /* SCANBUILD: scan-build complains here about assigned value
25137 * being garbage or undefined. This is correct but operating
25138 * on undefined values has no ill effect and is ignored by the
25139 * caller in the case where this happens.
25140 */
25141 d = dparts[i];
25142 if (DUK_ISFINITE(d)) {
25143 dparts[i] = duk_js_tointeger_number(d);
25144 }
25145 }
25146
25147 /* Use explicit steps in computation to try to ensure that
25148 * computation happens with intermediate results coerced to
25149 * double values (instead of using something more accurate).
25150 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
25151 * rules (= Ecmascript '+' and '*' operators).
25152 *
25153 * Without 'volatile' even this approach fails on some platform
25154 * and compiler combinations. For instance, gcc 4.8.1 on Ubuntu
25155 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
25156 * would fail because of some optimizations when computing tmp_time
25157 * (MakeTime below). Adding 'volatile' to tmp_time solved this
25158 * particular problem (annoyingly, also adding debug prints or
25159 * running the executable under valgrind hides it).
25160 */
25161
25162 /* MakeTime */
25163 tmp_time = 0.0;
25164 tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
25165 tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
25166 tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
25167 tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
25168
25169 /* MakeDay */
25170 tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
25171
25172 /* MakeDate */
25173 d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
25174
25175 DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
25176 (double) tmp_time, (double) tmp_day, (double) d));
25177
25178 /* Optional UTC conversion. */
25179 if (flags & DUK_DATE_FLAG_LOCALTIME) {
25180 /* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
25181 * time value computed from UTC parts. At this point we only
25182 * have 'd' which is a time value computed from local parts, so
25183 * it is off by the UTC-to-local time offset which we don't know
25184 * yet. The current solution for computing the UTC-to-local
25185 * time offset is to iterate a few times and detect a fixed
25186 * point or a two-cycle loop (or a sanity iteration limit),
25187 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
25188 *
25189 * E5.1 Section 15.9.1.9:
25190 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
25191 *
25192 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
25193 */
25194
25195#if 0
25196 /* Old solution: don't iterate, incorrect */
25197 tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
25198 DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
25199 d -= tzoff * 1000L;
25200 DUK_UNREF(tzoffprev1);
25201 DUK_UNREF(tzoffprev2);
25202#endif
25203
25204 /* Iteration solution */
25205 tzoff = 0;
25206 tzoffprev1 = 999999999L; /* invalid value which never matches */
25207 for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
25208 tzoffprev2 = tzoffprev1;
25209 tzoffprev1 = tzoff;
25210 tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
25211 DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
25212 (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25213 if (tzoff == tzoffprev1) {
25214 DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
25215 (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25216 break;
25217 } else if (tzoff == tzoffprev2) {
25218 /* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
25219 * In these cases, favor a higher tzoffset to get a consistent
25220 * result which is independent of iteration count. Not sure if
25221 * this is a generically correct solution.
25222 */
25223 DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
25224 (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25225 if (tzoffprev1 > tzoff) {
25226 tzoff = tzoffprev1;
25227 }
25228 break;
25229 }
25230 }
25231 DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
25232 d -= tzoff * 1000L;
25233 }
25234
25235 /* TimeClip(), which also handles Infinity -> NaN conversion */
25236 d = duk__timeclip(d);
25237
25238 return d;
25239}
25240
25241/*
25242 * API oriented helpers
25243 */
25244
25245/* Push 'this' binding, check that it is a Date object; then push the
25246 * internal time value. At the end, stack is: [ ... this timeval ].
25247 * Returns the time value. Local time adjustment is done if requested.
25248 */
25250 duk_hthread *thr = (duk_hthread *) ctx;
25251 duk_hobject *h;
25252 duk_double_t d;
25253 duk_int_t tzoffset = 0;
25254
25255 duk_push_this(ctx);
25256 h = duk_get_hobject(ctx, -1); /* XXX: getter with class check, useful in built-ins */
25258 DUK_ERROR_TYPE(thr, "expected Date");
25259 }
25260
25262 d = duk_to_number(ctx, -1);
25263 duk_pop(ctx);
25264
25265 if (DUK_ISNAN(d)) {
25266 if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
25267 d = 0.0;
25268 }
25270 DUK_ERROR_RANGE(thr, "Invalid Date");
25271 }
25272 }
25273 /* if no NaN handling flag, may still be NaN here, but not Inf */
25275
25276 if (flags & DUK_DATE_FLAG_LOCALTIME) {
25277 /* Note: DST adjustment is determined using UTC time.
25278 * If 'd' is NaN, tzoffset will be 0.
25279 */
25280 tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */
25281 d += tzoffset * 1000L;
25283 if (out_tzoffset) {
25284 *out_tzoffset = tzoffset;
25285 }
25286
25287 /* [ ... this ] */
25288 return d;
25289}
25290
25292 return duk__push_this_get_timeval_tzoffset(ctx, flags, NULL);
25293}
25294
25295/* Set timeval to 'this' from dparts, push the new time value onto the
25296 * value stack and return 1 (caller can then tail call us). Expects
25297 * the value stack to contain 'this' on the stack top.
25298 */
25300 duk_double_t d;
25301
25302 /* [ ... this ] */
25303
25304 d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
25305 duk_push_number(ctx, d); /* -> [ ... this timeval_new ] */
25306 duk_dup_top(ctx); /* -> [ ... this timeval_new timeval_new ] */
25308
25309 /* stack top: new time value, return 1 to allow tail calls */
25310 return 1;
25311}
25312
25313/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
25314DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {
25315 char yearstr[8]; /* "-123456\0" */
25316 char tzstr[8]; /* "+11:22\0" */
25317 char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
25318
25319 DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
25320 DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
25321 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
25322
25323 /* Note: %06d for positive value, %07d for negative value to include
25324 * sign and 6 digits.
25325 */
25326 DUK_SNPRINTF(yearstr,
25327 sizeof(yearstr),
25328 (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
25329 ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
25330 (long) parts[DUK_DATE_IDX_YEAR]);
25331 yearstr[sizeof(yearstr) - 1] = (char) 0;
25332
25333 if (flags & DUK_DATE_FLAG_LOCALTIME) {
25334 /* tzoffset seconds are dropped; 16 bits suffice for
25335 * time offset in minutes
25336 */
25337 if (tzoffset >= 0) {
25338 duk_small_int_t tmp = tzoffset / 60;
25339 DUK_SNPRINTF(tzstr, sizeof(tzstr), "+%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
25340 } else {
25341 duk_small_int_t tmp = -tzoffset / 60;
25342 DUK_SNPRINTF(tzstr, sizeof(tzstr), "-%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
25343 }
25344 tzstr[sizeof(tzstr) - 1] = (char) 0;
25345 } else {
25346 tzstr[0] = DUK_ASC_UC_Z;
25347 tzstr[1] = (char) 0;
25348 }
25349
25350 /* Unlike year, the other parts fit into 16 bits so %d format
25351 * is portable.
25352 */
25353 if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
25354 DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
25355 (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
25356 (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
25357 (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
25358 } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
25359 DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
25360 (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
25361 } else {
25363 DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
25364 (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
25365 (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
25366 (const char *) tzstr);
25367 }
25368}
25369
25370/* Helper for string conversion calls: check 'this' binding, get the
25371 * internal time value, and format date and/or time in a few formats.
25372 * Return value allows tail calls.
25373 */
25375 duk_double_t d;
25377 duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */
25378 duk_bool_t rc;
25379 duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
25380
25381 DUK_UNREF(rc); /* unreferenced with some options */
25382
25383 d = duk__push_this_get_timeval_tzoffset(ctx, flags, &tzoffset);
25384 if (DUK_ISNAN(d)) {
25386 return 1;
25387 }
25389
25390 /* formatters always get one-based month/day-of-month */
25392 DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
25393 DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
25394
25395 if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
25396 /* try locale specific formatter; if it refuses to format the
25397 * string, fall back to an ISO 8601 formatted value in local
25398 * time.
25399 */
25400#if defined(DUK_USE_DATE_FORMAT_STRING)
25401 /* Contract, either:
25402 * - Push string to value stack and return 1
25403 * - Don't push anything and return 0
25404 */
25405
25406 rc = DUK_USE_DATE_FORMAT_STRING(ctx, parts, tzoffset, flags);
25407 if (rc != 0) {
25408 return 1;
25409 }
25410#else
25411 /* No locale specific formatter; this is OK, we fall back
25412 * to ISO 8601.
25414#endif
25415 }
25416
25417 /* Different calling convention than above used because the helper
25418 * is shared.
25419 */
25420 duk__format_parts_iso8601(parts, tzoffset, flags, buf);
25421 duk_push_string(ctx, (const char *) buf);
25422 return 1;
25423}
25424
25425/* Helper for component getter calls: check 'this' binding, get the
25426 * internal time value, split it into parts (either as UTC time or
25427 * local time), push a specified component as a return value to the
25428 * value stack and return 1 (caller can then tail call us).
25429 */
25431 duk_double_t d;
25433 duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
25434
25435 DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */
25437
25438 d = duk__push_this_get_timeval(ctx, flags_and_idx);
25439 if (DUK_ISNAN(d)) {
25440 duk_push_nan(ctx);
25441 return 1;
25442 }
25444
25445 duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */
25446
25447 /* Setter APIs detect special year numbers (0...99) and apply a +1900
25448 * only in certain cases. The legacy getYear() getter applies -1900
25449 * unconditionally.
25450 */
25451 duk_push_int(ctx, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
25452 return 1;
25453}
25454
25455/* Helper for component setter calls: check 'this' binding, get the
25456 * internal time value, split it into parts (either as UTC time or
25457 * local time), modify one or more components as specified, recompute
25458 * the time value, set it as the internal value. Finally, push the
25459 * new time value as a return value to the value stack and return 1
25460 * (caller can then tail call us).
25461 */
25463 duk_double_t d;
25466 duk_idx_t nargs;
25467 duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
25468 duk_small_uint_t idx_first, idx;
25470
25471 nargs = duk_get_top(ctx);
25472 d = duk__push_this_get_timeval(ctx, flags_and_maxnargs);
25474
25475 if (DUK_ISFINITE(d)) {
25476 duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
25477 } else {
25478 /* NaN timevalue: we need to coerce the arguments, but
25479 * the resulting internal timestamp needs to remain NaN.
25480 * This works but is not pretty: parts and dparts will
25481 * be partially uninitialized, but we only write to them.
25482 */
25483 }
25484
25485 /*
25486 * Determining which datetime components to overwrite based on
25487 * stack arguments is a bit complicated, but important to factor
25488 * out from setters themselves for compactness.
25489 *
25490 * If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
25491 *
25492 * 1 -> millisecond
25493 * 2 -> second, [millisecond]
25494 * 3 -> minute, [second], [millisecond]
25495 * 4 -> hour, [minute], [second], [millisecond]
25496 *
25497 * Else:
25498 *
25499 * 1 -> date
25500 * 2 -> month, [date]
25501 * 3 -> year, [month], [date]
25502 *
25503 * By comparing nargs and maxnargs (and flags) we know which
25504 * components to override. We rely on part index ordering.
25505 */
25506
25507 if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
25508 DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
25509 idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
25510 } else {
25511 DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
25512 idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
25513 }
25514 DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */
25516
25517 for (i = 0; i < maxnargs; i++) {
25518 if ((duk_idx_t) i >= nargs) {
25519 /* no argument given -> leave components untouched */
25520 break;
25521 }
25522 idx = idx_first + i;
25523 DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
25525
25526 if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
25528 }
25529
25530 dparts[idx] = duk_to_number(ctx, i);
25531
25532 if (idx == DUK_DATE_IDX_DAY) {
25533 /* Day-of-month is one-based in the API, but zero-based
25534 * internally, so fix here. Note that month is zero-based
25535 * both in the API and internally.
25536 */
25537 /* SCANBUILD: complains about use of uninitialized values.
25538 * The complaint is correct, but operating in undefined
25539 * values here is intentional in some cases and the caller
25540 * ignores the results.
25541 */
25542 dparts[idx] -= 1.0;
25543 }
25545
25546 /* Leaves new timevalue on stack top and returns 1, which is correct
25547 * for part setters.
25548 */
25549 if (DUK_ISFINITE(d)) {
25550 return duk__set_this_timeval_from_dparts(ctx, dparts, flags_and_maxnargs);
25551 } else {
25552 /* Internal timevalue is already NaN, so don't touch it. */
25553 duk_push_nan(ctx);
25554 return 1;
25555 }
25556}
25557
25558/* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
25559 * 1900 and replace value at idx_val.
25560 */
25562 duk_double_t d;
25563
25564 /* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
25565 * might not generate better code due to casting.
25566 */
25567
25568 /* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
25569 duk_to_number(ctx, idx_val);
25570 if (duk_is_nan(ctx, idx_val)) {
25571 return;
25572 }
25573 duk_dup(ctx, idx_val);
25574 duk_to_int(ctx, -1);
25575 d = duk_get_number(ctx, -1); /* get as double to handle huge numbers correctly */
25576 if (d >= 0.0 && d <= 99.0) {
25577 d += 1900.0;
25578 duk_push_number(ctx, d);
25579 duk_replace(ctx, idx_val);
25580 }
25581 duk_pop(ctx);
25582}
25583
25584/* Set datetime parts from stack arguments, defaulting any missing values.
25585 * Day-of-week is not set; it is not required when setting the time value.
25586 */
25588 duk_double_t d;
25590 duk_small_uint_t idx;
25591
25592 /* Causes a ToNumber() coercion, but doesn't break coercion order since
25593 * year is coerced first anyway.
25594 */
25596
25597 /* There are at most 7 args, but we use 8 here so that also
25598 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
25599 * for any Valgrind gripes later.
25600 */
25601 for (i = 0; i < 8; i++) {
25602 /* Note: rely on index ordering */
25603 idx = DUK_DATE_IDX_YEAR + i;
25604 if ((duk_idx_t) i < nargs) {
25605 d = duk_to_number(ctx, (duk_idx_t) i);
25606 if (idx == DUK_DATE_IDX_DAY) {
25607 /* Convert day from one-based to zero-based (internal). This may
25608 * cause the day part to be negative, which is OK.
25609 */
25610 d -= 1.0;
25611 }
25612 } else {
25613 /* All components default to 0 except day-of-month which defaults
25614 * to 1. However, because our internal day-of-month is zero-based,
25615 * it also defaults to zero here.
25616 */
25617 d = 0.0;
25618 }
25619 dparts[idx] = d;
25620 }
25621
25622 DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
25623 (double) dparts[0], (double) dparts[1],
25624 (double) dparts[2], (double) dparts[3],
25625 (double) dparts[4], (double) dparts[5],
25626 (double) dparts[6], (double) dparts[7]));
25627}
25628
25629/*
25630 * Helper to format a time value into caller buffer, used by logging.
25631 * 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long.
25632 */
25633
25634DUK_INTERNAL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf) {
25636
25638 parts,
25639 NULL,
25641
25643 0 /*tzoffset*/,
25646 DUK_DATE_FLAG_SEP_T /*flags*/,
25647 out_buf);
25648}
25649
25650/*
25651 * Indirect magic value lookup for Date methods.
25652 *
25653 * Date methods don't put their control flags into the function magic value
25654 * because they wouldn't fit into a LIGHTFUNC's magic field. Instead, the
25655 * magic value is set to an index pointing to the array of control flags
25656 * below.
25657 *
25658 * This must be kept in strict sync with genbuiltins.py!
25659 */
25660
25661static duk_uint16_t duk__date_magics[] = {
25662 /* 0: toString */
25664
25665 /* 1: toDateString */
25667
25668 /* 2: toTimeString */
25670
25671 /* 3: toLocaleString */
25673
25674 /* 4: toLocaleDateString */
25676
25677 /* 5: toLocaleTimeString */
25679
25680 /* 6: toUTCString */
25682
25683 /* 7: toISOString */
25685
25686 /* 8: getFullYear */
25688
25689 /* 9: getUTCFullYear */
25691
25692 /* 10: getMonth */
25694
25695 /* 11: getUTCMonth */
25697
25698 /* 12: getDate */
25700
25701 /* 13: getUTCDate */
25703
25704 /* 14: getDay */
25706
25707 /* 15: getUTCDay */
25709
25710 /* 16: getHours */
25712
25713 /* 17: getUTCHours */
25715
25716 /* 18: getMinutes */
25718
25719 /* 19: getUTCMinutes */
25721
25722 /* 20: getSeconds */
25724
25725 /* 21: getUTCSeconds */
25727
25728 /* 22: getMilliseconds */
25730
25731 /* 23: getUTCMilliseconds */
25733
25734 /* 24: setMilliseconds */
25736
25737 /* 25: setUTCMilliseconds */
25739
25740 /* 26: setSeconds */
25742
25743 /* 27: setUTCSeconds */
25745
25746 /* 28: setMinutes */
25748
25749 /* 29: setUTCMinutes */
25751
25752 /* 30: setHours */
25754
25755 /* 31: setUTCHours */
25757
25758 /* 32: setDate */
25760
25761 /* 33: setUTCDate */
25762 0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
25763
25764 /* 34: setMonth */
25767 /* 35: setUTCMonth */
25768 0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
25769
25770 /* 36: setFullYear */
25772
25773 /* 37: setUTCFullYear */
25775
25776 /* 38: getYear */
25778
25779 /* 39: setYear */
25781};
25782
25785 DUK_ASSERT(magicidx >= 0 && magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
25786 return (duk_small_uint_t) duk__date_magics[magicidx];
25787}
25788
25789/*
25790 * Constructor calls
25791 */
25792
25794 duk_idx_t nargs = duk_get_top(ctx);
25795 duk_bool_t is_cons = duk_is_constructor_call(ctx);
25797 duk_double_t d;
25798
25799 DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
25800
25805
25806 /* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
25807 * is mutable.
25808 */
25809
25810 if (nargs == 0 || !is_cons) {
25811 d = duk__timeclip(DUK_USE_DATE_GET_NOW(ctx));
25812 duk_push_number(ctx, d);
25814 if (!is_cons) {
25815 /* called as a normal function: return new Date().toString() */
25816 duk_to_string(ctx, -1);
25817 }
25818 return 1;
25819 } else if (nargs == 1) {
25821 if (duk_is_string(ctx, 0)) {
25822 duk__parse_string(ctx, duk_to_string(ctx, 0));
25823 duk_replace(ctx, 0); /* may be NaN */
25824 }
25825 d = duk__timeclip(duk_to_number(ctx, 0));
25826 duk_push_number(ctx, d);
25828 return 1;
25829 }
25830
25831 duk__set_parts_from_args(ctx, dparts, nargs);
25832
25833 /* Parts are in local time, convert when setting. */
25834
25835 (void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */
25836 duk_pop(ctx); /* -> [ ... this ] */
25837 return 1;
25838}
25839
25841 return duk__parse_string(ctx, duk_to_string(ctx, 0));
25842}
25843
25845 duk_idx_t nargs = duk_get_top(ctx);
25847 duk_double_t d;
25848
25849 /* Behavior for nargs < 2 is implementation dependent: currently we'll
25850 * set a NaN time value (matching V8 behavior) in this case.
25851 */
25852
25853 if (nargs < 2) {
25854 duk_push_nan(ctx);
25855 } else {
25856 duk__set_parts_from_args(ctx, dparts, nargs);
25857 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
25858 duk_push_number(ctx, d);
25859 }
25860 return 1;
25861}
25862
25864 duk_double_t d;
25865
25866 d = DUK_USE_DATE_GET_NOW(ctx);
25867 DUK_ASSERT(duk__timeclip(d) == d); /* TimeClip() should never be necessary */
25868 duk_push_number(ctx, d);
25869 return 1;
25870}
25871
25872/*
25873 * String/JSON conversions
25874 *
25875 * Human readable conversions are now basically ISO 8601 with a space
25876 * (instead of 'T') as the date/time separator. This is a good baseline
25877 * and is platform independent.
25878 *
25879 * A shared native helper to provide many conversions. Magic value contains
25880 * a set of flags. The helper provides:
25881 *
25882 * toString()
25883 * toDateString()
25884 * toTimeString()
25885 * toLocaleString()
25886 * toLocaleDateString()
25887 * toLocaleTimeString()
25888 * toUTCString()
25889 * toISOString()
25890 *
25891 * Notes:
25892 *
25893 * - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
25894 * required to be the same Ecmascript function object (!), so it is
25895 * omitted from here.
25896 *
25897 * - Date.prototype.toUTCString(): E5.1 specification does not require a
25898 * specific format, but result should be human readable. The
25899 * specification suggests using ISO 8601 format with a space (instead
25900 * of 'T') separator if a more human readable format is not available.
25901 *
25902 * - Date.prototype.toISOString(): unlike other conversion functions,
25903 * toISOString() requires a RangeError for invalid date values.
25904 */
25908 return duk__to_string_helper(ctx, flags);
25909}
25910
25912 /* This native function is also used for Date.prototype.getTime()
25913 * as their behavior is identical.
25914 */
25915
25916 duk_double_t d = duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ this ] */
25918 duk_push_number(ctx, d);
25919 return 1;
25920}
25921
25923 /* Note: toJSON() is a generic function which works even if 'this'
25924 * is not a Date. The sole argument is ignored.
25925 */
25926
25927 duk_push_this(ctx);
25928 duk_to_object(ctx, -1);
25929
25930 duk_dup_top(ctx);
25932 if (duk_is_number(ctx, -1)) {
25933 duk_double_t d = duk_get_number(ctx, -1);
25934 if (!DUK_ISFINITE(d)) {
25935 duk_push_null(ctx);
25936 return 1;
25937 }
25938 }
25939 duk_pop(ctx);
25940
25942 duk_dup(ctx, -2); /* -> [ O toIsoString O ] */
25943 duk_call_method(ctx, 0);
25944 return 1;
25945}
25946
25947/*
25948 * Getters.
25949 *
25950 * Implementing getters is quite easy. The internal time value is either
25951 * NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
25952 * The internal time value can be converted to integer parts, and each
25953 * part will be normalized and will fit into a 32-bit signed integer.
25954 *
25955 * A shared native helper to provide all getters. Magic value contains
25956 * a set of flags and also packs the date component index argument. The
25957 * helper provides:
25958 *
25959 * getFullYear()
25960 * getUTCFullYear()
25961 * getMonth()
25962 * getUTCMonth()
25963 * getDate()
25964 * getUTCDate()
25965 * getDay()
25966 * getUTCDay()
25967 * getHours()
25968 * getUTCHours()
25969 * getMinutes()
25970 * getUTCMinutes()
25971 * getSeconds()
25972 * getUTCSeconds()
25973 * getMilliseconds()
25974 * getUTCMilliseconds()
25975 * getYear()
25977 * Notes:
25978 *
25979 * - Date.prototype.getDate(): 'date' means day-of-month, and is
25980 * zero-based in internal calculations but public API expects it to
25981 * be one-based.
25982 *
25983 * - Date.prototype.getTime() and Date.prototype.valueOf() have identical
25984 * behavior. They have separate function objects, but share the same C
25985 * function (duk_bi_date_prototype_value_of).
25986 */
25987
25990 return duk__get_part_helper(ctx, flags_and_idx);
25991}
25992
25994 /*
25995 * Return (t - LocalTime(t)) in minutes:
25996 *
25997 * t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
25998 * = -(LocalTZA + DaylightSavingTA(t))
25999 *
26000 * where DaylightSavingTA() is checked for time 't'.
26001 *
26002 * Note that the sign of the result is opposite to common usage,
26003 * e.g. for EE(S)T which normally is +2h or +3h from UTC, this
26004 * function returns -120 or -180.
26005 *
26006 */
26007
26008 duk_double_t d;
26009 duk_int_t tzoffset;
26010
26011 /* Note: DST adjustment is determined using UTC time. */
26012 d = duk__push_this_get_timeval(ctx, 0 /*flags*/);
26014 if (DUK_ISNAN(d)) {
26015 duk_push_nan(ctx);
26016 } else {
26018 tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
26019 duk_push_int(ctx, -tzoffset / 60);
26020 }
26021 return 1;
26022}
26023
26024/*
26025 * Setters.
26026 *
26027 * Setters are a bit more complicated than getters. Component setters
26028 * break down the current time value into its (normalized) component
26029 * parts, replace one or more components with -unnormalized- new values,
26030 * and the components are then converted back into a time value. As an
26031 * example of using unnormalized values:
26032 *
26033 * var d = new Date(1234567890);
26034 *
26035 * is equivalent to:
26036 *
26037 * var d = new Date(0);
26038 * d.setUTCMilliseconds(1234567890);
26039 *
26040 * A shared native helper to provide almost all setters. Magic value
26041 * contains a set of flags and also packs the "maxnargs" argument. The
26042 * helper provides:
26043 *
26044 * setMilliseconds()
26045 * setUTCMilliseconds()
26046 * setSeconds()
26047 * setUTCSeconds()
26048 * setMinutes()
26049 * setUTCMinutes()
26050 * setHours()
26051 * setUTCHours()
26052 * setDate()
26053 * setUTCDate()
26054 * setMonth()
26055 * setUTCMonth()
26056 * setFullYear()
26057 * setUTCFullYear()
26058 * setYear()
26059 *
26060 * Notes:
26062 * - Date.prototype.setYear() (Section B addition): special year check
26063 * is omitted. NaN / Infinity will just flow through and ultimately
26064 * result in a NaN internal time value.
26065 *
26066 * - Date.prototype.setYear() does not have optional arguments for
26067 * setting month and day-in-month (like setFullYear()), but we indicate
26068 * 'maxnargs' to be 3 to get the year written to the correct component
26069 * index in duk__set_part_helper(). The function has nargs == 1, so only
26070 * the year will be set regardless of actual argument count.
26071 */
26072
26074 duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(ctx);
26075 return duk__set_part_helper(ctx, flags_and_maxnargs);
26076}
26077
26079 duk_double_t d;
26080
26081 (void) duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ timeval this ] */
26082 d = duk__timeclip(duk_to_number(ctx, 0));
26083 duk_push_number(ctx, d);
26084 duk_dup_top(ctx);
26085 duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
26087 return 1;
26088}
26089/*
26090 * Unix-like Date providers
26091 *
26092 * Generally useful Unix / POSIX / ANSI Date providers.
26093 */
26094
26095/* include removed: duk_internal.h */
26096
26097/* The necessary #includes are in place in duk_config.h. */
26098
26099/* Buffer sizes for some UNIX calls. Larger than strictly necessary
26100 * to avoid Valgrind errors.
26101 */
26102#define DUK__STRPTIME_BUF_SIZE 64
26103#define DUK__STRFTIME_BUF_SIZE 64
26104
26105#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
26106/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */
26107DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) {
26108 duk_hthread *thr = (duk_hthread *) ctx;
26109 struct timeval tv;
26110 duk_double_t d;
26111
26112 if (gettimeofday(&tv, NULL) != 0) {
26114 }
26115
26116 d = ((duk_double_t) tv.tv_sec) * 1000.0 +
26117 ((duk_double_t) (tv.tv_usec / 1000));
26118 DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions */
26119
26120 return d;
26121}
26122#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
26123
26124#if defined(DUK_USE_DATE_NOW_TIME)
26125/* Not a very good provider: only full seconds are available. */
26127 time_t t;
26128
26129 DUK_UNREF(ctx);
26130 t = time(NULL);
26131 return ((duk_double_t) t) * 1000.0;
26132}
26133#endif /* DUK_USE_DATE_NOW_TIME */
26134
26135#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R)
26136/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
26138 time_t t, t1, t2;
26141 struct tm tms[2];
26142#ifdef DUK_USE_DATE_TZO_GMTIME
26143 struct tm *tm_ptr;
26144#endif
26145
26146 /* For NaN/inf, the return value doesn't matter. */
26147 if (!DUK_ISFINITE(d)) {
26148 return 0;
26149 }
26150
26151 /* If not within Ecmascript range, some integer time calculations
26152 * won't work correctly (and some asserts will fail), so bail out
26153 * if so. This fixes test-bug-date-insane-setyear.js. There is
26154 * a +/- 24h leeway in this range check to avoid a test262 corner
26155 * case documented in test-bug-date-timeval-edges.js.
26156 */
26158 DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
26159 return 0;
26160 }
26161
26162 /*
26163 * This is a bit tricky to implement portably. The result depends
26164 * on the timestamp (specifically, DST depends on the timestamp).
26165 * If e.g. UNIX APIs are used, they'll have portability issues with
26166 * very small and very large years.
26167 *
26168 * Current approach:
26169 *
26170 * - Stay within portable UNIX limits by using equivalent year mapping.
26171 * Avoid year 1970 and 2038 as some conversions start to fail, at
26172 * least on some platforms. Avoiding 1970 means that there are
26173 * currently DST discrepancies for 1970.
26174 *
26175 * - Create a UTC and local time breakdowns from 't'. Then create
26176 * a time_t using gmtime() and localtime() and compute the time
26177 * difference between the two.
26178 *
26179 * Equivalent year mapping (E5 Section 15.9.1.8):
26180 *
26181 * If the host environment provides functionality for determining
26182 * daylight saving time, the implementation of ECMAScript is free
26183 * to map the year in question to an equivalent year (same
26184 * leap-year-ness and same starting week day for the year) for which
26185 * the host environment provides daylight saving time information.
26186 * The only restriction is that all equivalent years should produce
26187 * the same result.
26188 *
26189 * This approach is quite reasonable but not entirely correct, e.g.
26190 * the specification also states (E5 Section 15.9.1.8):
26191 *
26192 * The implementation of ECMAScript should not try to determine
26193 * whether the exact time was subject to daylight saving time, but
26194 * just whether daylight saving time would have been in effect if
26195 * the _current daylight saving time algorithm_ had been used at the
26196 * time. This avoids complications such as taking into account the
26197 * years that the locale observed daylight saving time year round.
26198 *
26199 * Since we rely on the platform APIs for conversions between local
26200 * time and UTC, we can't guarantee the above. Rather, if the platform
26201 * has historical DST rules they will be applied. This seems to be the
26202 * general preferred direction in Ecmascript standardization (or at least
26203 * implementations) anyway, and even the equivalent year mapping should
26204 * be disabled if the platform is known to handle DST properly for the
26205 * full Ecmascript range.
26206 *
26207 * The following has useful discussion and links:
26208 *
26209 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
26210 */
26211
26212 duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
26213 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
26214
26215 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
26216 DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
26217 t = (time_t) (d / 1000.0);
26218 DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
26219
26220 DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
26221
26222#if defined(DUK_USE_DATE_TZO_GMTIME_R)
26223 (void) gmtime_r(&t, &tms[0]);
26224 (void) localtime_r(&t, &tms[1]);
26225#elif defined(DUK_USE_DATE_TZO_GMTIME)
26226 tm_ptr = gmtime(&t);
26227 DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
26228 tm_ptr = localtime(&t);
26229 DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));
26230#else
26231#error internal error
26232#endif
26233 DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26234 "wday:%ld,yday:%ld,isdst:%ld}",
26235 (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
26236 (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
26237 (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
26238 DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26239 "wday:%ld,yday:%ld,isdst:%ld}",
26240 (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
26241 (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
26242 (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
26243
26244 /* tm_isdst is both an input and an output to mktime(), use 0 to
26245 * avoid DST handling in mktime():
26246 * - https://github.com/svaarala/duktape/issues/406
26247 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
26248 */
26249 tms[0].tm_isdst = 0;
26250 tms[1].tm_isdst = 0;
26251 t1 = mktime(&tms[0]); /* UTC */
26252 t2 = mktime(&tms[1]); /* local */
26253 if (t1 == (time_t) -1 || t2 == (time_t) -1) {
26254 /* This check used to be for (t < 0) but on some platforms
26255 * time_t is unsigned and apparently the proper way to detect
26256 * an mktime() error return is the cast above. See e.g.:
26257 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
26258 */
26259 goto error;
26260 }
26261 DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
26262
26263 /* Compute final offset in seconds, positive if local time ahead of
26264 * UTC (returned value is UTC-to-local offset).
26265 *
26266 * difftime() returns a double, so coercion to int generates quite
26267 * a lot of code. Direct subtraction is not portable, however.
26268 * XXX: allow direct subtraction on known platforms.
26269 */
26270#if 0
26271 return (duk_int_t) (t2 - t1);
26272#endif
26273 return (duk_int_t) difftime(t2, t1);
26274
26275 error:
26276 /* XXX: return something more useful, so that caller can throw? */
26277 DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
26278 return 0;
26279}
26280#endif /* DUK_USE_DATE_TZO_GMTIME */
26281
26282#if defined(DUK_USE_DATE_PRS_STRPTIME)
26283DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str) {
26284 struct tm tm;
26285 time_t t;
26286 char buf[DUK__STRPTIME_BUF_SIZE];
26287
26288 /* copy to buffer with spare to avoid Valgrind gripes from strptime */
26289 DUK_ASSERT(str != NULL);
26290 DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */
26291 DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
26292 buf[sizeof(buf) - 1] = (char) 0;
26293
26294 DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
26295
26296 DUK_MEMZERO(&tm, sizeof(tm));
26297 if (strptime((const char *) buf, "%c", &tm) != NULL) {
26298 DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26299 "wday:%ld,yday:%ld,isdst:%ld}",
26300 (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
26301 (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
26302 (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
26303 tm.tm_isdst = -1; /* negative: dst info not available */
26304
26305 t = mktime(&tm);
26306 DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
26307 if (t >= 0) {
26308 duk_push_number(ctx, ((duk_double_t) t) * 1000.0);
26309 return 1;
26310 }
26311 }
26312
26313 return 0;
26314}
26315#endif /* DUK_USE_DATE_PRS_STRPTIME */
26316
26317#if defined(DUK_USE_DATE_PRS_GETDATE)
26318DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str) {
26319 struct tm tm;
26320 duk_small_int_t rc;
26321 time_t t;
26322
26323 /* For this to work, DATEMSK must be set, so this is not very
26324 * convenient for an embeddable interpreter.
26325 */
26326
26327 DUK_MEMZERO(&tm, sizeof(struct tm));
26328 rc = (duk_small_int_t) getdate_r(str, &tm);
26329 DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
26330
26331 if (rc == 0) {
26332 t = mktime(&tm);
26333 DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
26334 if (t >= 0) {
26335 duk_push_number(ctx, (duk_double_t) t);
26336 return 1;
26337 }
26338 }
26339
26340 return 0;
26341}
26342#endif /* DUK_USE_DATE_PRS_GETDATE */
26343
26344#if defined(DUK_USE_DATE_FMT_STRFTIME)
26345DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {
26346 char buf[DUK__STRFTIME_BUF_SIZE];
26347 struct tm tm;
26348 const char *fmt;
26349
26350 DUK_UNREF(tzoffset);
26351
26352 /* If the platform doesn't support the entire Ecmascript range, we need
26353 * to return 0 so that the caller can fall back to the default formatter.
26354 *
26355 * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript
26356 * range is supported. For smaller time_t values (4 bytes in practice),
26357 * assumes that the signed 32-bit range is supported.
26358 *
26359 * XXX: detect this more correctly per platform. The size of time_t is
26360 * probably not an accurate guarantee of strftime() supporting or not
26361 * supporting a large time range (the full Ecmascript range).
26362 */
26363 if (sizeof(time_t) < 8 &&
26364 (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
26365 /* be paranoid for 32-bit time values (even avoiding negative ones) */
26366 return 0;
26367 }
26368
26369 DUK_MEMZERO(&tm, sizeof(tm));
26370 tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
26371 tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
26372 tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
26373 tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */
26374 tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */
26375 tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
26376 tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
26377 tm.tm_isdst = 0;
26378
26379 DUK_MEMZERO(buf, sizeof(buf));
26380 if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
26381 fmt = "%c";
26382 } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
26383 fmt = "%x";
26384 } else {
26386 fmt = "%X";
26387 }
26388 (void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
26389 DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
26390
26391 duk_push_string(ctx, buf);
26392 return 1;
26393}
26394#endif /* DUK_USE_DATE_FMT_STRFTIME */
26395
26396#undef DUK__STRPTIME_BUF_SIZE
26397#undef DUK__STRFTIME_BUF_SIZE
26398/*
26399 * Windows Date providers
26400 *
26401 * Platform specific links:
26402 *
26403 * - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
26404 */
26405
26406/* include removed: duk_internal.h */
26407
26408/* The necessary #includes are in place in duk_config.h. */
26409
26410#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
26411/* Shared Windows helpers. */
26412DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
26413 FILETIME ft;
26414 if (SystemTimeToFileTime(st, &ft) == 0) {
26415 DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
26416 res->QuadPart = 0;
26417 } else {
26418 res->LowPart = ft.dwLowDateTime;
26419 res->HighPart = ft.dwHighDateTime;
26420 }
26421}
26422DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
26423 DUK_MEMZERO((void *) st, sizeof(*st));
26424 st->wYear = 1970;
26425 st->wMonth = 1;
26426 st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */
26427 st->wDay = 1;
26428 DUK_ASSERT(st->wHour == 0);
26429 DUK_ASSERT(st->wMinute == 0);
26430 DUK_ASSERT(st->wSecond == 0);
26431 DUK_ASSERT(st->wMilliseconds == 0);
26432}
26433#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
26434
26435#ifdef DUK_USE_DATE_NOW_WINDOWS
26436DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) {
26437 /* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
26438 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
26439 */
26440 SYSTEMTIME st1, st2;
26441 ULARGE_INTEGER tmp1, tmp2;
26442
26443 DUK_UNREF(ctx);
26444
26445 GetSystemTime(&st1);
26446 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
26447
26448 duk__set_systime_jan1970(&st2);
26449 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
26450
26451 /* Difference is in 100ns units, convert to milliseconds w/o fractions */
26452 return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL);
26453}
26454#endif /* DUK_USE_DATE_NOW_WINDOWS */
26455
26456
26457#if defined(DUK_USE_DATE_TZO_WINDOWS)
26458DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
26459 SYSTEMTIME st1;
26460 SYSTEMTIME st2;
26461 SYSTEMTIME st3;
26462 ULARGE_INTEGER tmp1;
26463 ULARGE_INTEGER tmp2;
26464 ULARGE_INTEGER tmp3;
26465 FILETIME ft1;
26466
26467 /* XXX: handling of timestamps outside Windows supported range.
26468 * How does Windows deal with dates before 1600? Does windows
26469 * support all Ecmascript years (like -200000 and +200000)?
26470 * Should equivalent year mapping be used here too? If so, use
26471 * a shared helper (currently integrated into timeval-to-parts).
26472 */
26473
26474 /* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
26475 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
26476 */
26477
26478 duk__set_systime_jan1970(&st1);
26479 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
26480 tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */
26481 tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */
26482
26483 ft1.dwLowDateTime = tmp2.LowPart;
26484 ft1.dwHighDateTime = tmp2.HighPart;
26485 FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
26486 if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
26487 DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
26488 return 0;
26489 }
26490 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
26491
26492 /* Positive if local time ahead of UTC. */
26493 return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL); /* seconds */
26494}
26495#endif /* DUK_USE_DATE_TZO_WINDOWS */
26496/*
26497 * Duktape built-ins
26499 * Size optimization note: it might seem that vararg multipurpose functions
26500 * like fin(), enc(), and dec() are not very size optimal, but using a single
26501 * user-visible Ecmascript function saves a lot of run-time footprint; each
26502 * Function instance takes >100 bytes. Using a shared native helper and a
26503 * 'magic' value won't save much if there are multiple Function instances
26504 * anyway.
26505 */
26506
26507/* include removed: duk_internal.h */
26508
26509/* Raw helper to extract internal information / statistics about a value.
26510 * The return values are version specific and must not expose anything
26511 * that would lead to security issues (e.g. exposing compiled function
26512 * 'data' buffer might be an issue). Currently only counts and sizes and
26513 * such are given so there should not be a security impact.
26514 */
26516 duk_hthread *thr = (duk_hthread *) ctx;
26517 duk_tval *tv;
26518 duk_heaphdr *h;
26519 duk_int_t i, n;
26520
26521 DUK_UNREF(thr);
26522
26523 /* result array */
26524 duk_push_array(ctx); /* -> [ val arr ] */
26525
26526 /* type tag (public) */
26527 duk_push_int(ctx, duk_get_type(ctx, 0));
26528
26529 /* address */
26530 tv = duk_get_tval(ctx, 0);
26531 DUK_ASSERT(tv != NULL); /* because arg count is 1 */
26533 h = DUK_TVAL_GET_HEAPHDR(tv);
26534 duk_push_pointer(ctx, (void *) h);
26535 } else {
26536 /* internal type tag */
26538 goto done;
26539 }
26540 DUK_ASSERT(h != NULL);
26541
26542 /* refcount */
26543#ifdef DUK_USE_REFERENCE_COUNTING
26545#else
26546 duk_push_undefined(ctx);
26547#endif
26548
26549 /* heaphdr size and additional allocation size, followed by
26550 * type specific stuff (with varying value count)
26551 */
26553 case DUK_HTYPE_STRING: {
26554 duk_hstring *h_str = (duk_hstring *) h;
26555 duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1));
26556 break;
26557 }
26558 case DUK_HTYPE_OBJECT: {
26559 duk_hobject *h_obj = (duk_hobject *) h;
26560 duk_small_uint_t hdr_size;
26562 hdr_size = (duk_small_uint_t) sizeof(duk_hcompiledfunction);
26563 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
26564 hdr_size = (duk_small_uint_t) sizeof(duk_hnativefunction);
26565 } else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
26566 hdr_size = (duk_small_uint_t) sizeof(duk_hthread);
26567#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26568 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
26569 hdr_size = (duk_small_uint_t) sizeof(duk_hbufferobject);
26570#endif
26571 } else {
26572 hdr_size = (duk_small_uint_t) sizeof(duk_hobject);
26573 }
26574 duk_push_uint(ctx, (duk_uint_t) hdr_size);
26577 /* Note: e_next indicates the number of gc-reachable entries
26578 * in the entry part, and also indicates the index where the
26579 * next new property would be inserted. It does *not* indicate
26580 * the number of non-NULL keys present in the object. That
26581 * value could be counted separately but requires a pass through
26582 * the key list.
26583 */
26589 if (h_data) {
26591 } else {
26592 duk_push_uint(ctx, 0);
26593 }
26594 }
26595 break;
26596 }
26597 case DUK_HTYPE_BUFFER: {
26598 duk_hbuffer *h_buf = (duk_hbuffer *) h;
26599 if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
26600 if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
26602 } else {
26603 /* When alloc_size == 0 the second allocation may not
26604 * actually exist.
26605 */
26607 }
26609 } else {
26610 duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1));
26611 }
26612 break;
26613
26614 }
26615 }
26616
26617 done:
26618 /* set values into ret array */
26619 /* XXX: primitive to make array from valstack slice */
26620 n = duk_get_top(ctx);
26621 for (i = 2; i < n; i++) {
26622 duk_dup(ctx, i);
26623 duk_put_prop_index(ctx, 1, i - 2);
26624 }
26625 duk_dup(ctx, 1);
26626 return 1;
26627}
26628
26630 duk_hthread *thr = (duk_hthread *) ctx;
26631 duk_activation *act;
26633 duk_uint_fast32_t line;
26634 duk_int_t level;
26635
26636 /* -1 = top callstack entry, callstack[callstack_top - 1]
26637 * -callstack_top = bottom callstack entry, callstack[0]
26638 */
26639 level = duk_to_int(ctx, 0);
26640 if (level >= 0 || -level > (duk_int_t) thr->callstack_top) {
26641 return 0;
26642 }
26643 DUK_ASSERT(level >= -((duk_int_t) thr->callstack_top) && level <= -1);
26644 act = thr->callstack + thr->callstack_top + level;
26645
26646 duk_push_object(ctx);
26647
26648 duk_push_tval(ctx, &act->tv_func);
26649
26650 /* Relevant PC is just before current one because PC is
26651 * post-incremented. This should match what error augment
26652 * code does.
26653 */
26654 pc = duk_hthread_get_act_prev_pc(thr, act);
26655 duk_push_uint(ctx, (duk_uint_t) pc);
26656
26657#if defined(DUK_USE_PC2LINE)
26658 line = duk_hobject_pc2line_query(ctx, -2, pc);
26659#else
26660 line = 0;
26661#endif
26663
26664 /* Providing access to e.g. act->lex_env would be dangerous: these
26665 * internal structures must never be accessible to the application.
26666 * Duktape relies on them having consistent data, and this consistency
26667 * is only asserted for, not checked for.
26668 */
26669
26670 /* [ level obj func pc line ] */
26671
26672 /* XXX: version specific array format instead? */
26676 return 1;
26677}
26678
26680#ifdef DUK_USE_MARK_AND_SWEEP
26681 duk_hthread *thr = (duk_hthread *) ctx;
26683 duk_bool_t rc;
26684
26685 flags = (duk_small_uint_t) duk_get_uint(ctx, 0);
26686 rc = duk_heap_mark_and_sweep(thr->heap, flags);
26687
26688 /* XXX: Not sure what the best return value would be in the API.
26689 * Return a boolean for now. Note that rc == 0 is success (true).
26690 */
26691 duk_push_boolean(ctx, !rc);
26692 return 1;
26693#else
26694 DUK_UNREF(ctx);
26695 return 0;
26696#endif
26697}
26698
26700 (void) duk_require_hobject(ctx, 0);
26701 if (duk_get_top(ctx) >= 2) {
26702 /* Set: currently a finalizer is disabled by setting it to
26703 * undefined; this does not remove the property at the moment.
26704 * The value could be type checked to be either a function
26705 * or something else; if something else, the property could
26706 * be deleted.
26707 */
26708 duk_set_top(ctx, 2);
26710 return 0;
26711 } else {
26712 /* Get. */
26713 DUK_ASSERT(duk_get_top(ctx) == 1);
26715 return 1;
26716 }
26717}
26718
26720 duk_hthread *thr = (duk_hthread *) ctx;
26721 duk_hstring *h_str;
26722
26723 DUK_UNREF(thr);
26724
26725 /* Vararg function: must be careful to check/require arguments.
26726 * The JSON helpers accept invalid indices and treat them like
26727 * non-existent optional parameters.
26728 */
26729
26730 h_str = duk_require_hstring(ctx, 0);
26732
26733 if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
26734 duk_set_top(ctx, 2);
26735 duk_hex_encode(ctx, 1);
26736 DUK_ASSERT_TOP(ctx, 2);
26737 } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
26738 duk_set_top(ctx, 2);
26739 duk_base64_encode(ctx, 1);
26740 DUK_ASSERT_TOP(ctx, 2);
26741#ifdef DUK_USE_JX
26742 } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
26744 1 /*idx_value*/,
26745 2 /*idx_replacer*/,
26746 3 /*idx_space*/,
26750#endif
26751#ifdef DUK_USE_JC
26752 } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
26754 1 /*idx_value*/,
26755 2 /*idx_replacer*/,
26756 3 /*idx_space*/,
26758 DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
26759#endif
26760 } else {
26761 return DUK_RET_TYPE_ERROR;
26762 }
26763 return 1;
26764}
26765
26767 duk_hthread *thr = (duk_hthread *) ctx;
26768 duk_hstring *h_str;
26769
26770 DUK_UNREF(thr);
26771
26772 /* Vararg function: must be careful to check/require arguments.
26773 * The JSON helpers accept invalid indices and treat them like
26774 * non-existent optional parameters.
26775 */
26776
26777 h_str = duk_require_hstring(ctx, 0);
26779
26780 if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
26781 duk_set_top(ctx, 2);
26782 duk_hex_decode(ctx, 1);
26783 DUK_ASSERT_TOP(ctx, 2);
26784 } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
26785 duk_set_top(ctx, 2);
26786 duk_base64_decode(ctx, 1);
26787 DUK_ASSERT_TOP(ctx, 2);
26788#ifdef DUK_USE_JX
26789 } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
26791 1 /*idx_value*/,
26792 2 /*idx_replacer*/,
26793 DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
26794#endif
26795#ifdef DUK_USE_JC
26796 } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
26798 1 /*idx_value*/,
26799 2 /*idx_replacer*/,
26801#endif
26802 } else {
26803 return DUK_RET_TYPE_ERROR;
26804 }
26805 return 1;
26807
26808/*
26809 * Compact an object
26810 */
26811
26813 DUK_ASSERT_TOP(ctx, 1);
26814 duk_compact(ctx, 0);
26815 return 1; /* return the argument object */
26816}
26817/*
26818 * Error built-ins
26819 */
26820
26821/* include removed: duk_internal.h */
26822
26824 /* Behavior for constructor and non-constructor call is
26825 * the same except for augmenting the created error. When
26826 * called as a constructor, the caller (duk_new()) will handle
26827 * augmentation; when called as normal function, we need to do
26828 * it here.
26829 */
26830
26831 duk_hthread *thr = (duk_hthread *) ctx;
26832 duk_small_int_t bidx_prototype = duk_get_current_magic(ctx);
26833
26834 /* same for both error and each subclass like TypeError */
26835 duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
26837
26838 DUK_UNREF(thr);
26839
26840 duk_push_object_helper(ctx, flags_and_class, bidx_prototype);
26841
26842 /* If message is undefined, the own property 'message' is not set at
26843 * all to save property space. An empty message is inherited anyway.
26844 */
26845 if (!duk_is_undefined(ctx, 0)) {
26846 duk_to_string(ctx, 0);
26847 duk_dup(ctx, 0); /* [ message error message ] */
26849 }
26850
26851 /* Augment the error if called as a normal function. __FILE__ and __LINE__
26852 * are not desirable in this case.
26853 */
26854
26855#ifdef DUK_USE_AUGMENT_ERROR_CREATE
26856 if (!duk_is_constructor_call(ctx)) {
26857 duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
26858 }
26859#endif
26860
26861 return 1;
26862}
26863
26865 /* XXX: optimize with more direct internal access */
26866
26867 duk_push_this(ctx);
26869
26870 /* [ ... this ] */
26871
26873 if (duk_is_undefined(ctx, -1)) {
26874 duk_pop(ctx);
26875 duk_push_string(ctx, "Error");
26876 } else {
26877 duk_to_string(ctx, -1);
26878 }
26879
26880 /* [ ... this name ] */
26881
26882 /* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
26883 * accident or are they actually needed? The first ToString()
26884 * could conceivably return 'undefined'.
26885 */
26887 if (duk_is_undefined(ctx, -1)) {
26888 duk_pop(ctx);
26889 duk_push_string(ctx, "");
26890 } else {
26891 duk_to_string(ctx, -1);
26892 }
26893
26894 /* [ ... this name message ] */
26895
26896 if (duk_get_length(ctx, -2) == 0) {
26897 /* name is empty -> return message */
26898 return 1;
26899 }
26900 if (duk_get_length(ctx, -1) == 0) {
26901 /* message is empty -> return name */
26902 duk_pop(ctx);
26903 return 1;
26904 }
26905 duk_push_string(ctx, ": ");
26906 duk_insert(ctx, -2); /* ... name ': ' message */
26907 duk_concat(ctx, 3);
26908
26909 return 1;
26910}
26911
26912#if defined(DUK_USE_TRACEBACKS)
26915 * Traceback handling
26917 * The unified helper decodes the traceback and produces various requested
26918 * outputs. It should be optimized for size, and may leave garbage on stack,
26919 * only the topmost return value matters. For instance, traceback separator
26920 * and decoded strings are pushed even when looking for filename only.
26921 *
26922 * NOTE: although _Tracedata is an internal property, user code can currently
26923 * write to the array (or replace it with something other than an array).
26924 * The code below must tolerate arbitrary _Tracedata. It can throw errors
26925 * etc, but cannot cause a segfault or memory unsafe behavior.
26926 */
26927
26928/* constants arbitrary, chosen for small loads */
26929#define DUK__OUTPUT_TYPE_TRACEBACK (-1)
26930#define DUK__OUTPUT_TYPE_FILENAME 0
26931#define DUK__OUTPUT_TYPE_LINENUMBER 1
26932
26934 duk_hthread *thr = (duk_hthread *) ctx;
26935 duk_idx_t idx_td;
26936 duk_small_int_t i; /* traceback depth fits into 16 bits */
26937 duk_small_int_t t; /* stack type fits into 16 bits */
26938 duk_small_int_t count_func = 0; /* traceback depth ensures fits into 16 bits */
26939 const char *str_tailcall = " tailcall";
26940 const char *str_strict = " strict";
26941 const char *str_construct = " construct";
26942 const char *str_prevyield = " preventsyield";
26943 const char *str_directeval = " directeval";
26944 const char *str_empty = "";
26945
26946 DUK_ASSERT_TOP(ctx, 0); /* fixed arg count */
26947 DUK_UNREF(thr);
26948
26949 duk_push_this(ctx);
26951 idx_td = duk_get_top_index(ctx);
26952
26954 duk_push_this(ctx);
26955
26956 /* [ ... this tracedata sep this ] */
26957
26958 /* XXX: skip null filename? */
26959
26960 if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
26961 /* Current tracedata contains 2 entries per callstack entry. */
26962 for (i = 0; ; i += 2) {
26963 duk_int_t pc;
26964 duk_int_t line;
26965 duk_int_t flags;
26966 duk_double_t d;
26967 const char *funcname;
26968 const char *filename;
26969 duk_hobject *h_func;
26970 duk_hstring *h_name;
26971
26972 duk_require_stack(ctx, 5);
26973 duk_get_prop_index(ctx, idx_td, i);
26974 duk_get_prop_index(ctx, idx_td, i + 1);
26975 d = duk_to_number(ctx, -1);
26977 flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
26978 t = (duk_small_int_t) duk_get_type(ctx, -2);
26979
26980 if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
26981 /*
26982 * Ecmascript/native function call or lightfunc call
26983 */
26984
26985 count_func++;
26986
26987 /* [ ... v1(func) v2(pc+flags) ] */
26988
26989 h_func = duk_get_hobject(ctx, -2); /* NULL for lightfunc */
26990
26993
26994#if defined(DUK_USE_PC2LINE)
26995 line = duk_hobject_pc2line_query(ctx, -4, (duk_uint_fast32_t) pc);
26996#else
26997 line = 0;
26998#endif
26999
27000 /* [ ... v1 v2 name filename ] */
27001
27002 /* When looking for .fileName/.lineNumber, blame first
27003 * function which has a .fileName.
27004 */
27005 if (duk_is_string(ctx, -1)) {
27006 if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
27007 return 1;
27008 } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
27009 duk_push_int(ctx, line);
27010 return 1;
27011 }
27012 }
27013
27014 /* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
27015 /* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
27016 h_name = duk_get_hstring(ctx, -2); /* may be NULL */
27017 funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
27018 "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
27019 filename = duk_get_string(ctx, -1);
27020 filename = filename ? filename : "";
27022 DUK_ASSERT(filename != NULL);
27023
27024 if (h_func == NULL) {
27025 duk_push_sprintf(ctx, "at %s light%s%s%s%s%s",
27026 (const char *) funcname,
27027 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27028 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27029 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27030 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27031 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27032 } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) {
27033 duk_push_sprintf(ctx, "at %s (%s) native%s%s%s%s%s",
27034 (const char *) funcname,
27035 (const char *) filename,
27036 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27037 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27038 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27039 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27040 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27041 } else {
27042 duk_push_sprintf(ctx, "at %s (%s:%ld)%s%s%s%s%s",
27043 (const char *) funcname,
27044 (const char *) filename,
27045 (long) line,
27046 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27047 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27048 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27049 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27050 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27051 }
27052 duk_replace(ctx, -5); /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
27053 duk_pop_n(ctx, 3); /* -> [ ... str ] */
27054 } else if (t == DUK_TYPE_STRING) {
27055 /*
27056 * __FILE__ / __LINE__ entry, here 'pc' is line number directly.
27057 * Sometimes __FILE__ / __LINE__ is reported as the source for
27058 * the error (fileName, lineNumber), sometimes not.
27059 */
27060
27061 /* [ ... v1(filename) v2(line+flags) ] */
27062
27063 /* When looking for .fileName/.lineNumber, blame compilation
27064 * or C call site unless flagged not to do so.
27065 */
27066 if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
27067 if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
27068 duk_pop(ctx);
27069 return 1;
27070 } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
27071 duk_push_int(ctx, pc);
27072 return 1;
27073 }
27074 }
27075
27076 duk_push_sprintf(ctx, "at [anon] (%s:%ld) internal",
27077 (const char *) duk_get_string(ctx, -2), (long) pc);
27078 duk_replace(ctx, -3); /* [ ... v1 v2 str ] -> [ ... str v2 ] */
27079 duk_pop(ctx); /* -> [ ... str ] */
27080 } else {
27081 /* unknown, ignore */
27082 duk_pop_2(ctx);
27083 break;
27084 }
27085 }
27086
27087 if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
27088 /* Possibly truncated; there is no explicit truncation
27089 * marker so this is the best we can do.
27090 */
27091
27093 }
27094 }
27095
27096 /* [ ... this tracedata sep this str1 ... strN ] */
27098 if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
27099 return 0;
27100 } else {
27101 /* The 'this' after 'sep' will get ToString() coerced by
27102 * duk_join() automatically. We don't want to do that
27103 * coercion when providing .fileName or .lineNumber (GH-254).
27104 */
27105 duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
27106 return 1;
27107 }
27108}
27109
27110/* XXX: Output type could be encoded into native function 'magic' value to
27111 * save space. For setters the stridx could be encoded into 'magic'.
27112 */
27113
27116}
27117
27120}
27121
27124}
27125
27126#undef DUK__OUTPUT_TYPE_TRACEBACK
27127#undef DUK__OUTPUT_TYPE_FILENAME
27128#undef DUK__OUTPUT_TYPE_LINENUMBER
27129
27130#else /* DUK_USE_TRACEBACKS */
27131
27132/*
27133 * Traceback handling when tracebacks disabled.
27134 *
27135 * The fileName / lineNumber stubs are now necessary because built-in
27136 * data will include the accessor properties in Error.prototype. If those
27137 * are removed for builds without tracebacks, these can also be removed.
27138 * 'stack' should still be present and produce a ToString() equivalent:
27139 * this is useful for user code which prints a stacktrace and expects to
27140 * see something useful. A normal stacktrace also begins with a ToString()
27141 * of the error so this makes sense.
27142 */
27143
27145 /* XXX: remove this native function and map 'stack' accessor
27146 * to the toString() implementation directly.
27147 */
27149}
27150
27152 DUK_UNREF(ctx);
27153 return 0;
27154}
27155
27157 DUK_UNREF(ctx);
27158 return 0;
27159}
27160
27161#endif /* DUK_USE_TRACEBACKS */
27162
27164 /* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
27165 * user code called Object.defineProperty() to create an overriding
27166 * own property. This allows user code to overwrite .fileName etc
27167 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
27168 * See https://github.com/svaarala/duktape/issues/387.
27169 */
27170
27171 DUK_ASSERT_TOP(ctx, 1); /* fixed arg count: value */
27173 duk_push_this(ctx);
27174 duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key);
27175 duk_dup(ctx, 0);
27177 /* [ ... obj key value ] */
27178
27179 DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
27180 duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1)));
27181
27184 DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
27186 return 0;
27187}
27188
27191}
27192
27195}
27196
27199}
27200/*
27201 * Function built-ins
27202 */
27203
27204/* include removed: duk_internal.h */
27205
27207 duk_hthread *thr = (duk_hthread *) ctx;
27208 duk_hstring *h_sourcecode;
27209 duk_idx_t nargs;
27210 duk_idx_t i;
27211 duk_small_uint_t comp_flags;
27213 duk_hobject *outer_lex_env;
27214 duk_hobject *outer_var_env;
27215
27216 /* normal and constructor calls have identical semantics */
27217
27218 nargs = duk_get_top(ctx);
27219 for (i = 0; i < nargs; i++) {
27220 duk_to_string(ctx, i);
27221 }
27222
27223 if (nargs == 0) {
27224 duk_push_string(ctx, "");
27225 duk_push_string(ctx, "");
27226 } else if (nargs == 1) {
27227 /* XXX: cover this with the generic >1 case? */
27228 duk_push_string(ctx, "");
27229 } else {
27230 duk_insert(ctx, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
27231 duk_push_string(ctx, ",");
27232 duk_insert(ctx, 1);
27233 duk_join(ctx, nargs - 1);
27234 }
27235
27236 /* [ body formals ], formals is comma separated list that needs to be parsed */
27237
27238 DUK_ASSERT_TOP(ctx, 2);
27239
27240 /* XXX: this placeholder is not always correct, but use for now.
27241 * It will fail in corner cases; see test-dev-func-cons-args.js.
27242 */
27243 duk_push_string(ctx, "function(");
27244 duk_dup(ctx, 1);
27245 duk_push_string(ctx, "){");
27246 duk_dup(ctx, 0);
27247 duk_push_string(ctx, "}");
27248 duk_concat(ctx, 5);
27249
27250 /* [ body formals source ] */
27251
27252 DUK_ASSERT_TOP(ctx, 3);
27253
27254 /* strictness is not inherited, intentional */
27255 comp_flags = DUK_JS_COMPILE_FLAG_FUNCEXPR;
27256
27257 duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */
27258 h_sourcecode = duk_require_hstring(ctx, -2);
27259 duk_js_compile(thr,
27260 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
27261 (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
27262 comp_flags);
27263 func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
27264 DUK_ASSERT(func != NULL);
27267 /* [ body formals source template ] */
27268
27269 /* only outer_lex_env matters, as functions always get a new
27270 * variable declaration environment.
27271 */
27273 outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
27274 outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
27275
27276 duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
27277
27278 /* [ body formals source template closure ] */
27279
27280 return 1;
27281}
27282
27284 /* ignore arguments, return undefined (E5 Section 15.3.4) */
27285 DUK_UNREF(ctx);
27286 return 0;
27287}
27288
27290 duk_tval *tv;
27291
27292 /*
27293 * E5 Section 15.3.4.2 places few requirements on the output of
27294 * this function:
27295 *
27296 * - The result is an implementation dependent representation
27297 * of the function; in particular
27298 *
27299 * - The result must follow the syntax of a FunctionDeclaration.
27300 * In particular, the function must have a name (even in the
27301 * case of an anonymous function or a function with an empty
27302 * name).
27303 *
27304 * - Note in particular that the output does NOT need to compile
27305 * into anything useful.
27306 */
27307
27308
27309 /* XXX: faster internal way to get this */
27310 duk_push_this(ctx);
27311 tv = duk_get_tval(ctx, -1);
27312 DUK_ASSERT(tv != NULL);
27313
27314 if (DUK_TVAL_IS_OBJECT(tv)) {
27316 const char *func_name;
27317
27318 /* Function name: missing/undefined is mapped to empty string,
27319 * otherwise coerce to string.
27320 */
27321 /* XXX: currently no handling for non-allowed identifier characters,
27322 * e.g. a '{' in the function name.
27323 */
27325 if (duk_is_undefined(ctx, -1)) {
27326 func_name = "";
27327 } else {
27328 func_name = duk_to_string(ctx, -1);
27329 DUK_ASSERT(func_name != NULL);
27330 }
27331
27332 /* Indicate function type in the function body using a dummy
27333 * directive.
27334 */
27336 duk_push_sprintf(ctx, "function %s() {\"ecmascript\"}", (const char *) func_name);
27337 } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
27338 duk_push_sprintf(ctx, "function %s() {\"native\"}", (const char *) func_name);
27339 } else if (DUK_HOBJECT_HAS_BOUND(obj)) {
27340 duk_push_sprintf(ctx, "function %s() {\"bound\"}", (const char *) func_name);
27341 } else {
27342 goto type_error;
27343 }
27344 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
27346 } else {
27347 goto type_error;
27348 }
27349
27350 return 1;
27351
27352 type_error:
27353 return DUK_RET_TYPE_ERROR;
27354}
27355
27357 duk_idx_t len;
27358 duk_idx_t i;
27359
27360 DUK_ASSERT_TOP(ctx, 2); /* not a vararg function */
27361
27362 duk_push_this(ctx);
27363 if (!duk_is_callable(ctx, -1)) {
27364 DUK_DDD(DUK_DDDPRINT("func is not callable"));
27365 goto type_error;
27366 }
27367 duk_insert(ctx, 0);
27368 DUK_ASSERT_TOP(ctx, 3);
27369
27370 DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT",
27371 (duk_tval *) duk_get_tval(ctx, 0),
27372 (duk_tval *) duk_get_tval(ctx, 1),
27373 (duk_tval *) duk_get_tval(ctx, 2)));
27374
27375 /* [ func thisArg argArray ] */
27376
27377 if (duk_is_null_or_undefined(ctx, 2)) {
27378 DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args"));
27379 len = 0;
27380 } else if (!duk_is_object(ctx, 2)) {
27381 goto type_error;
27382 } else {
27383 DUK_DDD(DUK_DDDPRINT("argArray is an object"));
27384
27385 /* XXX: make this an internal helper */
27387 len = (duk_idx_t) duk_to_uint32(ctx, -1); /* ToUint32() coercion required */
27388 duk_pop(ctx);
27389
27390 duk_require_stack(ctx, len);
27391
27392 DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len));
27393 for (i = 0; i < len; i++) {
27394 duk_get_prop_index(ctx, 2, i);
27395 }
27397 duk_remove(ctx, 2);
27398 DUK_ASSERT_TOP(ctx, 2 + len);
27399
27400 /* [ func thisArg arg1 ... argN ] */
27401
27402 DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld",
27403 (duk_tval *) duk_get_tval(ctx, 0),
27404 (duk_tval *) duk_get_tval(ctx, 1),
27405 (long) len));
27406 duk_call_method(ctx, len);
27407 return 1;
27408
27409 type_error:
27410 return DUK_RET_TYPE_ERROR;
27411}
27412
27414 duk_idx_t nargs;
27415
27416 /* Step 1 is not necessary because duk_call_method() will take
27417 * care of it.
27418 */
27419
27420 /* vararg function, thisArg needs special handling */
27421 nargs = duk_get_top(ctx); /* = 1 + arg count */
27422 if (nargs == 0) {
27423 duk_push_undefined(ctx);
27424 nargs++;
27425 }
27426 DUK_ASSERT(nargs >= 1);
27427
27428 /* [ thisArg arg1 ... argN ] */
27429
27430 duk_push_this(ctx); /* 'func' in the algorithm */
27431 duk_insert(ctx, 0);
27432
27433 /* [ func thisArg arg1 ... argN ] */
27434
27435 DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argcount=%ld, top=%ld",
27436 (duk_tval *) duk_get_tval(ctx, 0),
27437 (duk_tval *) duk_get_tval(ctx, 1),
27438 (long) (nargs - 1),
27439 (long) duk_get_top(ctx)));
27440 duk_call_method(ctx, nargs - 1);
27441 return 1;
27442}
27443
27444/* XXX: the implementation now assumes "chained" bound functions,
27445 * whereas "collapsed" bound functions (where there is ever only
27446 * one bound function which directly points to a non-bound, final
27447 * function) would require a "collapsing" implementation which
27448 * merges argument lists etc here.
27449 */
27451 duk_hobject *h_bound;
27452 duk_hobject *h_target;
27453 duk_idx_t nargs;
27454 duk_idx_t i;
27455
27456 /* vararg function, careful arg handling (e.g. thisArg may not be present) */
27457 nargs = duk_get_top(ctx); /* = 1 + arg count */
27458 if (nargs == 0) {
27459 duk_push_undefined(ctx);
27460 nargs++;
27461 }
27462 DUK_ASSERT(nargs >= 1);
27463
27464 duk_push_this(ctx);
27465 if (!duk_is_callable(ctx, -1)) {
27466 DUK_DDD(DUK_DDDPRINT("func is not callable"));
27467 goto type_error;
27468 }
27469
27470 /* [ thisArg arg1 ... argN func ] (thisArg+args == nargs total) */
27471 DUK_ASSERT_TOP(ctx, nargs + 1);
27472
27473 /* create bound function object */
27480 h_bound = duk_get_hobject(ctx, -1);
27481 DUK_ASSERT(h_bound != NULL);
27482
27483 /* [ thisArg arg1 ... argN func boundFunc ] */
27484 duk_dup(ctx, -2); /* func */
27486
27487 duk_dup(ctx, 0); /* thisArg */
27489
27490 duk_push_array(ctx);
27491
27492 /* [ thisArg arg1 ... argN func boundFunc argArray ] */
27493
27494 for (i = 0; i < nargs - 1; i++) {
27495 duk_dup(ctx, 1 + i);
27496 duk_put_prop_index(ctx, -2, i);
27497 }
27499
27500 /* [ thisArg arg1 ... argN func boundFunc ] */
27501
27502 /* bound function 'length' property is interesting */
27503 h_target = duk_get_hobject(ctx, -2);
27504 if (h_target == NULL || /* lightfunc */
27506 /* For lightfuncs, simply read the virtual property. */
27507 duk_int_t tmp;
27509 tmp = duk_to_int(ctx, -1) - (nargs - 1); /* step 15.a */
27510 duk_pop(ctx);
27511 duk_push_int(ctx, (tmp < 0 ? 0 : tmp));
27512 } else {
27513 duk_push_int(ctx, 0);
27514 }
27515 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); /* attrs in E5 Section 15.3.5.1 */
27516
27517 /* caller and arguments must use the same thrower, [[ThrowTypeError]] */
27520
27521 /* these non-standard properties are copied for convenience */
27522 /* XXX: 'copy properties' API call? */
27527
27528 /* The 'strict' flag is copied to get the special [[Get]] of E5.1
27529 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
27530 * function. Not sure if this is correct, because the specification
27531 * is a bit ambiguous on this point but it would make sense.
27532 */
27533 if (h_target == NULL) {
27534 /* Lightfuncs are always strict. */
27535 DUK_HOBJECT_SET_STRICT(h_bound);
27536 } else if (DUK_HOBJECT_HAS_STRICT(h_target)) {
27537 DUK_HOBJECT_SET_STRICT(h_bound);
27538 }
27539 DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
27540
27541 return 1;
27542
27543 type_error:
27544 return DUK_RET_TYPE_ERROR;
27545}
27546/*
27547 * Global object built-ins
27548 */
27549
27550/* include removed: duk_internal.h */
27552/*
27553 * Encoding/decoding helpers
27555
27556/* XXX: Could add fast path (for each transform callback) with direct byte
27557 * lookups (no shifting) and no explicit check for x < 0x80 before table
27558 * lookup.
27559 */
27560
27561/* Macros for creating and checking bitmasks for character encoding.
27562 * Bit number is a bit counterintuitive, but minimizes code size.
27563 */
27564#define DUK__MKBITS(a,b,c,d,e,f,g,h) ((duk_uint8_t) ( \
27565 ((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
27566 ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
27567 ))
27568#define DUK__CHECK_BITMASK(table,cp) ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
27569
27570/* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
27571DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
27572 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27573 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27574 DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x20-0x2f */
27575 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
27576 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
27577 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
27578 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
27579 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
27580};
27581
27582/* E5.1 Section 15.1.3.4: uriUnescaped */
27584 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27585 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27586 DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0), /* 0x20-0x2f */
27587 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
27588 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
27589 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
27590 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
27591 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
27592};
27593
27594/* E5.1 Section 15.1.3.1: uriReserved + '#' */
27595DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
27596 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27597 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27598 DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1), /* 0x20-0x2f */
27599 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
27600 DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
27601 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
27602 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
27603 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
27604};
27605
27606/* E5.1 Section 15.1.3.2: empty */
27608 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27609 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27610 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x20-0x2f */
27611 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
27612 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
27613 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
27614 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
27615 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
27616};
27618#ifdef DUK_USE_SECTION_B
27619/* E5.1 Section B.2.2, step 7. */
27621 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27622 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27623 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1), /* 0x20-0x2f */
27624 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
27625 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
27626 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
27627 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
27628 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0) /* 0x70-0x7f */
27630#endif /* DUK_USE_SECTION_B */
27631
27632#undef DUK__MKBITS
27633
27634typedef struct {
27635 duk_hthread *thr;
27636 duk_hstring *h_str;
27638 const duk_uint8_t *p;
27639 const duk_uint8_t *p_start;
27640 const duk_uint8_t *p_end;
27642
27643typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
27644
27645/* XXX: refactor and share with other code */
27647 duk_small_int_t ch;
27648 duk_small_int_t t = 0;
27649
27650 while (n > 0) {
27651 t = t * 16;
27652 ch = (duk_small_int_t) duk_hex_dectab[*p++];
27653 if (DUK_LIKELY(ch >= 0)) {
27654 t += ch;
27655 } else {
27656 return -1;
27657 }
27658 n--;
27659 }
27660 return t;
27661}
27662
27663DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, const void *udata) {
27664 duk_hthread *thr = (duk_hthread *) ctx;
27665 duk__transform_context tfm_ctx_alloc;
27666 duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
27667 duk_codepoint_t cp;
27668
27669 tfm_ctx->thr = thr;
27670
27671 tfm_ctx->h_str = duk_to_hstring(ctx, 0);
27672 DUK_ASSERT(tfm_ctx->h_str != NULL);
27673
27674 DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */
27675
27676 tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
27677 tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
27678 tfm_ctx->p = tfm_ctx->p_start;
27679
27680 while (tfm_ctx->p < tfm_ctx->p_end) {
27681 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
27682 callback(tfm_ctx, udata, cp);
27683 }
27684
27685 DUK_BW_COMPACT(thr, &tfm_ctx->bw);
27686
27687 duk_to_string(ctx, -1);
27688 return 1;
27689}
27690
27692 duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
27693 duk_small_int_t len;
27694 duk_codepoint_t cp1, cp2;
27695 duk_small_int_t i, t;
27696 const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
27697
27698 /* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
27699 * Codepoint range is restricted so this is a slightly too large
27700 * but doesn't matter.
27701 */
27702 DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
27703
27704 if (cp < 0) {
27705 goto uri_error;
27706 } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
27707 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
27708 return;
27709 } else if (cp >= 0xdc00L && cp <= 0xdfffL) {
27710 goto uri_error;
27711 } else if (cp >= 0xd800L && cp <= 0xdbffL) {
27712 /* Needs lookahead */
27713 if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
27714 goto uri_error;
27715 }
27716 if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
27717 goto uri_error;
27718 }
27719 cp1 = cp;
27720 cp = ((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L;
27721 } else if (cp > 0x10ffffL) {
27722 /* Although we can allow non-BMP characters (they'll decode
27723 * back into surrogate pairs), we don't allow extended UTF-8
27724 * characters; they would encode to URIs which won't decode
27725 * back because of strict UTF-8 checks in URI decoding.
27726 * (However, we could just as well allow them here.)
27727 */
27728 goto uri_error;
27729 } else {
27730 /* Non-BMP characters within valid UTF-8 range: encode as is.
27731 * They'll decode back into surrogate pairs if the escaped
27732 * output is decoded.
27733 */
27734 ;
27735 }
27737 len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
27738 for (i = 0; i < len; i++) {
27739 t = (int) xutf8_buf[i];
27740 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27741 &tfm_ctx->bw,
27743 (duk_uint8_t) duk_uc_nybbles[t >> 4],
27744 (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
27745 }
27746
27747 return;
27748
27749 uri_error:
27750 DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
27751}
27752
27754 const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
27755 duk_small_uint_t utf8_blen;
27756 duk_codepoint_t min_cp;
27757 duk_small_int_t t; /* must be signed */
27759
27760 /* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
27761 * percent escape path writes max two times CESU-8 encoded BMP length.
27762 */
27763 DUK_BW_ENSURE(tfm_ctx->thr,
27764 &tfm_ctx->bw,
27767
27768 if (cp == (duk_codepoint_t) '%') {
27769 const duk_uint8_t *p = tfm_ctx->p;
27770 duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
27771
27772 DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
27773
27774 if (left < 2) {
27775 goto uri_error;
27776 }
27777
27778 t = duk__decode_hex_escape(p, 2);
27779 DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
27780 if (t < 0) {
27781 goto uri_error;
27782 }
27783
27784 if (t < 0x80) {
27785 if (DUK__CHECK_BITMASK(reserved_table, t)) {
27786 /* decode '%xx' to '%xx' if decoded char in reserved set */
27787 DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
27788 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27789 &tfm_ctx->bw,
27791 p[0],
27792 p[1]);
27793 } else {
27794 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
27795 }
27796 tfm_ctx->p += 2;
27797 return;
27798 }
27799
27800 /* Decode UTF-8 codepoint from a sequence of hex escapes. The
27801 * first byte of the sequence has been decoded to 't'.
27802 *
27803 * Note that UTF-8 validation must be strict according to the
27804 * specification: E5.1 Section 15.1.3, decode algorithm step
27805 * 4.d.vii.8. URIError from non-shortest encodings is also
27806 * specifically noted in the spec.
27807 */
27808
27809 DUK_ASSERT(t >= 0x80);
27810 if (t < 0xc0) {
27811 /* continuation byte */
27812 goto uri_error;
27813 } else if (t < 0xe0) {
27814 /* 110x xxxx; 2 bytes */
27815 utf8_blen = 2;
27816 min_cp = 0x80L;
27817 cp = t & 0x1f;
27818 } else if (t < 0xf0) {
27819 /* 1110 xxxx; 3 bytes */
27820 utf8_blen = 3;
27821 min_cp = 0x800L;
27822 cp = t & 0x0f;
27823 } else if (t < 0xf8) {
27824 /* 1111 0xxx; 4 bytes */
27825 utf8_blen = 4;
27826 min_cp = 0x10000L;
27827 cp = t & 0x07;
27828 } else {
27829 /* extended utf-8 not allowed for URIs */
27830 goto uri_error;
27831 }
27832
27833 if (left < utf8_blen * 3 - 1) {
27834 /* '%xx%xx...%xx', p points to char after first '%' */
27835 goto uri_error;
27836 }
27837
27838 p += 3;
27839 for (i = 1; i < utf8_blen; i++) {
27840 /* p points to digit part ('%xy', p points to 'x') */
27841 t = duk__decode_hex_escape(p, 2);
27842 DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
27843 (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
27844 if (t < 0) {
27845 goto uri_error;
27846 }
27847 if ((t & 0xc0) != 0x80) {
27848 goto uri_error;
27849 }
27850 cp = (cp << 6) + (t & 0x3f);
27851 p += 3;
27852 }
27853 p--; /* p overshoots */
27854 tfm_ctx->p = p;
27855
27856 DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
27857
27858 if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
27859 goto uri_error;
27860 }
27861
27862 /* The E5.1 algorithm checks whether or not a decoded codepoint
27863 * is below 0x80 and perhaps may be in the "reserved" set.
27864 * This seems pointless because the single byte UTF-8 case is
27865 * handled separately, and non-shortest encodings are rejected.
27866 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
27867 * the reserved set.
27868 */
27869
27870 /* utf-8 validation ensures these */
27871 DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
27872
27873 if (cp >= 0x10000L) {
27874 cp -= 0x10000L;
27875 DUK_ASSERT(cp < 0x100000L);
27876
27877 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
27878 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffUL) + 0xdc00L));
27879 } else {
27880 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
27881 }
27882 } else {
27883 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
27884 }
27885 return;
27886
27887 uri_error:
27888 DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
27889}
27890
27891#ifdef DUK_USE_SECTION_B
27893 DUK_UNREF(udata);
27894
27895 DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
27896
27897 if (cp < 0) {
27898 goto esc_error;
27899 } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
27900 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
27901 } else if (cp < 0x100L) {
27902 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27903 &tfm_ctx->bw,
27904 (duk_uint8_t) DUK_ASC_PERCENT,
27905 (duk_uint8_t) duk_uc_nybbles[cp >> 4],
27906 (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
27907 } else if (cp < 0x10000L) {
27908 DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
27909 &tfm_ctx->bw,
27910 (duk_uint8_t) DUK_ASC_PERCENT,
27911 (duk_uint8_t) DUK_ASC_LC_U,
27912 (duk_uint8_t) duk_uc_nybbles[cp >> 12],
27913 (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
27914 (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
27915 (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
27916 } else {
27917 /* Characters outside BMP cannot be escape()'d. We could
27918 * encode them as surrogate pairs (for codepoints inside
27919 * valid UTF-8 range, but not extended UTF-8). Because
27920 * escape() and unescape() are legacy functions, we don't.
27921 */
27922 goto esc_error;
27923 }
27924
27925 return;
27926
27927 esc_error:
27928 DUK_ERROR_TYPE(tfm_ctx->thr, "invalid input");
27929}
27930
27933
27934 DUK_UNREF(udata);
27935
27936 if (cp == (duk_codepoint_t) '%') {
27937 const duk_uint8_t *p = tfm_ctx->p;
27938 duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
27939
27940 if (left >= 5 && p[0] == 'u' &&
27941 ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
27942 cp = (duk_codepoint_t) t;
27943 tfm_ctx->p += 5;
27944 } else if (left >= 2 &&
27945 ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
27946 cp = (duk_codepoint_t) t;
27947 tfm_ctx->p += 2;
27948 }
27950
27951 DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
27952}
27953#endif /* DUK_USE_SECTION_B */
27954
27955/*
27956 * Eval
27957 *
27958 * Eval needs to handle both a "direct eval" and an "indirect eval".
27959 * Direct eval handling needs access to the caller's activation so that its
27960 * lexical environment can be accessed. A direct eval is only possible from
27961 * Ecmascript code; an indirect eval call is possible also from C code.
27962 * When an indirect eval call is made from C code, there may not be a
27963 * calling activation at all which needs careful handling.
27964 */
27965
27967 duk_hthread *thr = (duk_hthread *) ctx;
27968 duk_hstring *h;
27969 duk_activation *act_caller;
27970 duk_activation *act_eval;
27971 duk_activation *act;
27973 duk_hobject *outer_lex_env;
27974 duk_hobject *outer_var_env;
27975 duk_bool_t this_to_global = 1;
27976 duk_small_uint_t comp_flags;
27977 duk_int_t level = -2;
27978
27979 DUK_ASSERT(duk_get_top(ctx) == 1 || duk_get_top(ctx) == 2); /* 2 when called by debugger */
27980 DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */
27981 DUK_ASSERT(((thr->callstack + thr->callstack_top - 1)->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
27982 (thr->callstack_top >= 2)); /* if direct eval, calling activation must exist */
27983
27984 /*
27985 * callstack_top - 1 --> this function
27986 * callstack_top - 2 --> caller (may not exist)
27987 *
27988 * If called directly from C, callstack_top might be 1. If calling
27989 * activation doesn't exist, call must be indirect.
27990 */
27991
27992 h = duk_get_hstring(ctx, 0);
27993 if (!h) {
27994 return 1; /* return arg as-is */
27995 }
27996
27997#if defined(DUK_USE_DEBUGGER_SUPPORT)
27998 /* NOTE: level is used only by the debugger and should never be present
27999 * for an Ecmascript eval().
28000 */
28001 DUK_ASSERT(level == -2); /* by default, use caller's environment */
28002 if (duk_get_top(ctx) >= 2 && duk_is_number(ctx, 1)) {
28003 level = duk_get_int(ctx, 1);
28004 }
28005 DUK_ASSERT(level <= -2); /* This is guaranteed by debugger code. */
28006#endif
28007
28008 /* [ source ] */
28009
28010 comp_flags = DUK_JS_COMPILE_FLAG_EVAL;
28011 act_eval = thr->callstack + thr->callstack_top - 1; /* this function */
28012 if (thr->callstack_top >= (duk_size_t) -level) {
28013 /* Have a calling activation, check for direct eval (otherwise
28014 * assume indirect eval.
28015 */
28016 act_caller = thr->callstack + thr->callstack_top + level; /* caller */
28017 if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
28018 (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
28019 /* Only direct eval inherits strictness from calling code
28020 * (E5.1 Section 10.1.1).
28021 */
28022 comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
28023 }
28024 } else {
28025 DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
28026 }
28027 act_caller = NULL; /* avoid dereference after potential callstack realloc */
28028 act_eval = NULL;
28029
28030 duk_push_hstring_stridx(ctx, DUK_STRIDX_INPUT); /* XXX: copy from caller? */
28031 duk_js_compile(thr,
28032 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
28034 comp_flags);
28035 func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
28036 DUK_ASSERT(func != NULL);
28038
28039 /* [ source template ] */
28040
28041 /* E5 Section 10.4.2 */
28042 DUK_ASSERT(thr->callstack_top >= 1);
28043 act = thr->callstack + thr->callstack_top - 1; /* this function */
28044 if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
28045 DUK_ASSERT(thr->callstack_top >= 2);
28046 act = thr->callstack + thr->callstack_top + level; /* caller */
28047 if (act->lex_env == NULL) {
28048 DUK_ASSERT(act->var_env == NULL);
28049 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
28050
28051 /* this may have side effects, so re-lookup act */
28053 act = thr->callstack + thr->callstack_top + level;
28054 }
28055 DUK_ASSERT(act->lex_env != NULL);
28056 DUK_ASSERT(act->var_env != NULL);
28057
28058 this_to_global = 0;
28059
28060 if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
28061 duk_hobject *new_env;
28062 duk_hobject *act_lex_env;
28063
28064 DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
28065 "var_env and lex_env to a fresh env, "
28066 "this_binding to caller's this_binding"));
28067
28068 act = thr->callstack + thr->callstack_top + level; /* caller */
28069 act_lex_env = act->lex_env;
28070 act = NULL; /* invalidated */
28071
28075 act_lex_env);
28076 new_env = duk_require_hobject(ctx, -1);
28077 DUK_ASSERT(new_env != NULL);
28078 DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO",
28079 (duk_heaphdr *) new_env));
28080
28081 outer_lex_env = new_env;
28082 outer_var_env = new_env;
28083
28084 duk_insert(ctx, 0); /* stash to bottom of value stack to keep new_env reachable for duration of eval */
28085
28086 /* compiler's responsibility */
28088 } else {
28089 DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
28090 "var_env and lex_env to caller's envs, "
28091 "this_binding to caller's this_binding"));
28092
28093 outer_lex_env = act->lex_env;
28094 outer_var_env = act->var_env;
28095
28096 /* compiler's responsibility */
28098 }
28099 } else {
28100 DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
28101 "global object, this_binding to global object"));
28102
28103 this_to_global = 1;
28104 outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
28105 outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
28106 }
28107 act = NULL;
28108
28109 /* Eval code doesn't need an automatic .prototype object. */
28110 duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
28111
28112 /* [ source template closure ] */
28113
28114 if (this_to_global) {
28117 } else {
28118 duk_tval *tv;
28119 DUK_ASSERT(thr->callstack_top >= 2);
28120 act = thr->callstack + thr->callstack_top + level; /* caller */
28121 tv = thr->valstack + act->idx_bottom - 1; /* this is just beneath bottom */
28122 DUK_ASSERT(tv >= thr->valstack);
28123 duk_push_tval(ctx, tv);
28124 }
28125
28126 DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
28127 (duk_heaphdr *) outer_lex_env,
28128 (duk_heaphdr *) outer_var_env,
28129 duk_get_tval(ctx, -1)));
28130
28131 /* [ source template closure this ] */
28132
28133 duk_call_method(ctx, 0);
28134
28135 /* [ source template result ] */
28136
28137 return 1;
28138}
28139
28140/*
28141 * Parsing of ints and floats
28142 */
28143
28145 duk_int32_t radix;
28146 duk_small_uint_t s2n_flags;
28147
28148 DUK_ASSERT_TOP(ctx, 2);
28149 duk_to_string(ctx, 0);
28150
28151 radix = duk_to_int32(ctx, 1);
28152
28153 s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
28159
28160 /* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
28161 *
28162 * Don't autodetect octals (from leading zeroes), require user code to
28163 * provide an explicit radix 8 for parsing octal. See write-up from Mozilla:
28164 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
28165 */
28166
28167 if (radix != 0) {
28168 if (radix < 2 || radix > 36) {
28169 goto ret_nan;
28171 if (radix != 16) {
28172 s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
28173 }
28174 } else {
28175 radix = 10;
28176 }
28177
28178 duk_dup(ctx, 0);
28179 duk_numconv_parse(ctx, radix, s2n_flags);
28180 return 1;
28181
28182 ret_nan:
28183 duk_push_nan(ctx);
28184 return 1;
28185}
28186
28188 duk_small_uint_t s2n_flags;
28189 duk_int32_t radix;
28190
28191 DUK_ASSERT_TOP(ctx, 1);
28192 duk_to_string(ctx, 0);
28193
28194 radix = 10;
28195
28196 /* XXX: check flags */
28197 s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
28207
28208 duk_numconv_parse(ctx, radix, s2n_flags);
28209 return 1;
28210}
28211
28212/*
28213 * Number checkers
28214 */
28218 duk_push_boolean(ctx, DUK_ISNAN(d));
28219 return 1;
28220}
28221
28225 return 1;
28226}
28228/*
28229 * URI handling
28230 */
28231
28235
28239
28242}
28243
28246}
28247
28248#ifdef DUK_USE_SECTION_B
28250 return duk__transform_helper(ctx, duk__transform_callback_escape, (const void *) NULL);
28251}
28254 return duk__transform_helper(ctx, duk__transform_callback_unescape, (const void *) NULL);
28255}
28256#else /* DUK_USE_SECTION_B */
28258 DUK_UNREF(ctx);
28260}
28261
28263 DUK_UNREF(ctx);
28265}
28266#endif /* DUK_USE_SECTION_B */
28267
28268#if defined(DUK_USE_BROWSER_LIKE) && (defined(DUK_USE_FILE_IO) || defined(DUK_USE_DEBUGGER_SUPPORT))
28270 duk_hthread *thr = (duk_hthread *) ctx;
28271 duk_int_t magic;
28272 duk_idx_t nargs;
28273 const duk_uint8_t *buf;
28274 duk_size_t sz_buf;
28275 const char nl = (const char) DUK_ASC_LF;
28276#ifndef DUK_USE_PREFER_SIZE
28277 duk_uint8_t buf_stack[256];
28278#endif
28279#ifdef DUK_USE_FILE_IO
28280 duk_file *f_out;
28281#endif
28282
28283 DUK_UNREF(thr);
28284
28285 magic = duk_get_current_magic(ctx);
28286 DUK_UNREF(magic);
28287
28288 nargs = duk_get_top(ctx);
28289
28290 /* If argument count is 1 and first argument is a buffer, write the buffer
28291 * as raw data into the file without a newline; this allows exact control
28292 * over stdout/stderr without an additional entrypoint (useful for now).
28293 *
28294 * Otherwise current print/alert semantics are to ToString() coerce
28295 * arguments, join them with a single space, and append a newline.
28296 */
28297
28298 if (nargs == 1 && duk_is_buffer(ctx, 0)) {
28299 buf = (const duk_uint8_t *) duk_get_buffer(ctx, 0, &sz_buf);
28300 DUK_ASSERT(buf != NULL);
28301 } else if (nargs > 0) {
28302#ifdef DUK_USE_PREFER_SIZE
28303 /* Compact but lots of churn. */
28305 duk_insert(ctx, 0);
28306 duk_join(ctx, nargs);
28307 duk_push_string(thr, "\n");
28308 duk_concat(ctx, 2);
28309 buf = (const duk_uint8_t *) duk_get_lstring(ctx, -1, &sz_buf);
28310 DUK_ASSERT(buf != NULL);
28311#else /* DUK_USE_PREFER_SIZE */
28312 /* Higher footprint, less churn. */
28313 duk_idx_t i;
28314 duk_size_t sz_str;
28315 const duk_uint8_t *p_str;
28316 duk_uint8_t *p;
28317
28318 sz_buf = (duk_size_t) nargs; /* spaces (nargs - 1) + newline */
28319 for (i = 0; i < nargs; i++) {
28320 (void) duk_to_lstring(ctx, i, &sz_str);
28321 sz_buf += sz_str;
28322 }
28323
28324 if (sz_buf <= sizeof(buf_stack)) {
28325 p = (duk_uint8_t *) buf_stack;
28326 } else {
28327 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sz_buf);
28328 DUK_ASSERT(p != NULL);
28329 }
28330
28331 buf = (const duk_uint8_t *) p;
28332 for (i = 0; i < nargs; i++) {
28333 p_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &sz_str);
28334 DUK_ASSERT(p_str != NULL);
28335 DUK_MEMCPY((void *) p, (const void *) p_str, sz_str);
28336 p += sz_str;
28337 *p++ = (duk_uint8_t) (i == nargs - 1 ? DUK_ASC_LF : DUK_ASC_SPACE);
28338 }
28339 DUK_ASSERT((const duk_uint8_t *) p == buf + sz_buf);
28340#endif /* DUK_USE_PREFER_SIZE */
28341 } else {
28342 buf = (const duk_uint8_t *) &nl;
28343 sz_buf = 1;
28344 }
28345
28346 /* 'buf' contains the string to write, 'sz_buf' contains the length
28347 * (which may be zero).
28348 */
28349 DUK_ASSERT(buf != NULL);
28350
28351 if (sz_buf == 0) {
28352 return 0;
28353 }
28354
28355#ifdef DUK_USE_FILE_IO
28356 f_out = (magic ? DUK_STDERR : DUK_STDOUT);
28357 DUK_FWRITE((const void *) buf, 1, (size_t) sz_buf, f_out);
28358 DUK_FFLUSH(f_out);
28359#endif
28360
28361#if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_PRINTALERT)
28362 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
28363 duk_debug_write_notify(thr, magic ? DUK_DBG_CMD_ALERT : DUK_DBG_CMD_PRINT);
28364 duk_debug_write_string(thr, (const char *) buf, sz_buf);
28365 duk_debug_write_eom(thr);
28366 }
28367#endif
28368 return 0;
28369}
28370#elif defined(DUK_USE_BROWSER_LIKE) /* print provider */
28372 DUK_UNREF(ctx);
28373 return 0;
28374}
28375#else /* print provider */
28377 DUK_UNREF(ctx);
28379}
28380#endif /* print provider */
28381
28382/*
28383 * CommonJS require() and modules support
28384 */
28385
28386#if defined(DUK_USE_COMMONJS_MODULES)
28387DUK_LOCAL void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) {
28388 duk_hthread *thr = (duk_hthread *) ctx;
28389 duk_uint8_t buf[DUK_BI_COMMONJS_MODULE_ID_LIMIT];
28390 duk_uint8_t *p;
28391 duk_uint8_t *q;
28392 duk_uint8_t *q_last; /* last component */
28393 duk_int_t int_rc;
28394
28395 DUK_ASSERT(req_id != NULL);
28396 /* mod_id may be NULL */
28397
28398 /*
28399 * A few notes on the algorithm:
28400 *
28401 * - Terms are not allowed to begin with a period unless the term
28402 * is either '.' or '..'. This simplifies implementation (and
28403 * is within CommonJS modules specification).
28404 *
28405 * - There are few output bound checks here. This is on purpose:
28406 * the resolution input is length checked and the output is never
28407 * longer than the input. The resolved output is written directly
28408 * over the input because it's never longer than the input at any
28409 * point in the algorithm.
28410 *
28411 * - Non-ASCII characters are processed as individual bytes and
28412 * need no special treatment. However, U+0000 terminates the
28413 * algorithm; this is not an issue because U+0000 is not a
28414 * desirable term character anyway.
28415 */
28416
28417 /*
28418 * Set up the resolution input which is the requested ID directly
28419 * (if absolute or no current module path) or with current module
28420 * ID prepended (if relative and current module path exists).
28421 *
28422 * Suppose current module is 'foo/bar' and relative path is './quux'.
28423 * The 'bar' component must be replaced so the initial input here is
28424 * 'foo/bar/.././quux'.
28425 */
28426
28427 if (mod_id != NULL && req_id[0] == '.') {
28428 int_rc = DUK_SNPRINTF((char *) buf, sizeof(buf), "%s/../%s", mod_id, req_id);
28429 } else {
28430 int_rc = DUK_SNPRINTF((char *) buf, sizeof(buf), "%s", req_id);
28431 }
28432 if (int_rc >= (duk_int_t) sizeof(buf) || int_rc < 0) {
28433 /* Potentially truncated, NUL not guaranteed in any case.
28434 * The (int_rc < 0) case should not occur in practice.
28435 */
28436 DUK_DD(DUK_DDPRINT("resolve error: temporary working module ID doesn't fit into resolve buffer"));
28437 goto resolve_error;
28438 }
28439 DUK_ASSERT(DUK_STRLEN((const char *) buf) < sizeof(buf)); /* at most sizeof(buf) - 1 */
28440
28441 DUK_DDD(DUK_DDDPRINT("input module id: '%s'", (const char *) buf));
28442
28443 /*
28444 * Resolution loop. At the top of the loop we're expecting a valid
28445 * term: '.', '..', or a non-empty identifier not starting with a period.
28446 */
28447
28448 p = buf;
28449 q = buf;
28450 for (;;) {
28452
28453 /* Here 'p' always points to the start of a term.
28454 *
28455 * We can also unconditionally reset q_last here: if this is
28456 * the last (non-empty) term q_last will have the right value
28457 * on loop exit.
28458 */
28459
28460 DUK_ASSERT(p >= q); /* output is never longer than input during resolution */
28461
28462 DUK_DDD(DUK_DDDPRINT("resolve loop top: p -> '%s', q=%p, buf=%p",
28463 (const char *) p, (void *) q, (void *) buf));
28464
28465 q_last = q;
28466
28467 c = *p++;
28468 if (DUK_UNLIKELY(c == 0)) {
28469 DUK_DD(DUK_DDPRINT("resolve error: requested ID must end with a non-empty term"));
28470 goto resolve_error;
28471 } else if (DUK_UNLIKELY(c == '.')) {
28472 c = *p++;
28473 if (c == '/') {
28474 /* Term was '.' and is eaten entirely (including dup slashes). */
28475 goto eat_dup_slashes;
28476 }
28477 if (c == '.' && *p == '/') {
28478 /* Term was '..', backtrack resolved name by one component.
28479 * q[-1] = previous slash (or beyond start of buffer)
28480 * q[-2] = last char of previous component (or beyond start of buffer)
28481 */
28482 p++; /* eat (first) input slash */
28483 DUK_ASSERT(q >= buf);
28484 if (q == buf) {
28485 DUK_DD(DUK_DDPRINT("resolve error: term was '..' but nothing to backtrack"));
28486 goto resolve_error;
28487 }
28488 DUK_ASSERT(*(q - 1) == '/');
28489 q--; /* backtrack to last output slash (dups already eliminated) */
28490 for (;;) {
28491 /* Backtrack to previous slash or start of buffer. */
28492 DUK_ASSERT(q >= buf);
28493 if (q == buf) {
28494 break;
28495 }
28496 if (*(q - 1) == '/') {
28497 break;
28498 }
28499 q--;
28500 }
28501 goto eat_dup_slashes;
28502 }
28503 DUK_DD(DUK_DDPRINT("resolve error: term begins with '.' but is not '.' or '..' (not allowed now)"));
28504 goto resolve_error;
28505 } else if (DUK_UNLIKELY(c == '/')) {
28506 /* e.g. require('/foo'), empty terms not allowed */
28507 DUK_DD(DUK_DDPRINT("resolve error: empty term (not allowed now)"));
28508 goto resolve_error;
28509 } else {
28510 for (;;) {
28511 /* Copy term name until end or '/'. */
28512 *q++ = c;
28513 c = *p++;
28514 if (DUK_UNLIKELY(c == 0)) {
28515 /* This was the last term, and q_last was
28516 * updated to match this term at loop top.
28517 */
28518 goto loop_done;
28519 } else if (DUK_UNLIKELY(c == '/')) {
28520 *q++ = '/';
28521 break;
28522 } else {
28523 /* write on next loop */
28524 }
28525 }
28526 }
28527
28528 eat_dup_slashes:
28529 for (;;) {
28530 /* eat dup slashes */
28531 c = *p;
28532 if (DUK_LIKELY(c != '/')) {
28533 break;
28534 }
28535 p++;
28536 }
28537 }
28538 loop_done:
28539 /* Output #1: resolved absolute name */
28540 DUK_ASSERT(q >= buf);
28541 duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
28543 /* Output #2: last component name */
28544 DUK_ASSERT(q >= q_last);
28545 DUK_ASSERT(q_last >= buf);
28546 duk_push_lstring(ctx, (const char *) q_last, (size_t) (q - q_last));
28548 DUK_DD(DUK_DDPRINT("after resolving module name: buf=%p, q_last=%p, q=%p",
28549 (void *) buf, (void *) q_last, (void *) q));
28550 return;
28552 resolve_error:
28553 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "cannot resolve module id: %s", (const char *) req_id);
28555#endif /* DUK_USE_COMMONJS_MODULES */
28556
28557#if defined(DUK_USE_COMMONJS_MODULES)
28558/* Stack indices for better readability */
28559#define DUK__IDX_REQUESTED_ID 0 /* Module id requested */
28560#define DUK__IDX_REQUIRE 1 /* Current require() function */
28561#define DUK__IDX_REQUIRE_ID 2 /* The base ID of the current require() function, resolution base */
28562#define DUK__IDX_RESOLVED_ID 3 /* Resolved, normalized absolute module ID */
28563#define DUK__IDX_LASTCOMP 4 /* Last component name in resolved path */
28564#define DUK__IDX_DUKTAPE 5 /* Duktape object */
28565#define DUK__IDX_MODLOADED 6 /* Duktape.modLoaded[] module cache */
28566#define DUK__IDX_UNDEFINED 7 /* 'undefined', artifact of lookup */
28567#define DUK__IDX_FRESH_REQUIRE 8 /* New require() function for module, updated resolution base */
28568#define DUK__IDX_EXPORTS 9 /* Default exports table */
28569#define DUK__IDX_MODULE 10 /* Module object containing module.exports, etc */
28570
28572 const char *str_req_id; /* requested identifier */
28573 const char *str_mod_id; /* require.id of current module */
28574 duk_int_t pcall_rc;
28575
28576 /* NOTE: we try to minimize code size by avoiding unnecessary pops,
28577 * so the stack looks a bit cluttered in this function. DUK_ASSERT_TOP()
28578 * assertions are used to ensure stack configuration is correct at each
28579 * step.
28580 */
28581
28582 /*
28583 * Resolve module identifier into canonical absolute form.
28584 */
28585
28586 str_req_id = duk_require_string(ctx, DUK__IDX_REQUESTED_ID);
28589 str_mod_id = duk_get_string(ctx, DUK__IDX_REQUIRE_ID); /* ignore non-strings */
28590 DUK_DDD(DUK_DDDPRINT("resolve module id: requested=%!T, currentmodule=%!T",
28593 duk__bi_global_resolve_module_id(ctx, str_req_id, str_mod_id);
28594 str_req_id = NULL;
28595 str_mod_id = NULL;
28596 DUK_DDD(DUK_DDDPRINT("resolved module id: requested=%!T, currentmodule=%!T, result=%!T, lastcomp=%!T",
28601
28602 /* [ requested_id require require.id resolved_id last_comp ] */
28604
28605 /*
28606 * Cached module check.
28607 *
28608 * If module has been loaded or its loading has already begun without
28609 * finishing, return the same cached value ('exports'). The value is
28610 * registered when module load starts so that circular references can
28611 * be supported to some extent.
28612 */
28613
28615 duk_get_prop_stridx(ctx, DUK__IDX_DUKTAPE, DUK_STRIDX_MOD_LOADED); /* Duktape.modLoaded */
28618
28620 if (duk_get_prop(ctx, DUK__IDX_MODLOADED)) {
28621 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */
28622 DUK_DD(DUK_DDPRINT("module already loaded: %!T",
28624 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_EXPORTS); /* return module.exports */
28625 return 1;
28626 }
28628
28629 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined ] */
28630
28631 /*
28632 * Module not loaded (and loading not started previously).
28633 *
28634 * Create a new require() function with 'id' set to resolved ID
28635 * of module being loaded. Also create 'exports' and 'module'
28636 * tables but don't register exports to the loaded table yet.
28637 * We don't want to do that unless the user module search callbacks
28638 * succeeds in finding the module.
28639 */
28640
28641 DUK_D(DUK_DPRINT("loading module %!T, resolution base %!T, requested ID %!T -> resolved ID %!T, last component %!T",
28647
28648 /* Fresh require: require.id is left configurable (but not writable)
28649 * so that is not easy to accidentally tweak it, but it can still be
28650 * done with Object.defineProperty().
28651 *
28652 * XXX: require.id could also be just made non-configurable, as there
28653 * is no practical reason to touch it.
28654 */
28659 duk_xdef_prop_stridx(ctx, DUK__IDX_FRESH_REQUIRE, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_C); /* a fresh require() with require.id = resolved target module id */
28660
28661 /* Module table:
28662 * - module.exports: initial exports table (may be replaced by user)
28663 * - module.id is non-writable and non-configurable, as the CommonJS
28664 * spec suggests this if possible
28665 * - module.filename: not set, defaults to resolved ID if not explicitly
28666 * set by modSearch() (note capitalization, not .fileName, matches Node.js)
28667 * - module.name: not set, defaults to last component of resolved ID if
28668 * not explicitly set by modSearch()
28669 */
28670 duk_push_object(ctx); /* exports */
28671 duk_push_object(ctx); /* module */
28674 duk_dup(ctx, DUK__IDX_RESOLVED_ID); /* resolved id: require(id) must return this same module */
28675 duk_xdef_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE); /* module.id = resolved_id */
28676 duk_compact(ctx, DUK__IDX_MODULE); /* module table remains registered to modLoaded, minimize its size */
28678
28679 DUK_DD(DUK_DDPRINT("module table created: %!T", duk_get_tval(ctx, DUK__IDX_MODULE)));
28680
28681 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module ] */
28682
28683 /* Register the module table early to modLoaded[] so that we can
28684 * support circular references even in modSearch(). If an error
28685 * is thrown, we'll delete the reference.
28686 */
28689 duk_put_prop(ctx, DUK__IDX_MODLOADED); /* Duktape.modLoaded[resolved_id] = module */
28690
28691 /*
28692 * Call user provided module search function and build the wrapped
28693 * module source code (if necessary). The module search function
28694 * can be used to implement pure Ecmacsript, pure C, and mixed
28695 * Ecmascript/C modules.
28696 *
28697 * The module search function can operate on the exports table directly
28698 * (e.g. DLL code can register values to it). It can also return a
28699 * string which is interpreted as module source code (if a non-string
28700 * is returned the module is assumed to be a pure C one). If a module
28701 * cannot be found, an error must be thrown by the user callback.
28702 *
28703 * Because Duktape.modLoaded[] already contains the module being
28704 * loaded, circular references for C modules should also work
28705 * (although expected to be quite rare).
28706 */
28707
28708 duk_push_string(ctx, "(function(require,exports,module){");
28709
28710 /* Duktape.modSearch(resolved_id, fresh_require, exports, module). */
28711 duk_get_prop_stridx(ctx, DUK__IDX_DUKTAPE, DUK_STRIDX_MOD_SEARCH); /* Duktape.modSearch */
28715 duk_dup(ctx, DUK__IDX_MODULE); /* [ ... Duktape.modSearch resolved_id last_comp fresh_require exports module ] */
28716 pcall_rc = duk_pcall(ctx, 4 /*nargs*/); /* -> [ ... source ] */
28718
28719 if (pcall_rc != DUK_EXEC_SUCCESS) {
28720 /* Delete entry in Duktape.modLoaded[] and rethrow. */
28721 goto delete_rethrow;
28722 }
28723
28724 /* If user callback did not return source code, module loading
28725 * is finished (user callback initialized exports table directly).
28726 */
28727 if (!duk_is_string(ctx, -1)) {
28728 /* User callback did not return source code, so module loading
28729 * is finished: just update modLoaded with final module.exports
28730 * and we're done.
28731 */
28732 goto return_exports;
28733 }
28734
28735 /* Finish the wrapped module source. Force module.filename as the
28736 * function .fileName so it gets set for functions defined within a
28737 * module. This also ensures loggers created within the module get
28738 * the module ID (or overridden filename) as their default logger name.
28739 * (Note capitalization: .filename matches Node.js while .fileName is
28740 * used elsewhere in Duktape.)
28741 */
28742 duk_push_string(ctx, "})");
28743 duk_concat(ctx, 3);
28745 /* module.filename for .fileName, default to resolved ID if
28746 * not present.
28747 */
28748 duk_pop(ctx);
28750 }
28752
28753 /* Module has now evaluated to a wrapped module function. Force its
28754 * .name to match module.name (defaults to last component of resolved
28755 * ID) so that it is shown in stack traces too. Note that we must not
28756 * introduce an actual name binding into the function scope (which is
28757 * usually the case with a named function) because it would affect the
28758 * scope seen by the module and shadow accesses to globals of the same name.
28759 * This is now done by compiling the function as anonymous and then forcing
28760 * its .name without setting a "has name binding" flag.
28761 */
28762
28765 /* module.name for .name, default to last component if
28766 * not present.
28767 */
28768 duk_pop(ctx);
28770 }
28772
28773 /*
28774 * Call the wrapped module function.
28775 *
28776 * Use a protected call so that we can update Duktape.modLoaded[resolved_id]
28777 * even if the module throws an error.
28778 */
28779
28780 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */
28782
28783 duk_dup(ctx, DUK__IDX_EXPORTS); /* exports (this binding) */
28784 duk_dup(ctx, DUK__IDX_FRESH_REQUIRE); /* fresh require (argument) */
28785 duk_get_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_EXPORTS); /* relookup exports from module.exports in case it was changed by modSearch */
28786 duk_dup(ctx, DUK__IDX_MODULE); /* module (argument) */
28788
28789 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */
28790
28791 pcall_rc = duk_pcall_method(ctx, 3 /*nargs*/);
28792 if (pcall_rc != DUK_EXEC_SUCCESS) {
28793 /* Module loading failed. Node.js will forget the module
28794 * registration so that another require() will try to load
28795 * the module again. Mimic that behavior.
28796 */
28797 goto delete_rethrow;
28798 }
28799
28800 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */
28802
28803 /* fall through */
28804
28805 return_exports:
28807 duk_compact(ctx, -1); /* compact the exports table */
28808 return 1; /* return module.exports */
28809
28810 delete_rethrow:
28812 duk_del_prop(ctx, DUK__IDX_MODLOADED); /* delete Duktape.modLoaded[resolved_id] */
28813 duk_throw(ctx); /* rethrow original error */
28814 return 0; /* not reachable */
28815}
28816
28817#undef DUK__IDX_REQUESTED_ID
28818#undef DUK__IDX_REQUIRE
28819#undef DUK__IDX_REQUIRE_ID
28820#undef DUK__IDX_RESOLVED_ID
28821#undef DUK__IDX_LASTCOMP
28822#undef DUK__IDX_DUKTAPE
28823#undef DUK__IDX_MODLOADED
28824#undef DUK__IDX_UNDEFINED
28825#undef DUK__IDX_FRESH_REQUIRE
28826#undef DUK__IDX_EXPORTS
28827#undef DUK__IDX_MODULE
28828#else
28830 DUK_UNREF(ctx);
28832}
28833#endif /* DUK_USE_COMMONJS_MODULES */
28834/*
28835 * JSON built-ins.
28836 *
28837 * See doc/json.rst.
28838 *
28839 * Codepoints are handled as duk_uint_fast32_t to ensure that the full
28840 * unsigned 32-bit range is supported. This matters to e.g. JX.
28842 * Input parsing doesn't do an explicit end-of-input check at all. This is
28843 * safe: input string data is always NUL-terminated (0x00) and valid JSON
28844 * inputs never contain plain NUL characters, so that as long as syntax checks
28845 * are correct, we'll never read past the NUL. This approach reduces code size
28846 * and improves parsing performance, but it's critical that syntax checks are
28847 * indeed correct!
28848 */
28849
28850/* include removed: duk_internal.h */
28851
28852/*
28853 * Local defines and forward declarations.
28854 */
28855
28856#define DUK__JSON_DECSTR_BUFSIZE 128
28857#define DUK__JSON_DECSTR_CHUNKSIZE 64
28858#define DUK__JSON_ENCSTR_CHUNKSIZE 64
28859#define DUK__JSON_STRINGIFY_BUFSIZE 128
28860#define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */
28861
28864DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
28865DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
28870#ifdef DUK_USE_JX
28874#endif
28882
28887#if defined(DUK_USE_FASTINT)
28888DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
28889#endif
28891DUK_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);
28901#if defined(DUK_USE_FASTINT)
28902DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
28903#endif
28904#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
28906DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
28908#endif
28910
28911/*
28912 * Helper tables
28913 */
28914
28915#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
28916DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
28917 /* 0x00 ... 0x7f: as is
28918 * 0x80: escape generically
28919 * 0x81: slow path
28920 * 0xa0 ... 0xff: backslash + one char
28921 */
28922
28923 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
28924 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
28925 0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
28926 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
28927 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
28928 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
28929 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
28930 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
28931 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
28932 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
28933 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
28934 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
28935 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
28936 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
28937 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
28938 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
28939};
28940#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
28941DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
28946};
28947#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
28948
28949#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
28950DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
28951 /* 0x00: slow path
28952 * other: as is
28953 */
28954 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28955 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28956 0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
28957 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
28958 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
28959 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
28960 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
28961 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
28962 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
28963 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
28964 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
28965 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
28966 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
28967 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
28968 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
28969 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
28970};
28971#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
28972
28973#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
28974DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
28975 /* 0x00: finish (non-white)
28976 * 0x01: continue
28977 */
28978 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
28979 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28980 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28981 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28991 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28992 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28993 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
28994};
28995#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
28996
28997#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
28998DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
28999 /* 0x00: finish (not part of number)
29000 * 0x01: continue
29001 */
29002 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29003 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29004 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
29005 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29006 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29008 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29009 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29010 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29011 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29012 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29014 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29015 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29016 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29017 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
29018};
29019#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29020
29021/*
29022 * Parsing implementation.
29023 *
29024 * JSON lexer is now separate from duk_lexer.c because there are numerous
29025 * small differences making it difficult to share the lexer.
29027 * The parser here works with raw bytes directly; this works because all
29028 * JSON delimiters are ASCII characters. Invalid xUTF-8 encoded values
29029 * inside strings will be passed on without normalization; this is not a
29030 * compliance concern because compliant inputs will always be valid
29031 * CESU-8 encodings.
29032 */
29033
29035 /* Shared handler to minimize parser size. Cause will be
29036 * hidden, unfortunately, but we'll have an offset which
29037 * is often quite enough.
29038 */
29040 (long) (js_ctx->p - js_ctx->p_start));
29041}
29042
29044 const duk_uint8_t *p;
29045 duk_uint8_t t;
29046
29047 p = js_ctx->p;
29048 for (;;) {
29049 DUK_ASSERT(p <= js_ctx->p_end);
29050 t = *p;
29051
29052#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
29053 /* This fast path is pretty marginal in practice.
29054 * XXX: candidate for removal.
29055 */
29056 DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */
29057 if (duk__json_eatwhite_lookup[t] == 0) {
29058 break;
29059 }
29060#else /* DUK_USE_JSON_EATWHITE_FASTPATH */
29061 if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
29062 /* NUL also comes here. Comparison order matters, 0x20
29063 * is most common whitespace.
29064 */
29065 break;
29067#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
29068 p++;
29069 }
29070 js_ctx->p = p;
29071}
29073DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
29074 DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
29075 return *js_ctx->p;
29076}
29077
29078DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
29079 DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
29080 return *js_ctx->p++;
29081}
29082
29084 duk__dec_eat_white(js_ctx);
29085 return duk__dec_get(js_ctx);
29086}
29087
29088/* For JX, expressing the whole unsigned 32-bit range matters. */
29091 duk_uint_fast32_t res = 0;
29092 duk_uint8_t x;
29094
29095 for (i = 0; i < n; i++) {
29096 /* XXX: share helper from lexer; duk_lexer.c / hexval(). */
29097
29098 x = duk__dec_get(js_ctx);
29099 DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
29100 (long) i, (long) n, (long) res, (long) x));
29101
29102 /* x == 0x00 (EOF) causes syntax_error */
29103 DUK_ASSERT(duk_hex_dectab[0] == -1);
29104 t = duk_hex_dectab[x & 0xff];
29105 if (DUK_LIKELY(t >= 0)) {
29106 res = (res * 16) + t;
29107 } else {
29108 /* catches EOF and invalid digits */
29109 goto syntax_error;
29110 }
29111 }
29112
29113 DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
29114 return res;
29115
29116 syntax_error:
29117 duk__dec_syntax_error(js_ctx);
29119 return 0;
29120}
29121
29123 duk_hstring *h;
29124 const duk_uint8_t *p;
29125 duk_uint8_t x, y;
29126
29127 /* First character has already been eaten and checked by the caller.
29128 * We can scan until a NUL in stridx string because no built-in strings
29129 * have internal NULs.
29130 */
29131
29132 DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */
29134 h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
29135 DUK_ASSERT(h != NULL);
29136
29137 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
29138 DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */
29139
29140 for (;;) {
29141 x = *p;
29142 if (x == 0) {
29143 break;
29144 }
29145 y = duk__dec_get(js_ctx);
29146 if (x != y) {
29147 /* Catches EOF of JSON input. */
29148 goto syntax_error;
29149 }
29150 p++;
29151 }
29152
29153 return;
29154
29155 syntax_error:
29156 duk__dec_syntax_error(js_ctx);
29158}
29159
29162
29163 /* EOF (-1) will be cast to an unsigned value first
29164 * and then re-cast for the switch. In any case, it
29165 * will match the default case (syntax error).
29166 */
29167 cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
29168 switch ((int) cp) {
29169 case DUK_ASC_BACKSLASH: break;
29170 case DUK_ASC_DOUBLEQUOTE: break;
29171 case DUK_ASC_SLASH: break;
29172 case DUK_ASC_LC_T: cp = 0x09; break;
29173 case DUK_ASC_LC_N: cp = 0x0a; break;
29174 case DUK_ASC_LC_R: cp = 0x0d; break;
29175 case DUK_ASC_LC_F: cp = 0x0c; break;
29176 case DUK_ASC_LC_B: cp = 0x08; break;
29177 case DUK_ASC_LC_U: {
29178 cp = duk__dec_decode_hex_escape(js_ctx, 4);
29179 break;
29180 }
29181#ifdef DUK_USE_JX
29182 case DUK_ASC_UC_U: {
29183 if (js_ctx->flag_ext_custom) {
29184 cp = duk__dec_decode_hex_escape(js_ctx, 8);
29185 } else {
29186 return 1; /* syntax error */
29187 }
29188 break;
29189 }
29190 case DUK_ASC_LC_X: {
29191 if (js_ctx->flag_ext_custom) {
29193 } else {
29194 return 1; /* syntax error */
29195 }
29196 break;
29197 }
29198#endif /* DUK_USE_JX */
29199 default:
29200 /* catches EOF (0x00) */
29201 return 1; /* syntax error */
29202 }
29203
29204 DUK_RAW_WRITE_XUTF8(*ext_p, cp);
29205
29206 return 0;
29207}
29208
29210 duk_hthread *thr = js_ctx->thr;
29211 duk_context *ctx = (duk_context *) thr;
29212 duk_bufwriter_ctx bw_alloc;
29214 duk_uint8_t *q;
29215
29216 /* '"' was eaten by caller */
29217
29218 /* Note that we currently parse -bytes-, not codepoints.
29219 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
29220 * so they'll simply pass through (valid UTF-8 or not).
29221 */
29222
29223 bw = &bw_alloc;
29225 q = DUK_BW_GET_PTR(js_ctx->thr, bw);
29226
29227#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
29228 for (;;) {
29229 duk_small_uint_t safe;
29230 duk_uint8_t b, x;
29231 const duk_uint8_t *p;
29232
29233 /* Select a safe loop count where no output checks are
29234 * needed assuming we won't encounter escapes. Input
29235 * bound checks are not necessary as a NUL (guaranteed)
29236 * will cause a SyntaxError before we read out of bounds.
29237 */
29238
29240
29241 /* Ensure space for 1:1 output plus one escape. */
29242 q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
29243
29244 p = js_ctx->p; /* temp copy, write back for next loop */
29245 for (;;) {
29246 if (safe == 0) {
29247 js_ctx->p = p;
29248 break;
29249 }
29250 safe--;
29251
29252 /* End of input (NUL) goes through slow path and causes SyntaxError. */
29254
29255 b = *p++;
29257 if (DUK_LIKELY(x != 0)) {
29258 /* Fast path, decode as is. */
29259 *q++ = b;
29260 } else if (b == DUK_ASC_DOUBLEQUOTE) {
29261 js_ctx->p = p;
29262 goto found_quote;
29263 } else if (b == DUK_ASC_BACKSLASH) {
29264 /* We've ensured space for one escaped input; then
29265 * bail out and recheck (this makes escape handling
29266 * quite slow but it's uncommon).
29267 */
29268 js_ctx->p = p;
29269 if (duk__dec_string_escape(js_ctx, &q) != 0) {
29270 goto syntax_error;
29271 }
29272 break;
29273 } else {
29274 js_ctx->p = p;
29275 goto syntax_error;
29276 }
29277 }
29278 }
29279 found_quote:
29280#else /* DUK_USE_JSON_DECSTRING_FASTPATH */
29281 for (;;) {
29282 duk_uint8_t x;
29283
29285
29286 x = duk__dec_get(js_ctx);
29287
29288 if (x == DUK_ASC_DOUBLEQUOTE) {
29289 break;
29290 } else if (x == DUK_ASC_BACKSLASH) {
29291 if (duk__dec_string_escape(js_ctx, &q) != 0) {
29292 goto syntax_error;
29293 }
29294 } else if (x < 0x20) {
29295 /* catches EOF (NUL) */
29296 goto syntax_error;
29297 } else {
29298 *q++ = (duk_uint8_t) x;
29299 }
29300 }
29301#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
29303 DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
29304 duk_to_string(ctx, -1);
29305
29306 /* [ ... str ] */
29307
29308 return;
29309
29310 syntax_error:
29311 duk__dec_syntax_error(js_ctx);
29313}
29314
29315#ifdef DUK_USE_JX
29316/* Decode a plain string consisting entirely of identifier characters.
29317 * Used to parse plain keys (e.g. "foo: 123").
29318 */
29320 duk_hthread *thr = js_ctx->thr;
29321 duk_context *ctx = (duk_context *) thr;
29322 const duk_uint8_t *p;
29324
29325 /* Caller has already eaten the first char so backtrack one byte. */
29326
29327 js_ctx->p--; /* safe */
29328 p = js_ctx->p;
29329
29330 /* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
29331 * parsing (which is correct except if there are non-shortest encodings).
29332 * There is also no need to check explicitly for end of input buffer as
29333 * the input is NUL padded and NUL will exit the parsing loop.
29334 *
29335 * Because no unescaping takes place, we can just scan to the end of the
29336 * plain string and intern from the input buffer.
29337 */
29338
29339 for (;;) {
29340 x = *p;
29341
29342 /* There is no need to check the first character specially here
29343 * (i.e. reject digits): the caller only accepts valid initial
29344 * characters and won't call us if the first character is a digit.
29345 * This also ensures that the plain string won't be empty.
29346 */
29347
29349 break;
29350 }
29351 p++;
29352 }
29353
29354 duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
29355 js_ctx->p = p;
29356
29357 /* [ ... str ] */
29358}
29359#endif /* DUK_USE_JX */
29360
29361#ifdef DUK_USE_JX
29363 duk_hthread *thr = js_ctx->thr;
29364 duk_context *ctx = (duk_context *) thr;
29365 const duk_uint8_t *p;
29367 void *voidptr;
29368
29369 /* Caller has already eaten the first character ('(') which we don't need. */
29370
29371 p = js_ctx->p;
29372
29373 for (;;) {
29374 x = *p;
29375
29376 /* Assume that the native representation never contains a closing
29377 * parenthesis.
29378 */
29379
29380 if (x == DUK_ASC_RPAREN) {
29381 break;
29382 } else if (x <= 0) {
29383 /* NUL term or -1 (EOF), NUL check would suffice */
29384 goto syntax_error;
29385 }
29386 p++;
29387 }
29388
29389 /* There is no need to NUL delimit the sscanf() call: trailing garbage is
29390 * ignored and there is always a NUL terminator which will force an error
29391 * if no error is encountered before it. It's possible that the scan
29392 * would scan further than between [js_ctx->p,p[ though and we'd advance
29393 * by less than the scanned value.
29394 *
29395 * Because pointers are platform specific, a failure to scan a pointer
29396 * results in a null pointer which is a better placeholder than a missing
29397 * value or an error.
29398 */
29400 voidptr = NULL;
29401 (void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
29402 duk_push_pointer(ctx, voidptr);
29403 js_ctx->p = p + 1; /* skip ')' */
29404
29405 /* [ ... ptr ] */
29406
29407 return;
29408
29409 syntax_error:
29410 duk__dec_syntax_error(js_ctx);
29412}
29413#endif /* DUK_USE_JX */
29414
29415#ifdef DUK_USE_JX
29417 duk_hthread *thr = js_ctx->thr;
29418 duk_context *ctx = (duk_context *) thr;
29419 const duk_uint8_t *p;
29420 duk_uint8_t *buf;
29421 duk_size_t src_len;
29423
29424 /* Caller has already eaten the first character ('|') which we don't need. */
29425
29426 p = js_ctx->p;
29427
29428 /* XXX: Would be nice to share the fast path loop from duk_hex_decode()
29429 * and avoid creating a temporary buffer. However, there are some
29430 * differences which prevent trivial sharing:
29431 *
29432 * - Pipe char detection
29433 * - EOF detection
29434 * - Unknown length of input and output
29435 *
29436 * The best approach here would be a bufwriter and a reasonaly sized
29437 * safe inner loop (e.g. 64 output bytes at a time).
29438 */
29439
29440 for (;;) {
29441 x = *p;
29442
29443 /* This loop intentionally does not ensure characters are valid
29444 * ([0-9a-fA-F]) because the hex decode call below will do that.
29445 */
29446 if (x == DUK_ASC_PIPE) {
29447 break;
29448 } else if (x <= 0) {
29449 /* NUL term or -1 (EOF), NUL check would suffice */
29450 goto syntax_error;
29451 }
29452 p++;
29453 }
29454
29455 src_len = (duk_size_t) (p - js_ctx->p);
29456 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_len);
29458 DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);
29459 duk_hex_decode(ctx, -1);
29460
29461 js_ctx->p = p + 1; /* skip '|' */
29462
29463 /* [ ... buf ] */
29464
29465 return;
29466
29467 syntax_error:
29468 duk__dec_syntax_error(js_ctx);
29470}
29471#endif /* DUK_USE_JX */
29472
29473/* Parse a number, other than NaN or +/- Infinity */
29475 duk_context *ctx = (duk_context *) js_ctx->thr;
29476 const duk_uint8_t *p_start;
29477 const duk_uint8_t *p;
29478 duk_uint8_t x;
29479 duk_small_uint_t s2n_flags;
29480
29481 DUK_DDD(DUK_DDDPRINT("parse_number"));
29482
29483 p_start = js_ctx->p;
29484
29485 /* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
29486 * string for strict number parsing.
29487 */
29488
29489 p = js_ctx->p;
29490 for (;;) {
29491 x = *p;
29492
29493 DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
29494 (const void *) p_start, (const void *) p,
29495 (const void *) js_ctx->p_end, (long) x));
29496
29497#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
29498 /* This fast path is pretty marginal in practice.
29499 * XXX: candidate for removal.
29500 */
29501 DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */
29502 if (duk__json_decnumber_lookup[x] == 0) {
29503 break;
29504 }
29505#else /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29506 if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
29507 (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
29508 x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
29509 /* Plus sign must be accepted for positive exponents
29510 * (e.g. '1.5e+2'). This clause catches NULs.
29511 */
29512 break;
29513 }
29514#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29515 p++; /* safe, because matched (NUL causes a break) */
29516 }
29517 js_ctx->p = p;
29518
29519 DUK_ASSERT(js_ctx->p > p_start);
29520 duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (p - p_start));
29521
29523 DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */
29525
29526 DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
29527 (duk_tval *) duk_get_tval(ctx, -1)));
29528 duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
29529 if (duk_is_nan(ctx, -1)) {
29530 duk__dec_syntax_error(js_ctx);
29531 }
29532 DUK_ASSERT(duk_is_number(ctx, -1));
29533 DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
29534 (duk_tval *) duk_get_tval(ctx, -1)));
29535
29536 /* [ ... num ] */
29537}
29538
29540 duk_context *ctx = (duk_context *) js_ctx->thr;
29542
29543 /* c recursion check */
29545 DUK_ASSERT(js_ctx->recursion_depth >= 0);
29546 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
29547 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
29549 }
29550 js_ctx->recursion_depth++;
29551}
29552
29554 /* c recursion check */
29555
29556 DUK_ASSERT(js_ctx->recursion_depth > 0);
29557 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
29558 js_ctx->recursion_depth--;
29559}
29560
29562 duk_context *ctx = (duk_context *) js_ctx->thr;
29563 duk_int_t key_count; /* XXX: a "first" flag would suffice */
29564 duk_uint8_t x;
29565
29566 DUK_DDD(DUK_DDDPRINT("parse_object"));
29567
29568 duk__dec_objarr_entry(js_ctx);
29569
29570 duk_push_object(ctx);
29571
29572 /* Initial '{' has been checked and eaten by caller. */
29573
29574 key_count = 0;
29575 for (;;) {
29576 x = duk__dec_get_nonwhite(js_ctx);
29577
29578 DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
29579 (duk_tval *) duk_get_tval(ctx, -1),
29580 (long) x, (long) key_count));
29581
29582 /* handle comma and closing brace */
29583
29584 if (x == DUK_ASC_COMMA && key_count > 0) {
29585 /* accept comma, expect new value */
29586 x = duk__dec_get_nonwhite(js_ctx);
29587 } else if (x == DUK_ASC_RCURLY) {
29588 /* eat closing brace */
29589 break;
29590 } else if (key_count == 0) {
29591 /* accept anything, expect first value (EOF will be
29592 * caught by key parsing below.
29593 */
29594 ;
29595 } else {
29596 /* catches EOF (NUL) and initial comma */
29597 goto syntax_error;
29598 }
29599
29600 /* parse key and value */
29601
29602 if (x == DUK_ASC_DOUBLEQUOTE) {
29603 duk__dec_string(js_ctx);
29604#ifdef DUK_USE_JX
29605 } else if (js_ctx->flag_ext_custom &&
29607 duk__dec_plain_string(js_ctx);
29608#endif
29609 } else {
29610 goto syntax_error;
29611 }
29612
29613 /* [ ... obj key ] */
29614
29615 x = duk__dec_get_nonwhite(js_ctx);
29616 if (x != DUK_ASC_COLON) {
29617 goto syntax_error;
29618 }
29619
29620 duk__dec_value(js_ctx);
29621
29622 /* [ ... obj key val ] */
29623
29624 duk_xdef_prop_wec(ctx, -3);
29625
29626 /* [ ... obj ] */
29628 key_count++;
29629 }
29630
29631 /* [ ... obj ] */
29632
29633 DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
29634 (duk_tval *) duk_get_tval(ctx, -1)));
29635
29636 duk__dec_objarr_exit(js_ctx);
29637 return;
29638
29639 syntax_error:
29640 duk__dec_syntax_error(js_ctx);
29642}
29643
29645 duk_context *ctx = (duk_context *) js_ctx->thr;
29646 duk_uarridx_t arr_idx;
29647 duk_uint8_t x;
29648
29649 DUK_DDD(DUK_DDDPRINT("parse_array"));
29650
29651 duk__dec_objarr_entry(js_ctx);
29652
29653 duk_push_array(ctx);
29654
29655 /* Initial '[' has been checked and eaten by caller. */
29656
29657 arr_idx = 0;
29658 for (;;) {
29659 x = duk__dec_get_nonwhite(js_ctx);
29660
29661 DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
29662 (duk_tval *) duk_get_tval(ctx, -1),
29663 (long) x, (long) arr_idx));
29664
29665 /* handle comma and closing bracket */
29666
29667 if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
29668 /* accept comma, expect new value */
29669 ;
29670 } else if (x == DUK_ASC_RBRACKET) {
29671 /* eat closing bracket */
29672 break;
29673 } else if (arr_idx == 0) {
29674 /* accept anything, expect first value (EOF will be
29675 * caught by duk__dec_value() below.
29676 */
29677 js_ctx->p--; /* backtrack (safe) */
29678 } else {
29679 /* catches EOF (NUL) and initial comma */
29680 goto syntax_error;
29681 }
29682
29683 /* parse value */
29684
29685 duk__dec_value(js_ctx);
29686
29687 /* [ ... arr val ] */
29688
29689 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
29690 arr_idx++;
29691 }
29692
29693 /* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
29694 * set the values.
29696
29697 duk_set_length(ctx, -1, arr_idx);
29698
29699 /* [ ... arr ] */
29700
29701 DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
29702 (duk_tval *) duk_get_tval(ctx, -1)));
29703
29704 duk__dec_objarr_exit(js_ctx);
29705 return;
29706
29707 syntax_error:
29708 duk__dec_syntax_error(js_ctx);
29710}
29711
29713 duk_context *ctx = (duk_context *) js_ctx->thr;
29714 duk_uint8_t x;
29715
29716 x = duk__dec_get_nonwhite(js_ctx);
29717
29718 DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
29719
29720 /* Note: duk__dec_req_stridx() backtracks one char */
29721
29722 if (x == DUK_ASC_DOUBLEQUOTE) {
29723 duk__dec_string(js_ctx);
29724 } else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
29725#ifdef DUK_USE_JX
29726 if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
29727 duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */
29729 } else {
29730#else
29731 { /* unconditional block */
29732#endif
29733 /* We already ate 'x', so backup one byte. */
29734 js_ctx->p--; /* safe */
29735 duk__dec_number(js_ctx);
29736 }
29737 } else if (x == DUK_ASC_LC_T) {
29739 duk_push_true(ctx);
29740 } else if (x == DUK_ASC_LC_F) {
29742 duk_push_false(ctx);
29743 } else if (x == DUK_ASC_LC_N) {
29745 duk_push_null(ctx);
29746#ifdef DUK_USE_JX
29747 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
29749 duk_push_undefined(ctx);
29750 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
29752 duk_push_nan(ctx);
29753 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
29756 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
29757 duk__dec_pointer(js_ctx);
29758 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
29759 duk__dec_buffer(js_ctx);
29760#endif
29761 } else if (x == DUK_ASC_LCURLY) {
29762 duk__dec_object(js_ctx);
29763 } else if (x == DUK_ASC_LBRACKET) {
29764 duk__dec_array(js_ctx);
29765 } else {
29766 /* catches EOF (NUL) */
29767 goto syntax_error;
29768 }
29769
29770 duk__dec_eat_white(js_ctx);
29771
29772 /* [ ... val ] */
29773 return;
29774
29775 syntax_error:
29776 duk__dec_syntax_error(js_ctx);
29778}
29779
29780/* Recursive value reviver, implements the Walk() algorithm. No C recursion
29781 * check is done here because the initial parsing step will already ensure
29782 * there is a reasonable limit on C recursion depth and hence object depth.
29783 */
29785 duk_context *ctx = (duk_context *) js_ctx->thr;
29786 duk_hobject *h;
29787 duk_uarridx_t i, arr_len;
29788
29789 DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
29790 (long) duk_get_top(ctx),
29791 (duk_tval *) duk_get_tval(ctx, -2),
29792 (duk_tval *) duk_get_tval(ctx, -1)));
29793
29794 duk_dup_top(ctx);
29795 duk_get_prop(ctx, -3); /* -> [ ... holder name val ] */
29796
29797 h = duk_get_hobject(ctx, -1);
29798 if (h != NULL) {
29800 arr_len = (duk_uarridx_t) duk_get_length(ctx, -1);
29801 for (i = 0; i < arr_len; i++) {
29802 /* [ ... holder name val ] */
29803
29804 DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
29805 (long) duk_get_top(ctx), (long) i, (long) arr_len,
29806 (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
29807 (duk_tval *) duk_get_tval(ctx, -1)));
29808
29809 /* XXX: push_uint_string / push_u32_string */
29810 duk_dup_top(ctx);
29811 duk_push_uint(ctx, (duk_uint_t) i);
29812 duk_to_string(ctx, -1); /* -> [ ... holder name val val ToString(i) ] */
29813 duk__dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */
29814
29815 if (duk_is_undefined(ctx, -1)) {
29816 duk_pop(ctx);
29817 duk_del_prop_index(ctx, -1, i);
29818 } else {
29819 /* XXX: duk_xdef_prop_index_wec() would be more appropriate
29820 * here but it currently makes some assumptions that might
29821 * not hold (e.g. that previous property is not an accessor).
29822 */
29823 duk_put_prop_index(ctx, -2, i);
29824 }
29825 }
29826 } else {
29827 /* [ ... holder name val ] */
29828 duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
29829 while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
29830 DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
29831 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -5),
29832 (duk_tval *) duk_get_tval(ctx, -4), (duk_tval *) duk_get_tval(ctx, -3),
29833 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
29834
29835 /* [ ... holder name val enum obj_key ] */
29836 duk_dup(ctx, -3);
29837 duk_dup(ctx, -2);
29838
29839 /* [ ... holder name val enum obj_key val obj_key ] */
29840 duk__dec_reviver_walk(js_ctx);
29841
29842 /* [ ... holder name val enum obj_key new_elem ] */
29843 if (duk_is_undefined(ctx, -1)) {
29844 duk_pop(ctx);
29845 duk_del_prop(ctx, -3);
29846 } else {
29847 /* XXX: duk_xdef_prop_index_wec() would be more appropriate
29848 * here but it currently makes some assumptions that might
29849 * not hold (e.g. that previous property is not an accessor).
29850 *
29851 * Using duk_put_prop() works incorrectly with '__proto__'
29852 * if the own property with that name has been deleted. This
29853 * does not happen normally, but a clever reviver can trigger
29854 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
29855 */
29856 duk_put_prop(ctx, -4);
29857 }
29858 }
29859 duk_pop(ctx); /* pop enum */
29863 /* [ ... holder name val ] */
29865 duk_dup(ctx, js_ctx->idx_reviver);
29866 duk_insert(ctx, -4); /* -> [ ... reviver holder name val ] */
29867 duk_call_method(ctx, 2); /* -> [ ... res ] */
29868
29869 DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
29870 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -1)));
29871}
29872
29874 * Stringify implementation.
29875 */
29876
29877#define DUK__EMIT_1(js_ctx,ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
29878#define DUK__EMIT_2(js_ctx,ch1,ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
29879#define DUK__EMIT_HSTR(js_ctx,h) duk__emit_hstring((js_ctx), (h))
29880#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
29881#define DUK__EMIT_CSTR(js_ctx,p) duk__emit_cstring((js_ctx), (p))
29882#endif
29883#define DUK__EMIT_STRIDX(js_ctx,i) duk__emit_stridx((js_ctx), (i))
29884#define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx))
29885
29887 DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
29888}
29889
29891 DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
29892}
29893
29895 DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
29896}
29897
29898#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
29899DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
29900 DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
29901}
29902#endif
29905 duk_hstring *h;
29906
29907 DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */
29909 h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
29910 DUK_ASSERT(h != NULL);
29911
29912 DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
29913}
29914
29916 DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
29917 DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
29918}
29919
29920#define DUK__MKESC(nybbles,esc1,esc2) \
29921 (((duk_uint_fast32_t) (nybbles)) << 16) | \
29922 (((duk_uint_fast32_t) (esc1)) << 8) | \
29923 ((duk_uint_fast32_t) (esc2))
29924
29925DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {
29927 duk_small_uint_t dig;
29928
29929 DUK_UNREF(js_ctx);
29930
29931 /* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
29932
29933 /* Select appropriate escape format automatically, and set 'tmp' to a
29934 * value encoding both the escape format character and the nybble count:
29935 *
29936 * (nybble_count << 16) | (escape_char1) | (escape_char2)
29937 */
29938
29939#ifdef DUK_USE_JX
29940 if (DUK_LIKELY(cp < 0x100UL)) {
29941 if (DUK_UNLIKELY(js_ctx->flag_ext_custom)) {
29943 } else {
29945 }
29946 } else
29947#endif
29948 if (DUK_LIKELY(cp < 0x10000UL)) {
29950 } else {
29951#ifdef DUK_USE_JX
29952 if (DUK_LIKELY(js_ctx->flag_ext_custom)) {
29954 } else
29955#endif
29956 {
29957 /* In compatible mode and standard JSON mode, output
29958 * something useful for non-BMP characters. This won't
29959 * roundtrip but will still be more or less readable and
29960 * more useful than an error.
29961 */
29963 }
29964 }
29965
29966 *q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
29967 *q++ = (duk_uint8_t) (tmp & 0xff);
29968
29969 tmp = tmp >> 16;
29970 while (tmp > 0) {
29971 tmp--;
29972 dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
29973 *q++ = duk_lc_digits[dig];
29974 }
29975
29976 return q;
29977}
29978
29980 const duk_int8_t *p, *p_start, *p_end; /* Note: intentionally signed. */
29981 duk_size_t k_len;
29982 duk_codepoint_t cp;
29983
29984 DUK_ASSERT(k != NULL);
29985
29986 /* Accept ASCII strings which conform to identifier requirements
29987 * as being emitted without key quotes. Since we only accept ASCII
29988 * there's no need for actual decoding: 'p' is intentionally signed
29989 * so that bytes >= 0x80 extend to negative values and are rejected
29990 * as invalid identifier codepoints.
29991 */
29992
29993 if (js_ctx->flag_avoid_key_quotes) {
29994 k_len = DUK_HSTRING_GET_BYTELEN(k);
29995 p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
29996 p_end = p_start + k_len;
29997 p = p_start;
29998
29999 if (p == p_end) {
30000 /* Zero length string is not accepted without quotes */
30001 goto quote_normally;
30002 }
30003 cp = (duk_codepoint_t) (*p++);
30005 goto quote_normally;
30006 }
30007 while (p < p_end) {
30008 cp = (duk_codepoint_t) (*p++);
30010 goto quote_normally;
30011 }
30012 }
30014 /* This seems faster than emitting bytes one at a time and
30015 * then potentially rewinding.
30016 */
30017 DUK__EMIT_HSTR(js_ctx, k);
30018 return;
30019 }
30020
30021 quote_normally:
30022 duk__enc_quote_string(js_ctx, k);
30023}
30024
30025/* The Quote(value) operation: quote a string.
30026 *
30027 * Stack policy: [ ] -> [ ].
30028 */
30029
30031 duk_hthread *thr = js_ctx->thr;
30032 const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
30033 duk_uint8_t *q;
30034 duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */
30035
30036 DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
30037
30038 DUK_ASSERT(h_str != NULL);
30039 p_start = DUK_HSTRING_GET_DATA(h_str);
30040 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
30041 p = p_start;
30042
30044
30045 /* Encode string in small chunks, estimating the maximum expansion so that
30046 * there's no need to ensure space while processing the chunk.
30047 */
30048
30049 while (p < p_end) {
30050 duk_size_t left, now, space;
30051
30052 left = (duk_size_t) (p_end - p);
30055
30056 /* Maximum expansion per input byte is 6:
30057 * - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
30058 * - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
30059 * - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
30060 */
30061 space = now * 6;
30062 q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
30063
30064 p_now = p + now;
30065
30066 while (p < p_now) {
30067#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
30068 duk_uint8_t b;
30069
30070 b = duk__json_quotestr_lookup[*p++];
30071 if (DUK_LIKELY(b < 0x80)) {
30072 /* Most input bytes go through here. */
30073 *q++ = b;
30074 } else if (b >= 0xa0) {
30075 *q++ = DUK_ASC_BACKSLASH;
30076 *q++ = (duk_uint8_t) (b - 0x80);
30077 } else if (b == 0x80) {
30078 cp = (duk_ucodepoint_t) (*(p - 1));
30079 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30080 } else if (b == 0x7f && js_ctx->flag_ascii_only) {
30081 /* 0x7F is special */
30082 DUK_ASSERT(b == 0x81);
30083 cp = (duk_ucodepoint_t) 0x7f;
30084 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30085 } else {
30086 DUK_ASSERT(b == 0x81);
30087 p--;
30088
30089 /* slow path is shared */
30090#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
30091 cp = *p;
30092
30093 if (DUK_LIKELY(cp <= 0x7f)) {
30094 /* ascii fast path: avoid decoding utf-8 */
30095 p++;
30096 if (cp == 0x22 || cp == 0x5c) {
30097 /* double quote or backslash */
30098 *q++ = DUK_ASC_BACKSLASH;
30099 *q++ = (duk_uint8_t) cp;
30100 } else if (cp < 0x20) {
30101 duk_uint_fast8_t esc_char;
30102
30103 /* This approach is a bit shorter than a straight
30104 * if-else-ladder and also a bit faster.
30105 */
30106 if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
30107 (esc_char = duk__json_quotestr_esc[cp]) != 0) {
30108 *q++ = DUK_ASC_BACKSLASH;
30109 *q++ = (duk_uint8_t) esc_char;
30110 } else {
30111 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30112 }
30113 } else if (cp == 0x7f && js_ctx->flag_ascii_only) {
30114 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30115 } else {
30116 /* any other printable -> as is */
30117 *q++ = (duk_uint8_t) cp;
30118 }
30119 } else {
30120 /* slow path is shared */
30121#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
30122
30123 /* slow path decode */
30124
30125 /* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
30126 * and go forward one byte. This is of course very lossy, but allows some kind
30127 * of output to be produced even for internal strings which don't conform to
30128 * XUTF-8. All standard Ecmascript strings are always CESU-8, so this behavior
30129 * does not violate the Ecmascript specification. The behavior is applied to
30130 * all modes, including Ecmascript standard JSON. Because the current XUTF-8
30131 * decoding is not very strict, this behavior only really affects initial bytes
30132 * and truncated codepoints.
30133 *
30134 * Another alternative would be to scan forwards to start of next codepoint
30135 * (or end of input) and emit just one replacement codepoint.
30136 */
30137
30138 p_tmp = p;
30139 if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
30140 /* Decode failed. */
30141 cp = *p_tmp;
30142 p = p_tmp + 1;
30143 }
30144
30145#ifdef DUK_USE_NONSTD_JSON_ESC_U2028_U2029
30146 if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
30147#else
30148 if (js_ctx->flag_ascii_only) {
30149#endif
30150 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30151 } else {
30152 /* as is */
30153 DUK_RAW_WRITE_XUTF8(q, cp);
30154 }
30155 }
30156 }
30157
30158 DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
30159 }
30160
30162}
30163
30164/* Encode a double (checked by caller) from stack top. Stack top may be
30165 * replaced by serialized string but is not popped (caller does that).
30166 */
30168 duk_hthread *thr;
30169 duk_context *ctx;
30170 duk_tval *tv;
30171 duk_double_t d;
30174 duk_small_uint_t stridx;
30175 duk_small_uint_t n2s_flags;
30176 duk_hstring *h_str;
30177
30178 DUK_ASSERT(js_ctx != NULL);
30179 thr = js_ctx->thr;
30180 DUK_ASSERT(thr != NULL);
30181 ctx = (duk_context *) thr;
30182
30183 /* Caller must ensure 'tv' is indeed a double and not a fastint! */
30184 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30186 d = DUK_TVAL_GET_DOUBLE(tv);
30187
30190 DUK_UNREF(s);
30191
30192 if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
30194
30195#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30196 /* Negative zero needs special handling in JX/JC because
30197 * it would otherwise serialize to '0', not '-0'.
30198 */
30199 if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
30200 (js_ctx->flag_ext_custom_or_compatible))) {
30202 } else
30203#endif /* DUK_USE_JX || DUK_USE_JC */
30204 {
30205 n2s_flags = 0;
30206 /* [ ... number ] -> [ ... string ] */
30207 duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags);
30208 }
30209 h_str = duk_to_hstring(ctx, -1);
30210 DUK_ASSERT(h_str != NULL);
30211 DUK__EMIT_HSTR(js_ctx, h_str);
30212 return;
30213 }
30214
30215#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30216 if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
30218 stridx = DUK_STRIDX_LC_NULL;
30219 } else if (c == DUK_FP_NAN) {
30220 stridx = js_ctx->stridx_custom_nan;
30221 } else if (s == 0) {
30222 stridx = js_ctx->stridx_custom_posinf;
30223 } else {
30224 stridx = js_ctx->stridx_custom_neginf;
30225 }
30226#else
30227 stridx = DUK_STRIDX_LC_NULL;
30228#endif
30229 DUK__EMIT_STRIDX(js_ctx, stridx);
30230}
30231
30232#if defined(DUK_USE_FASTINT)
30233/* Encode a fastint from duk_tval ptr, no value stack effects. */
30234DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
30235 duk_int64_t v;
30236
30237 /* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
30238 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
30239 * (20 chars long). Alloc space for 64-bit range to be safe.
30240 */
30241 duk_uint8_t buf[20 + 1];
30243 /* Caller must ensure 'tv' is indeed a fastint! */
30244 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
30245 v = DUK_TVAL_GET_FASTINT(tv);
30246
30247 /* XXX: There are no format strings in duk_config.h yet, could add
30248 * one for formatting duk_int64_t. For now, assumes "%lld" and that
30249 * "long long" type exists. Could also rely on C99 directly but that
30250 * won't work for older MSVC.
30251 */
30252 DUK_SPRINTF((char *) buf, "%lld", (long long) v);
30253 DUK__EMIT_CSTR(js_ctx, (const char *) buf);
30254}
30255#endif
30256
30257#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30258#if defined(DUK_USE_HEX_FASTPATH)
30259DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
30260 duk_uint8_t *q;
30261 duk_uint16_t *q16;
30263 duk_size_t i, len_safe;
30264#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30265 duk_bool_t shift_dst;
30266#endif
30267
30268 /* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
30269 * For platforms where unaligned accesses are not allowed, shift 'dst'
30270 * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result
30271 * in place. The faster encoding loop makes up the difference.
30272 * There's always space for one extra byte because a terminator always
30273 * follows the hex data and that's been accounted for by the caller.
30274 */
30275
30276#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30277 q16 = (duk_uint16_t *) (void *) dst;
30278#else
30279 shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
30280 if (shift_dst) {
30281 DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
30282 q16 = (duk_uint16_t *) (void *) (dst + 1);
30283 } else {
30284 DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
30285 q16 = (duk_uint16_t *) (void *) dst;
30286 }
30287 DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
30288#endif
30289
30290 len_safe = src_len & ~0x03U;
30291 for (i = 0; i < len_safe; i += 4) {
30292 q16[0] = duk_hex_enctab[src[i]];
30293 q16[1] = duk_hex_enctab[src[i + 1]];
30294 q16[2] = duk_hex_enctab[src[i + 2]];
30295 q16[3] = duk_hex_enctab[src[i + 3]];
30296 q16 += 4;
30297 }
30298 q = (duk_uint8_t *) q16;
30299
30300#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30301 if (shift_dst) {
30302 q--;
30303 DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);
30304 DUK_ASSERT(dst + 2 * len_safe == q);
30305 }
30306#endif
30307
30308 for (; i < src_len; i++) {
30309 x = src[i];
30310 *q++ = duk_lc_digits[x >> 4];
30311 *q++ = duk_lc_digits[x & 0x0f];
30312 }
30313
30314 return q;
30315}
30316#else /* DUK_USE_HEX_FASTPATH */
30317DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
30318 const duk_uint8_t *p;
30319 const duk_uint8_t *p_end;
30320 duk_uint8_t *q;
30322
30323 p = src;
30324 p_end = src + src_len;
30325 q = dst;
30326 while (p != p_end) {
30327 x = *p++;
30328 *q++ = duk_lc_digits[x >> 4];
30329 *q++ = duk_lc_digits[x & 0x0f];
30330 }
30331
30332 return q;
30333}
30334#endif /* DUK_USE_HEX_FASTPATH */
30335
30336DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
30337 duk_hthread *thr;
30338 duk_uint8_t *q;
30339 duk_size_t space;
30340
30341 thr = js_ctx->thr;
30342
30343 DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
30345
30346 /* Buffer values are encoded in (lowercase) hex to make the
30347 * binary data readable. Base64 or similar would be more
30348 * compact but less readable, and the point of JX/JC
30349 * variants is to be as useful to a programmer as possible.
30350 */
30351
30352 /* The #ifdef clutter here needs to handle the three cases:
30353 * (1) JX+JC, (2) JX only, (3) JC only.
30354 */
30355
30356 /* Note: space must cater for both JX and JC. */
30357 space = 9 + buf_len * 2 + 2;
30358 DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
30359 DUK_ASSERT((space - 2) / 2 >= buf_len); /* overflow not possible, buffer limits */
30360 q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
30361
30362#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30363 if (js_ctx->flag_ext_custom)
30364#endif
30365#if defined(DUK_USE_JX)
30366 {
30367 *q++ = DUK_ASC_PIPE;
30368 q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
30369 *q++ = DUK_ASC_PIPE;
30370
30371 }
30372#endif
30373#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30374 else
30375#endif
30376#if defined(DUK_USE_JC)
30377 {
30379 DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */
30380 q += 9;
30381 q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
30382 *q++ = DUK_ASC_DOUBLEQUOTE;
30383 *q++ = DUK_ASC_RCURLY;
30384 }
30385#endif
30386
30387 DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
30388}
30389
30391 duk__enc_buffer_data(js_ctx,
30392 (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
30394}
30395#endif /* DUK_USE_JX || DUK_USE_JC */
30396
30397#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30398DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
30399 char buf[64]; /* XXX: how to figure correct size? */
30400 const char *fmt;
30401
30402 DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
30404
30405 DUK_MEMZERO(buf, sizeof(buf));
30406
30407 /* The #ifdef clutter here needs to handle the three cases:
30408 * (1) JX+JC, (2) JX only, (3) JC only.
30409 */
30410#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30411 if (js_ctx->flag_ext_custom)
30412#endif
30413#if defined(DUK_USE_JX)
30414 {
30415 fmt = ptr ? "(%p)" : "(null)";
30416 }
30417#endif
30418#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30419 else
30420#endif
30421#if defined(DUK_USE_JC)
30422 {
30424 fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
30425 }
30426#endif
30427
30428 /* When ptr == NULL, the format argument is unused. */
30429 DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
30430 DUK__EMIT_CSTR(js_ctx, buf);
30431}
30432#endif /* DUK_USE_JX || DUK_USE_JC */
30433
30434#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30437
30438 if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
30440 } else {
30441 /* Handle both full and partial slice (as long as covered). */
30442 duk__enc_buffer_data(js_ctx,
30443 (duk_uint8_t *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
30444 (duk_size_t) h_bufobj->length);
30445 }
30447#endif /* DUK_USE_JX || DUK_USE_JC */
30448
30449/* Indent helper. Calling code relies on js_ctx->recursion_depth also being
30450 * directly related to indent depth.
30451 */
30452#if defined(DUK_USE_PREFER_SIZE)
30454 DUK_ASSERT(js_ctx->h_gap != NULL);
30455 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
30456
30457 DUK__EMIT_1(js_ctx, 0x0a);
30458 while (depth-- > 0) {
30459 DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
30460 }
30461}
30462#else /* DUK_USE_PREFER_SIZE */
30464 const duk_uint8_t *gap_data;
30465 duk_size_t gap_len;
30466 duk_size_t avail_bytes; /* bytes of indent available for copying */
30467 duk_size_t need_bytes; /* bytes of indent still needed */
30468 duk_uint8_t *p_start;
30469 duk_uint8_t *p;
30470
30471 DUK_ASSERT(js_ctx->h_gap != NULL);
30472 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
30473
30474 DUK__EMIT_1(js_ctx, 0x0a);
30475 if (DUK_UNLIKELY(depth == 0)) {
30476 return;
30477 }
30478
30479 /* To handle deeper indents efficiently, make use of copies we've
30480 * already emitted. In effect we can emit a sequence of 1, 2, 4,
30481 * 8, etc copies, and then finish the last run. Byte counters
30482 * avoid multiply with gap_len on every loop.
30483 */
30484
30485 gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
30486 gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
30487 DUK_ASSERT(gap_len > 0);
30488
30489 need_bytes = gap_len * depth;
30490 p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
30491 p_start = p;
30492
30493 DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);
30494 p += gap_len;
30495 avail_bytes = gap_len;
30496 DUK_ASSERT(need_bytes >= gap_len);
30497 need_bytes -= gap_len;
30498
30499 while (need_bytes >= avail_bytes) {
30500 DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);
30501 p += avail_bytes;
30502 need_bytes -= avail_bytes;
30503 avail_bytes <<= 1;
30504 }
30505
30506 DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */
30507 DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);
30508 p += need_bytes;
30509 /*avail_bytes += need_bytes*/
30510
30511 DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
30512}
30513#endif /* DUK_USE_PREFER_SIZE */
30514
30515/* Shared entry handling for object/array serialization. */
30517 duk_context *ctx = (duk_context *) js_ctx->thr;
30518 duk_hobject *h_target;
30519 duk_uint_fast32_t i, n;
30520
30521 *entry_top = duk_get_top(ctx);
30522
30524
30525 /* Loop check using a hybrid approach: a fixed-size visited[] array
30526 * with overflow in a loop check object.
30527 */
30528
30529 h_target = duk_get_hobject(ctx, -1); /* object or array */
30530 DUK_ASSERT(h_target != NULL);
30531
30532 n = js_ctx->recursion_depth;
30535 }
30536 for (i = 0; i < n; i++) {
30537 if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
30538 DUK_DD(DUK_DDPRINT("slow path loop detect"));
30540 }
30541 }
30543 js_ctx->visiting[js_ctx->recursion_depth] = h_target;
30544 } else {
30545 duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
30546 duk_dup_top(ctx); /* -> [ ... voidp voidp ] */
30547 if (duk_has_prop(ctx, js_ctx->idx_loop)) {
30549 }
30550 duk_push_true(ctx); /* -> [ ... voidp true ] */
30551 duk_put_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
30552 }
30553
30554 /* C recursion check. */
30555
30556 DUK_ASSERT(js_ctx->recursion_depth >= 0);
30557 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
30558 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
30560 }
30561 js_ctx->recursion_depth++;
30562
30563 DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
30564 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
30565}
30566
30567/* Shared exit handling for object/array serialization. */
30568DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
30569 duk_context *ctx = (duk_context *) js_ctx->thr;
30570 duk_hobject *h_target;
30571
30572 /* C recursion check. */
30573
30574 DUK_ASSERT(js_ctx->recursion_depth > 0);
30575 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
30576 js_ctx->recursion_depth--;
30577
30578 /* Loop check. */
30579
30580 h_target = duk_get_hobject(ctx, *entry_top - 1); /* original target at entry_top - 1 */
30581 DUK_ASSERT(h_target != NULL);
30582
30584 /* Previous entry was inside visited[], nothing to do. */
30585 } else {
30586 duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
30587 duk_del_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
30588 }
30589
30590 /* Restore stack top after unbalanced code paths. */
30591 duk_set_top(ctx, *entry_top);
30592
30593 DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
30594 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
30595}
30596
30597/* The JO(value) operation: encode object.
30598 *
30599 * Stack policy: [ object ] -> [ object ].
30600 */
30602 duk_context *ctx = (duk_context *) js_ctx->thr;
30603 duk_hstring *h_key;
30604 duk_idx_t entry_top;
30605 duk_idx_t idx_obj;
30606 duk_idx_t idx_keys;
30607 duk_bool_t emitted;
30608 duk_uarridx_t arr_len, i;
30609 duk_size_t prev_size;
30610
30611 DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30612
30613 duk__enc_objarr_entry(js_ctx, &entry_top);
30614
30615 idx_obj = entry_top - 1;
30616
30617 if (js_ctx->idx_proplist >= 0) {
30618 idx_keys = js_ctx->idx_proplist;
30619 } else {
30620 /* XXX: would be nice to enumerate an object at specified index */
30621 duk_dup(ctx, idx_obj);
30622 (void) duk_hobject_get_enumerated_keys(ctx, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); /* [ ... target ] -> [ ... target keys ] */
30623 idx_keys = duk_require_normalize_index(ctx, -1);
30624 /* leave stack unbalanced on purpose */
30625 }
30626
30627 DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
30628 (long) idx_keys, (duk_tval *) duk_get_tval(ctx, idx_keys)));
30629
30630 /* Steps 8-10 have been merged to avoid a "partial" variable. */
30631
30632 DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
30633
30634 /* XXX: keys is an internal object with all keys to be processed
30635 * in its (gapless) array part. Because nobody can touch the keys
30636 * object, we could iterate its array part directly (keeping in mind
30637 * that it can be reallocated).
30638 */
30639
30640 arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_keys);
30641 emitted = 0;
30642 for (i = 0; i < arr_len; i++) {
30643 duk_get_prop_index(ctx, idx_keys, i); /* -> [ ... key ] */
30644
30645 DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
30646 (duk_tval *) duk_get_tval(ctx, idx_obj),
30647 (duk_tval *) duk_get_tval(ctx, -1)));
30648
30649 h_key = duk_get_hstring(ctx, -1);
30650 DUK_ASSERT(h_key != NULL);
30651
30652 prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
30653 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30655 duk__enc_key_autoquote(js_ctx, h_key);
30657 } else {
30658 duk__enc_key_autoquote(js_ctx, h_key);
30659 DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
30660 }
30661
30662 /* [ ... key ] */
30663
30664 if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
30665 /* Value would yield 'undefined', so skip key altogether.
30666 * Side effects have already happened.
30667 */
30668 DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
30669 } else {
30670 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
30671 emitted = 1;
30672 }
30673
30674 /* [ ... ] */
30675 }
30676
30677 if (emitted) {
30678 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
30679 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
30680 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30681 DUK_ASSERT(js_ctx->recursion_depth >= 1);
30682 duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
30683 }
30684 }
30685 DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
30686
30687 duk__enc_objarr_exit(js_ctx, &entry_top);
30688
30689 DUK_ASSERT_TOP(ctx, entry_top);
30690}
30691
30692/* The JA(value) operation: encode array.
30693 *
30694 * Stack policy: [ array ] -> [ array ].
30695 */
30697 duk_context *ctx = (duk_context *) js_ctx->thr;
30698 duk_idx_t entry_top;
30699 duk_idx_t idx_arr;
30700 duk_bool_t emitted;
30701 duk_uarridx_t i, arr_len;
30702
30703 DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
30704 (duk_tval *) duk_get_tval(ctx, -1)));
30705
30706 duk__enc_objarr_entry(js_ctx, &entry_top);
30707
30708 idx_arr = entry_top - 1;
30709
30710 /* Steps 8-10 have been merged to avoid a "partial" variable. */
30711
30713
30714 arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_arr);
30715 emitted = 0;
30716 for (i = 0; i < arr_len; i++) {
30717 DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
30718 (duk_tval *) duk_get_tval(ctx, idx_arr),
30719 (long) i, (long) arr_len));
30720
30721 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30722 DUK_ASSERT(js_ctx->recursion_depth >= 1);
30724 }
30725
30726 /* XXX: duk_push_uint_string() */
30727 duk_push_uint(ctx, (duk_uint_t) i);
30728 duk_to_string(ctx, -1); /* -> [ ... key ] */
30729
30730 /* [ ... key ] */
30731
30732 if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
30733 /* Value would normally be omitted, replace with 'null'. */
30735 } else {
30736 ;
30737 }
30738
30739 /* [ ... ] */
30740
30741 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
30742 emitted = 1;
30743 }
30744
30745 if (emitted) {
30746 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
30747 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
30748 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30749 DUK_ASSERT(js_ctx->recursion_depth >= 1);
30750 duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
30751 }
30752 }
30754
30755 duk__enc_objarr_exit(js_ctx, &entry_top);
30756
30757 DUK_ASSERT_TOP(ctx, entry_top);
30758}
30759
30760/* The Str(key, holder) operation.
30761 *
30762 * Stack policy: [ ... key ] -> [ ... ]
30763 */
30765 duk_context *ctx = (duk_context *) js_ctx->thr;
30766 duk_hthread *thr = (duk_hthread *) ctx;
30767 duk_hobject *h_tmp;
30768 duk_tval *tv;
30769 duk_tval *tv_holder;
30770 duk_tval *tv_key;
30772
30773 DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
30774 (long) idx_holder, (duk_tval *) duk_get_tval(ctx, idx_holder),
30775 (duk_tval *) duk_get_tval(ctx, -1)));
30776
30777 DUK_UNREF(thr);
30778
30779 tv_holder = DUK_GET_TVAL_POSIDX(ctx, idx_holder);
30780 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
30781 tv_key = DUK_GET_TVAL_NEGIDX(ctx, -1);
30783 (void) duk_hobject_getprop(thr, tv_holder, tv_key);
30784
30785 /* -> [ ... key val ] */
30786
30787 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30788
30789 h_tmp = duk_get_hobject_or_lfunc_coerce(ctx, -1);
30790 if (h_tmp != NULL) {
30792 h_tmp = duk_get_hobject_or_lfunc_coerce(ctx, -1); /* toJSON() can also be a lightfunc */
30793
30794 if (h_tmp != NULL && DUK_HOBJECT_IS_CALLABLE(h_tmp)) {
30795 DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
30796 /* XXX: duk_dup_unvalidated(ctx, -2) etc. */
30797 duk_dup(ctx, -2); /* -> [ ... key val toJSON val ] */
30798 duk_dup(ctx, -4); /* -> [ ... key val toJSON val key ] */
30799 duk_call_method(ctx, 1); /* -> [ ... key val val' ] */
30800 duk_remove(ctx, -2); /* -> [ ... key val' ] */
30801 } else {
30802 duk_pop(ctx); /* -> [ ... key val ] */
30803 }
30804 }
30805
30806 /* [ ... key val ] */
30807
30808 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30809
30810 if (js_ctx->h_replacer) {
30811 /* XXX: Here a "slice copy" would be useful. */
30812 DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
30813 duk_push_hobject(ctx, js_ctx->h_replacer); /* -> [ ... key val replacer ] */
30814 duk_dup(ctx, idx_holder); /* -> [ ... key val replacer holder ] */
30815 duk_dup(ctx, -4); /* -> [ ... key val replacer holder key ] */
30816 duk_dup(ctx, -4); /* -> [ ... key val replacer holder key val ] */
30817 duk_call_method(ctx, 2); /* -> [ ... key val val' ] */
30818 duk_remove(ctx, -2); /* -> [ ... key val' ] */
30819 }
30820
30821 /* [ ... key val ] */
30822
30823 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30824
30825 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30826 if (DUK_TVAL_IS_OBJECT(tv)) {
30827 duk_hobject *h;
30828
30829 h = DUK_TVAL_GET_OBJECT(tv);
30830 DUK_ASSERT(h != NULL);
30831
30833#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30834 duk_hbufferobject *h_bufobj;
30835 h_bufobj = (duk_hbufferobject *) h;
30837
30838 /* Conceptually we'd extract the plain underlying buffer
30839 * or its slice and then do a type mask check below to
30840 * see if we should reject it. Do the mask check here
30841 * instead to avoid making a copy of the buffer slice.
30842 */
30843
30845 DUK_DDD(DUK_DDDPRINT("-> bufferobject (-> plain buffer) will result in undefined (type mask check)"));
30846 goto pop2_undef;
30847 }
30848 DUK_DDD(DUK_DDDPRINT("-> bufferobject won't result in undefined, encode directly"));
30849 duk__enc_bufferobject(js_ctx, h_bufobj);
30850 goto pop2_emitted;
30851#else
30852 DUK_DDD(DUK_DDDPRINT("no JX/JC support, bufferobject/buffer will always result in undefined"));
30853 goto pop2_undef;
30854#endif
30855 } else {
30857 switch ((int) c) {
30859 DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
30860 duk_to_number(ctx, -1);
30861 /* The coercion potentially invokes user .valueOf() and .toString()
30862 * but can't result in a function value because [[DefaultValue]] would
30863 * reject such a result: test-dev-json-stringify-coercion-1.js.
30864 */
30865 DUK_ASSERT(!duk_is_callable(ctx, -1));
30866 break;
30867 }
30869 DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
30870 duk_to_string(ctx, -1);
30871 /* Same coercion behavior as for Number. */
30872 DUK_ASSERT(!duk_is_callable(ctx, -1));
30873 break;
30874 }
30875#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30877#endif
30879 DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
30881 duk_remove(ctx, -2);
30882 break;
30883 }
30884 default: {
30885 /* Normal object which doesn't get automatically coerced to a
30886 * primitive value. Functions are checked for specially. The
30887 * primitive value coercions for Number, String, Pointer, and
30888 * Boolean can't result in functions so suffices to check here.
30889 */
30890 DUK_ASSERT(h != NULL);
30891 if (DUK_HOBJECT_IS_CALLABLE(h)) {
30892#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30893 if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
30895 /* We only get here when doing non-standard JSON encoding */
30896 DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
30899 goto pop2_emitted;
30900 } else {
30901 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
30902 goto pop2_undef;
30903 }
30904#else /* DUK_USE_JX || DUK_USE_JC */
30905 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
30906 goto pop2_undef;
30907#endif /* DUK_USE_JX || DUK_USE_JC */
30908 }
30909 }
30910 } /* end switch */
30911 }
30912 }
30913
30914 /* [ ... key val ] */
30915
30916 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30917
30918 if (duk_check_type_mask(ctx, -1, js_ctx->mask_for_undefined)) {
30919 /* will result in undefined */
30920 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
30921 goto pop2_undef;
30922 }
30923 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30924
30925 switch (DUK_TVAL_GET_TAG(tv)) {
30926#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30927 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
30928 case DUK_TAG_UNDEFINED: {
30930 break;
30931 }
30932#endif
30933 case DUK_TAG_NULL: {
30935 break;
30936 }
30937 case DUK_TAG_BOOLEAN: {
30940 break;
30941 }
30942#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30943 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
30944 case DUK_TAG_POINTER: {
30946 break;
30947 }
30948#endif /* DUK_USE_JX || DUK_USE_JC */
30949 case DUK_TAG_STRING: {
30951 DUK_ASSERT(h != NULL);
30952
30953 duk__enc_quote_string(js_ctx, h);
30954 break;
30955 }
30956 case DUK_TAG_OBJECT: {
30958 DUK_ASSERT(h != NULL);
30959
30960 /* Function values are handled completely above (including
30961 * coercion results):
30962 */
30964
30966 duk__enc_array(js_ctx);
30967 } else {
30968 duk__enc_object(js_ctx);
30969 }
30970 break;
30971 }
30972#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30973 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
30974 case DUK_TAG_BUFFER: {
30976 break;
30977 }
30978#endif /* DUK_USE_JX || DUK_USE_JC */
30979 case DUK_TAG_LIGHTFUNC: {
30980#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30981 /* We only get here when doing non-standard JSON encoding */
30984#else
30985 /* Standard JSON omits functions */
30987#endif
30988 break;
30989 }
30990#if defined(DUK_USE_FASTINT)
30991 case DUK_TAG_FASTINT:
30992 /* Number serialization has a significant impact relative to
30993 * other fast path code, so careful fast path for fastints.
30994 */
30995 duk__enc_fastint_tval(js_ctx, tv);
30996 break;
30997#endif
30998 default: {
30999 /* number */
31002 /* XXX: A fast path for usual integers would be useful when
31003 * fastint support is not enabled.
31004 */
31005 duk__enc_double(js_ctx);
31006 break;
31007 }
31008 }
31009
31010 pop2_emitted:
31011 duk_pop_2(ctx); /* [ ... key val ] -> [ ... ] */
31012 return 1; /* emitted */
31013
31014 pop2_undef:
31015 duk_pop_2(ctx); /* [ ... key val ] -> [ ... ] */
31016 return 0; /* not emitted */
31017}
31018
31019/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
31021 duk_hobject *h;
31023
31024 DUK_ASSERT(tv != NULL);
31025 if (DUK_TVAL_IS_STRING(tv) || DUK_TVAL_IS_NUMBER(tv)) {
31026 return 1;
31027 } else if (DUK_TVAL_IS_OBJECT(tv)) {
31028 h = DUK_TVAL_GET_OBJECT(tv);
31029 DUK_ASSERT(h != NULL);
31032 return 1;
31033 }
31034 }
31035
31036 return 0;
31037}
31038
31039/*
31040 * JSON.stringify() fast path
31041 *
31042 * Otherwise supports full JSON, JX, and JC features, but bails out on any
31043 * possible side effect which might change the value being serialized. The
31044 * fast path can take advantage of the fact that the value being serialized
31045 * is unchanged so that we can walk directly through property tables etc.
31046 */
31047
31048#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
31049DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
31050 duk_uint_fast32_t i, n;
31051
31052 DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
31053
31054 DUK_ASSERT(js_ctx != NULL);
31055 DUK_ASSERT(js_ctx->thr != NULL);
31056
31057#if 0 /* disabled for now */
31058 restart_match:
31059#endif
31060
31061 DUK_ASSERT(tv != NULL);
31062
31063 switch (DUK_TVAL_GET_TAG(tv)) {
31064 case DUK_TAG_UNDEFINED: {
31065#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31066 if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
31068 break;
31069 } else {
31070 goto emit_undefined;
31071 }
31072#else
31073 goto emit_undefined;
31074#endif
31075 }
31076 case DUK_TAG_NULL: {
31078 break;
31079 }
31080 case DUK_TAG_BOOLEAN: {
31083 break;
31084 }
31085 case DUK_TAG_STRING: {
31086 duk_hstring *h;
31087
31088 h = DUK_TVAL_GET_STRING(tv);
31089 DUK_ASSERT(h != NULL);
31090 duk__enc_quote_string(js_ctx, h);
31091 break;
31092 }
31093 case DUK_TAG_OBJECT: {
31094 duk_hobject *obj;
31095 duk_tval *tv_val;
31096 duk_bool_t emitted = 0;
31097 duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
31098 c_func, c_bufobj, c_object;
31099
31100 /* For objects JSON.stringify() only looks for own, enumerable
31101 * properties which is nice for the fast path here.
31102 *
31103 * For arrays JSON.stringify() uses [[Get]] so it will actually
31104 * inherit properties during serialization! This fast path
31105 * supports gappy arrays as long as there's no actual inherited
31106 * property (which might be a getter etc).
31107 *
31108 * Since recursion only happens for objects, we can have both
31109 * recursion and loop checks here. We use a simple, depth-limited
31110 * loop check in the fast path because the object-based tracking
31111 * is very slow (when tested, it accounted for 50% of fast path
31112 * execution time for input data with a lot of small objects!).
31113 */
31114
31115 /* XXX: for real world code, could just ignore array inheritance
31116 * and only look at array own properties.
31117 */
31118
31119 /* We rely on a few object flag / class number relationships here,
31120 * assert for them.
31121 */
31122
31123 obj = DUK_TVAL_GET_OBJECT(tv);
31124 DUK_ASSERT(obj != NULL);
31126
31127 /* Once recursion depth is increased, exit path must decrease
31128 * it (though it's OK to abort the fast path).
31129 */
31130
31131 DUK_ASSERT(js_ctx->recursion_depth >= 0);
31132 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31133 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
31134 DUK_DD(DUK_DDPRINT("fast path recursion limit"));
31136 }
31137
31138 for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
31139 if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
31140 DUK_DD(DUK_DDPRINT("fast path loop detect"));
31142 }
31143 }
31144
31145 /* Guaranteed by recursion_limit setup so we don't have to
31146 * check twice.
31147 */
31149 js_ctx->visiting[js_ctx->recursion_depth] = obj;
31150 js_ctx->recursion_depth++;
31151
31152 /* If object has a .toJSON() property, we can't be certain
31153 * that it wouldn't mutate any value arbitrarily, so bail
31154 * out of the fast path.
31155 *
31156 * If an object is a Proxy we also can't avoid side effects
31157 * so abandon.
31158 */
31159 /* XXX: non-callable .toJSON() doesn't need to cause an abort
31160 * but does at the moment, probably not worth fixing.
31161 */
31162 if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
31164 DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
31165 goto abort_fastpath;
31166 }
31167
31168 /* We could use a switch-case for the class number but it turns out
31169 * a small if-else ladder on class masks is better. The if-ladder
31170 * should be in order of relevancy.
31171 */
31172
31173 /* XXX: move masks to js_ctx? they don't change during one
31174 * fast path invocation.
31175 */
31177#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31178 if (js_ctx->flag_ext_custom_or_compatible) {
31179 c_all = DUK_HOBJECT_CMASK_ALL;
31180 c_array = DUK_HOBJECT_CMASK_ARRAY;
31181 c_unbox = DUK_HOBJECT_CMASK_NUMBER |
31187 c_undef = 0;
31188 c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
31189 }
31190 else
31191#endif
31192 {
31193 c_all = DUK_HOBJECT_CMASK_ALL;
31194 c_array = DUK_HOBJECT_CMASK_ARRAY;
31195 c_unbox = DUK_HOBJECT_CMASK_NUMBER |
31198 c_func = 0;
31199 c_bufobj = 0;
31200 c_undef = DUK_HOBJECT_CMASK_FUNCTION |
31203 c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
31204 }
31205
31206 c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj);
31207 if (c_bit & c_object) {
31208 /* All other object types. */
31209 DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
31210
31211 /* A non-Array object should not have an array part in practice.
31212 * But since it is supported internally (and perhaps used at some
31213 * point), check and abandon if that's the case.
31214 */
31215 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
31216 DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
31217 goto abort_fastpath;
31218 }
31219
31220 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
31221 duk_hstring *k;
31222 duk_size_t prev_size;
31223
31224 k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
31225 if (!k) {
31226 continue;
31227 }
31228 if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
31229 continue;
31230 }
31231 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
31232 /* Getter might have arbitrary side effects,
31233 * so bail out.
31234 */
31235 DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
31236 goto abort_fastpath;
31237 }
31238 if (DUK_HSTRING_HAS_INTERNAL(k)) {
31239 continue;
31240 }
31241
31242 tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
31243
31244 prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
31245 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31247 duk__enc_key_autoquote(js_ctx, k);
31249 } else {
31250 duk__enc_key_autoquote(js_ctx, k);
31251 DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
31252 }
31253
31254 if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
31255 DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
31256 DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
31257 } else {
31258 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
31259 emitted = 1;
31260 }
31261 }
31262
31263 /* If any non-Array value had enumerable virtual own
31264 * properties, they should be serialized here. Standard
31265 * types don't.
31266 */
31267
31268 if (emitted) {
31269 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
31270 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
31271 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31272 DUK_ASSERT(js_ctx->recursion_depth >= 1);
31273 duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
31274 }
31275 }
31276 DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
31277 } else if (c_bit & c_array) {
31278 duk_uint_fast32_t arr_len;
31279 duk_uint_fast32_t asize;
31280
31282
31283 /* Assume arrays are dense in the fast path. */
31284 if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
31285 DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
31286 goto abort_fastpath;
31287 }
31288
31289 arr_len = (duk_uint_fast32_t) duk_hobject_get_length(js_ctx->thr, obj);
31291 if (arr_len > asize) {
31292 /* Array length is larger than 'asize'. This shouldn't
31293 * happen in practice. Bail out just in case.
31294 */
31295 DUK_DD(DUK_DDPRINT("arr_len > asize, abort fast path"));
31296 goto abort_fastpath;
31297 }
31298 /* Array part may be larger than 'length'; if so, iterate
31299 * only up to array 'length'.
31300 */
31301 for (i = 0; i < arr_len; i++) {
31303
31304 tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
31305
31306 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31308 }
31309
31310 if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_val))) {
31311 /* Gap in array; check for inherited property,
31312 * bail out if one exists. This should be enough
31313 * to support gappy arrays for all practical code.
31314 */
31315 duk_hstring *h_tmp;
31316 duk_bool_t has_inherited;
31317
31318 /* XXX: refactor into an internal helper, pretty awkward */
31319 duk_push_uint((duk_context *) js_ctx->thr, (duk_uint_t) i);
31320 h_tmp = duk_to_hstring((duk_context *) js_ctx->thr, -1);
31321 DUK_ASSERT(h_tmp != NULL);
31322 has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
31323 duk_pop((duk_context *) js_ctx->thr);
31324
31325 if (has_inherited) {
31326 DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
31327 goto abort_fastpath;
31328 }
31329
31330 /* Ordinary gap, undefined encodes to 'null' in
31331 * standard JSON (and no JX/JC support here now).
31332 */
31333 DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
31334#if defined(DUK_USE_JX)
31336#else
31338#endif
31339 } else {
31340 if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
31342 }
31343 }
31344
31345 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
31346 emitted = 1;
31347 }
31348
31349 if (emitted) {
31350 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
31351 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
31352 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31353 DUK_ASSERT(js_ctx->recursion_depth >= 1);
31354 duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
31355 }
31356 }
31358 } else if (c_bit & c_unbox) {
31359 /* Certain boxed types are required to go through
31360 * automatic unboxing. Rely on internal value being
31361 * sane (to avoid infinite recursion).
31362 */
31363#if 1
31364 /* The code below is incorrect if .toString() or .valueOf() have
31365 * have been overridden. The correct approach would be to look up
31366 * the method(s) and if they resolve to the built-in function we
31367 * can safely bypass it and look up the internal value directly.
31368 * Unimplemented for now, abort fast path for boxed values.
31369 */
31370 goto abort_fastpath;
31371#else /* disabled */
31372 /* Disabled until fixed, see above. */
31373 duk_tval *tv_internal;
31374
31375 DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
31376
31377 tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
31378 DUK_ASSERT(tv_internal != NULL);
31379 DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
31380 DUK_TVAL_IS_NUMBER(tv_internal) ||
31381 DUK_TVAL_IS_BOOLEAN(tv_internal) ||
31382 DUK_TVAL_IS_POINTER(tv_internal));
31383
31384 tv = tv_internal;
31385 DUK_ASSERT(js_ctx->recursion_depth > 0);
31386 js_ctx->recursion_depth--; /* required to keep recursion depth correct */
31387 goto restart_match;
31388#endif /* disabled */
31389#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31390 } else if (c_bit & c_func) {
31392 } else if (c_bit & c_bufobj) {
31394#endif
31395 } else {
31396 DUK_ASSERT((c_bit & c_undef) != 0);
31397
31398 /* Must decrease recursion depth before returning. */
31399 DUK_ASSERT(js_ctx->recursion_depth > 0);
31400 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31401 js_ctx->recursion_depth--;
31402 goto emit_undefined;
31403 }
31404
31405 DUK_ASSERT(js_ctx->recursion_depth > 0);
31406 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31407 js_ctx->recursion_depth--;
31408 break;
31409 }
31410 case DUK_TAG_BUFFER: {
31411#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31412 if (js_ctx->flag_ext_custom_or_compatible) {
31414 break;
31415 } else {
31416 goto emit_undefined;
31417 }
31418#else
31419 goto emit_undefined;
31420#endif
31421 }
31422 case DUK_TAG_POINTER: {
31423#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31424 if (js_ctx->flag_ext_custom_or_compatible) {
31426 break;
31427 } else {
31428 goto emit_undefined;
31429 }
31430#else
31431 goto emit_undefined;
31432#endif
31433 }
31434 case DUK_TAG_LIGHTFUNC: {
31435 /* A lightfunc might also inherit a .toJSON() so just bail out. */
31436 /* XXX: Could just lookup .toJSON() and continue in fast path,
31437 * as it would almost never be defined.
31438 */
31439 DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
31440 goto abort_fastpath;
31441 }
31442#if defined(DUK_USE_FASTINT)
31443 case DUK_TAG_FASTINT: {
31444 /* Number serialization has a significant impact relative to
31445 * other fast path code, so careful fast path for fastints.
31446 */
31447 duk__enc_fastint_tval(js_ctx, tv);
31448 break;
31449 }
31450#endif
31451 default: {
31452 /* XXX: A fast path for usual integers would be useful when
31453 * fastint support is not enabled.
31454 */
31457
31458 /* XXX: Stack discipline is annoying, could be changed in numconv. */
31459 duk_push_tval((duk_context *) js_ctx->thr, tv);
31460 duk__enc_double(js_ctx);
31461 duk_pop((duk_context *) js_ctx->thr);
31462
31463#if 0
31464 /* Could also rely on native sprintf(), but it will handle
31465 * values like NaN, Infinity, -0, exponent notation etc in
31466 * a JSON-incompatible way.
31467 */
31468 duk_double_t d;
31469 char buf[64];
31470
31472 d = DUK_TVAL_GET_DOUBLE(tv);
31473 DUK_SPRINTF(buf, "%lg", d);
31474 DUK__EMIT_CSTR(js_ctx, buf);
31475#endif
31476 }
31477 }
31478 return 1; /* not undefined */
31479
31480 emit_undefined:
31481 return 0; /* value was undefined/unsupported */
31482
31483 abort_fastpath:
31484 /* Error message doesn't matter: the error is ignored anyway. */
31485 DUK_DD(DUK_DDPRINT("aborting fast path"));
31487 return 0; /* unreachable */
31488}
31489
31490DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_context *ctx) {
31491 duk_json_enc_ctx *js_ctx;
31492 duk_tval *tv;
31493
31494 DUK_ASSERT(ctx != NULL);
31495 tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
31497 js_ctx = (duk_json_enc_ctx *) DUK_TVAL_GET_POINTER(tv);
31498 DUK_ASSERT(js_ctx != NULL);
31499
31500 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
31501 if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
31502 DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
31503 return DUK_RET_ERROR; /* error message doesn't matter, ignored anyway */
31504 }
31505
31506 return 0;
31507}
31508#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
31509
31510/*
31511 * Top level wrappers
31512 */
31513
31516 duk_idx_t idx_value,
31517 duk_idx_t idx_reviver,
31518 duk_small_uint_t flags) {
31519 duk_hthread *thr = (duk_hthread *) ctx;
31520 duk_json_dec_ctx js_ctx_alloc;
31521 duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
31522 duk_hstring *h_text;
31523#ifdef DUK_USE_ASSERTIONS
31524 duk_idx_t entry_top = duk_get_top(ctx);
31525#endif
31526
31527 /* negative top-relative indices not allowed now */
31528 DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
31529 DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
31530
31531 DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
31532 (duk_tval *) duk_get_tval(ctx, idx_value),
31533 (duk_tval *) duk_get_tval(ctx, idx_reviver),
31534 (unsigned long) flags,
31535 (long) duk_get_top(ctx)));
31536
31537 DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
31538 js_ctx->thr = thr;
31539#ifdef DUK_USE_EXPLICIT_NULL_INIT
31540 /* nothing now */
31541#endif
31543 DUK_ASSERT(js_ctx->recursion_depth == 0);
31544
31545 /* Flag handling currently assumes that flags are consistent. This is OK
31546 * because the call sites are now strictly controlled.
31547 */
31548
31549 js_ctx->flags = flags;
31550#if defined(DUK_USE_JX)
31551 js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
31552#endif
31553#if defined(DUK_USE_JC)
31555#endif
31556#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31558#endif
31559
31560 h_text = duk_to_hstring(ctx, idx_value); /* coerce in-place */
31561 DUK_ASSERT(h_text != NULL);
31562
31563 /* JSON parsing code is allowed to read [p_start,p_end]: p_end is
31564 * valid and points to the string NUL terminator (which is always
31565 * guaranteed for duk_hstrings.
31566 */
31567 js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
31568 js_ctx->p = js_ctx->p_start;
31569 js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
31571 DUK_ASSERT(*(js_ctx->p_end) == 0x00);
31572
31573 duk__dec_value(js_ctx); /* -> [ ... value ] */
31574
31575 /* Trailing whitespace has been eaten by duk__dec_value(), so if
31576 * we're not at end of input here, it's a SyntaxError.
31577 */
31578
31579 if (js_ctx->p != js_ctx->p_end) {
31580 duk__dec_syntax_error(js_ctx);
31581 }
31582
31583 if (duk_is_callable(ctx, idx_reviver)) {
31584 DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
31585 (duk_tval *) duk_get_tval(ctx, idx_reviver)));
31586
31587 js_ctx->idx_reviver = idx_reviver;
31588
31589 duk_push_object(ctx);
31590 duk_dup(ctx, -2); /* -> [ ... val root val ] */
31591 duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING); /* default attrs ok */
31592 duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); /* -> [ ... val root "" ] */
31593
31594 DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
31595 (duk_tval *) duk_get_tval(ctx, -2),
31596 (duk_tval *) duk_get_tval(ctx, -1)));
31597
31598 duk__dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */
31599 duk_remove(ctx, -2); /* -> [ ... val' ] */
31600 } else {
31601 DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
31602 (duk_tval *) duk_get_tval(ctx, idx_reviver)));
31603 }
31604
31605 /* Final result is at stack top. */
31606
31607 DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
31608 (duk_tval *) duk_get_tval(ctx, idx_value),
31609 (duk_tval *) duk_get_tval(ctx, idx_reviver),
31610 (unsigned long) flags,
31611 (duk_tval *) duk_get_tval(ctx, -1),
31612 (long) duk_get_top(ctx)));
31613
31614 DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
31615}
31616
31619 duk_idx_t idx_value,
31620 duk_idx_t idx_replacer,
31621 duk_idx_t idx_space,
31622 duk_small_uint_t flags) {
31623 duk_hthread *thr = (duk_hthread *) ctx;
31624 duk_json_enc_ctx js_ctx_alloc;
31625 duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
31626 duk_hobject *h;
31627 duk_idx_t idx_holder;
31628 duk_idx_t entry_top;
31629
31630 /* negative top-relative indices not allowed now */
31631 DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
31632 DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
31633 DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
31634
31635 DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
31636 (duk_tval *) duk_get_tval(ctx, idx_value),
31637 (duk_tval *) duk_get_tval(ctx, idx_replacer),
31638 (duk_tval *) duk_get_tval(ctx, idx_space),
31639 (unsigned long) flags,
31640 (long) duk_get_top(ctx)));
31641
31642 entry_top = duk_get_top(ctx);
31643
31644 /*
31645 * Context init
31646 */
31647
31648 DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
31649 js_ctx->thr = thr;
31650#ifdef DUK_USE_EXPLICIT_NULL_INIT
31651 js_ctx->h_replacer = NULL;
31652 js_ctx->h_gap = NULL;
31653#endif
31654 js_ctx->idx_proplist = -1;
31655
31656 /* Flag handling currently assumes that flags are consistent. This is OK
31657 * because the call sites are now strictly controlled.
31658 */
31659
31660 js_ctx->flags = flags;
31661 js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
31663#ifdef DUK_USE_JX
31664 js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
31665#endif
31666#ifdef DUK_USE_JC
31668#endif
31669#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31671#endif
31672
31673 /* The #ifdef clutter here handles the JX/JC enable/disable
31674 * combinations properly.
31675 */
31676#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31677 js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL; /* standard JSON; array gaps */
31678#if defined(DUK_USE_JX)
31679 if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
31684 js_ctx->stridx_custom_function =
31688 }
31689#endif /* DUK_USE_JX */
31690#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
31691 else
31692#endif /* DUK_USE_JX && DUK_USE_JC */
31693#if defined(DUK_USE_JC)
31694 if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
31700 }
31701#endif /* DUK_USE_JC */
31702#endif /* DUK_USE_JX || DUK_USE_JC */
31703
31704#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31705 if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
31707 DUK_ASSERT(js_ctx->mask_for_undefined == 0); /* already zero */
31708 }
31709 else
31710#endif /* DUK_USE_JX || DUK_USE_JC */
31711 {
31716 }
31717
31719
31720 js_ctx->idx_loop = duk_push_object_internal(ctx);
31721 DUK_ASSERT(js_ctx->idx_loop >= 0);
31722
31723 /* [ ... buf loop ] */
31724
31725 /*
31726 * Process replacer/proplist (2nd argument to JSON.stringify)
31727 */
31728
31729 h = duk_get_hobject(ctx, idx_replacer);
31730 if (h != NULL) {
31731 if (DUK_HOBJECT_IS_CALLABLE(h)) {
31732 js_ctx->h_replacer = h;
31734 /* Here the specification requires correct array index enumeration
31735 * which is a bit tricky for sparse arrays (it is handled by the
31736 * enum setup code). We now enumerate ancestors too, although the
31737 * specification is not very clear on whether that is required.
31738 */
31739
31740 duk_uarridx_t plist_idx = 0;
31741 duk_small_uint_t enum_flags;
31742
31743 js_ctx->idx_proplist = duk_push_array(ctx); /* XXX: array internal? */
31744
31745 enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
31746 DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */
31747 duk_enum(ctx, idx_replacer, enum_flags);
31748 while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) {
31749 /* [ ... proplist enum_obj key val ] */
31751 /* XXX: duplicates should be eliminated here */
31752 DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
31753 (duk_tval *) duk_get_tval(ctx, -2),
31754 (duk_tval *) duk_get_tval(ctx, -1)));
31755 duk_to_string(ctx, -1); /* extra coercion of strings is OK */
31756 duk_put_prop_index(ctx, -4, plist_idx); /* -> [ ... proplist enum_obj key ] */
31757 plist_idx++;
31758 duk_pop(ctx);
31759 } else {
31760 DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
31761 (duk_tval *) duk_get_tval(ctx, -2),
31762 (duk_tval *) duk_get_tval(ctx, -1)));
31763 duk_pop_2(ctx);
31764 }
31765 }
31766 duk_pop(ctx); /* pop enum */
31767
31768 /* [ ... proplist ] */
31769 }
31770 }
31771
31772 /* [ ... buf loop (proplist) ] */
31773
31774 /*
31775 * Process space (3rd argument to JSON.stringify)
31776 */
31777
31778 h = duk_get_hobject(ctx, idx_space);
31779 if (h != NULL) {
31781 if (c == DUK_HOBJECT_CLASS_NUMBER) {
31782 duk_to_number(ctx, idx_space);
31783 } else if (c == DUK_HOBJECT_CLASS_STRING) {
31784 duk_to_string(ctx, idx_space);
31785 }
31786 }
31787
31788 if (duk_is_number(ctx, idx_space)) {
31789 duk_small_int_t nspace;
31790 /* spaces[] must be static to allow initializer with old compilers like BCC */
31791 static const char spaces[10] = {
31795 }; /* XXX: helper */
31796
31797 /* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
31798 nspace = (duk_small_int_t) duk_to_int_clamped(ctx, idx_space, 0 /*minval*/, 10 /*maxval*/);
31799 DUK_ASSERT(nspace >= 0 && nspace <= 10);
31800
31801 duk_push_lstring(ctx, spaces, (duk_size_t) nspace);
31802 js_ctx->h_gap = duk_get_hstring(ctx, -1);
31803 DUK_ASSERT(js_ctx->h_gap != NULL);
31804 } else if (duk_is_string(ctx, idx_space)) {
31805 /* XXX: substring in-place at idx_place? */
31806 duk_dup(ctx, idx_space);
31807 duk_substring(ctx, -1, 0, 10); /* clamp to 10 chars */
31808 js_ctx->h_gap = duk_get_hstring(ctx, -1);
31809 DUK_ASSERT(js_ctx->h_gap != NULL);
31810 } else {
31811 /* nop */
31812 }
31813
31814 if (js_ctx->h_gap != NULL) {
31815 /* if gap is empty, behave as if not given at all */
31816 if (DUK_HSTRING_GET_CHARLEN(js_ctx->h_gap) == 0) {
31817 js_ctx->h_gap = NULL;
31818 }
31819 }
31820
31821 /* [ ... buf loop (proplist) (gap) ] */
31822
31823 /*
31824 * Fast path: assume no mutation, iterate object property tables
31825 * directly; bail out if that assumption doesn't hold.
31826 */
31827
31828#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
31829 if (js_ctx->h_replacer == NULL && /* replacer is a mutation risk */
31830 js_ctx->idx_proplist == -1) { /* proplist is very rare */
31831 duk_int_t pcall_rc;
31832#ifdef DUK_USE_MARK_AND_SWEEP
31833 duk_small_uint_t prev_mark_and_sweep_base_flags;
31834#endif
31835
31836 DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
31837
31838 /* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
31839 * array so we don't need two counter checks in the fast path. The
31840 * slow path has a much larger recursion limit which we'll use if
31841 * necessary.
31842 */
31845 DUK_ASSERT(js_ctx->recursion_depth == 0);
31846
31847 /* Execute the fast path in a protected call. If any error is thrown,
31848 * fall back to the slow path. This includes e.g. recursion limit
31849 * because the fast path has a smaller recursion limit (and simpler,
31850 * limited loop detection).
31851 */
31852
31853 duk_push_pointer(ctx, (void *) js_ctx);
31854 duk_dup(ctx, idx_value);
31855
31856#if defined(DUK_USE_MARK_AND_SWEEP)
31857 /* Must prevent finalizers which may have arbitrary side effects. */
31858 prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
31860 DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */
31861 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact any objects */
31862#endif
31863
31864 pcall_rc = duk_safe_call(ctx, duk__json_stringify_fast, 2 /*nargs*/, 0 /*nret*/);
31865
31866#if defined(DUK_USE_MARK_AND_SWEEP)
31867 thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
31868#endif
31869 if (pcall_rc == DUK_EXEC_SUCCESS) {
31870 DUK_DD(DUK_DDPRINT("fast path successful"));
31871 DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
31872 goto replace_finished;
31873 }
31874
31875 /* We come here for actual aborts (like encountering .toJSON())
31876 * but also for recursion/loop errors. Bufwriter size can be
31877 * kept because we'll probably need at least as much as we've
31878 * allocated so far.
31879 */
31880 DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
31881 DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
31882 js_ctx->recursion_depth = 0;
31883 }
31884#endif
31885
31886 /*
31887 * Create wrapper object and serialize
31888 */
31889
31890 idx_holder = duk_push_object(ctx);
31891 duk_dup(ctx, idx_value);
31893
31894 DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
31895 "proplist=%!T, gap=%!O, holder=%!T",
31896 (unsigned long) js_ctx->flags,
31897 (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
31898 (duk_heaphdr *) js_ctx->h_replacer,
31899 (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
31900 (duk_heaphdr *) js_ctx->h_gap,
31901 (duk_tval *) duk_get_tval(ctx, -1)));
31902
31903 /* serialize the wrapper with empty string key */
31904
31906
31907 /* [ ... buf loop (proplist) (gap) holder "" ] */
31908
31910 DUK_ASSERT(js_ctx->recursion_depth == 0);
31911
31912 if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */
31913 /* Result is undefined. */
31914 duk_push_undefined(ctx);
31915 } else {
31916 /* Convert buffer to result string. */
31917 DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
31918 }
31919
31920 DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
31921 "proplist=%!T, gap=%!O, holder=%!T",
31922 (unsigned long) js_ctx->flags,
31923 (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
31924 (duk_heaphdr *) js_ctx->h_replacer,
31925 (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
31926 (duk_heaphdr *) js_ctx->h_gap,
31927 (duk_tval *) duk_get_tval(ctx, idx_holder)));
31928
31929 /* The stack has a variable shape here, so force it to the
31930 * desired one explicitly.
31931 */
31932
31933#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
31934 replace_finished:
31935#endif
31936 duk_replace(ctx, entry_top);
31937 duk_set_top(ctx, entry_top + 1);
31939 DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
31940 "flags=0x%08lx, result=%!T, stack_top=%ld",
31941 (duk_tval *) duk_get_tval(ctx, idx_value),
31942 (duk_tval *) duk_get_tval(ctx, idx_replacer),
31943 (duk_tval *) duk_get_tval(ctx, idx_space),
31944 (unsigned long) flags,
31945 (duk_tval *) duk_get_tval(ctx, -1),
31946 (long) duk_get_top(ctx)));
31947
31948 DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
31949}
31950
31951/*
31952 * Entry points
31953 */
31954
31957 0 /*idx_value*/,
31958 1 /*idx_replacer*/,
31959 0 /*flags*/);
31960 return 1;
31961}
31962
31965 0 /*idx_value*/,
31966 1 /*idx_replacer*/,
31967 2 /*idx_space*/,
31968 0 /*flags*/);
31969 return 1;
31970}
31971
31972#undef DUK__JSON_DECSTR_BUFSIZE
31973#undef DUK__JSON_DECSTR_CHUNKSIZE
31974#undef DUK__JSON_ENCSTR_CHUNKSIZE
31975#undef DUK__JSON_STRINGIFY_BUFSIZE
31976#undef DUK__JSON_MAX_ESC_LEN
31978 * Logging support
31979 */
31980
31981/* include removed: duk_internal.h */
31982
31983/* 3-letter log level strings */
31984DUK_LOCAL const duk_uint8_t duk__log_level_strings[] = {
31985 (duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_C,
31986 (duk_uint8_t) DUK_ASC_UC_D, (duk_uint8_t) DUK_ASC_UC_B, (duk_uint8_t) DUK_ASC_UC_G,
31987 (duk_uint8_t) DUK_ASC_UC_I, (duk_uint8_t) DUK_ASC_UC_N, (duk_uint8_t) DUK_ASC_UC_F,
31988 (duk_uint8_t) DUK_ASC_UC_W, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_N,
31989 (duk_uint8_t) DUK_ASC_UC_E, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_R,
31990 (duk_uint8_t) DUK_ASC_UC_F, (duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_L
31991};
31992
31993/* Constructor */
31995 duk_hthread *thr = (duk_hthread *) ctx;
31996 duk_idx_t nargs;
31997
31998 /* Calling as a non-constructor is not meaningful. */
31999 if (!duk_is_constructor_call(ctx)) {
32000 return DUK_RET_TYPE_ERROR;
32001 }
32002
32003 nargs = duk_get_top(ctx);
32004 duk_set_top(ctx, 1);
32005
32006 duk_push_this(ctx);
32007
32008 /* [ name this ] */
32009
32010 if (nargs == 0) {
32011 /* Automatic defaulting of logger name from caller. This would
32012 * work poorly with tail calls, but constructor calls are currently
32013 * never tail calls, so tail calls are not an issue now.
32014 */
32015
32016 if (thr->callstack_top >= 2) {
32017 duk_activation *act_caller = thr->callstack + thr->callstack_top - 2;
32018 duk_hobject *func_caller;
32019
32020 func_caller = DUK_ACT_GET_FUNC(act_caller);
32021 if (func_caller) {
32022 /* Stripping the filename might be a good idea
32023 * ("/foo/bar/quux.js" -> logger name "quux"),
32024 * but now used verbatim.
32025 */
32026 duk_push_hobject(ctx, func_caller);
32028 duk_replace(ctx, 0);
32029 }
32030 }
32031 }
32032 /* the stack is unbalanced here on purpose; we only rely on the
32033 * initial two values: [ name this ].
32035
32036 if (duk_is_string(ctx, 0)) {
32037 duk_dup(ctx, 0);
32039 } else {
32040 /* don't set 'n' at all, inherited value is used as name */
32041 }
32042
32043 duk_compact(ctx, 1);
32044
32045 return 0; /* keep default instance */
32046}
32047
32048/* Default function to format objects. Tries to use toLogString() but falls
32049 * back to toString(). Any errors are propagated out without catching.
32050 */
32053 /* [ arg toLogString ] */
32054
32055 duk_dup(ctx, 0);
32056 duk_call_method(ctx, 0);
32057
32058 /* [ arg result ] */
32059 return 1;
32060 }
32061
32062 /* [ arg undefined ] */
32063 duk_pop(ctx);
32064 duk_to_string(ctx, 0);
32065 return 1;
32066}
32067
32068/* Default function to write a formatted log line. Writes to stderr,
32069 * appending a newline to the log line.
32070 *
32071 * The argument is a buffer whose visible size contains the log message.
32072 * This function should avoid coercing the buffer to a string to avoid
32073 * string table traffic.
32074 */
32076 const char *data;
32077 duk_size_t data_len;
32078
32079 DUK_UNREF(ctx);
32080 DUK_UNREF(data);
32081 DUK_UNREF(data_len);
32083#ifdef DUK_USE_FILE_IO
32084 data = (const char *) duk_require_buffer(ctx, 0, &data_len);
32085 DUK_FWRITE((const void *) data, 1, data_len, DUK_STDERR);
32086 DUK_FPUTC((int) '\n', DUK_STDERR);
32088#else
32089 /* nop */
32090#endif
32091 return 0;
32092}
32093
32094/* Log frontend shared helper, magic value indicates log level. Provides
32095 * frontend functions: trace(), debug(), info(), warn(), error(), fatal().
32096 * This needs to have small footprint, reasonable performance, minimal
32097 * memory churn, etc.
32098 */
32100 duk_hthread *thr = (duk_hthread *) ctx;
32101 duk_double_t now;
32102 duk_small_int_t entry_lev = duk_get_current_magic(ctx);
32103 duk_small_int_t logger_lev;
32104 duk_int_t nargs;
32105 duk_int_t i;
32106 duk_size_t tot_len;
32107 const duk_uint8_t *arg_str;
32108 duk_size_t arg_len;
32109 duk_uint8_t *buf, *p;
32110 const duk_uint8_t *q;
32111 duk_uint8_t date_buf[DUK_BI_DATE_ISO8601_BUFSIZE];
32112 duk_size_t date_len;
32113 duk_small_int_t rc;
32114
32115 DUK_ASSERT(entry_lev >= 0 && entry_lev <= 5);
32116 DUK_UNREF(thr);
32117
32118 /* XXX: sanitize to printable (and maybe ASCII) */
32119 /* XXX: better multiline */
32120
32121 /*
32122 * Logger arguments are:
32123 *
32124 * magic: log level (0-5)
32125 * this: logger
32126 * stack: plain log args
32127 *
32128 * We want to minimize memory churn so a two-pass approach
32129 * is used: first pass formats arguments and computes final
32130 * string length, second pass copies strings either into a
32131 * pre-allocated and reused buffer (short messages) or into a
32132 * newly allocated fixed buffer. If the backend function plays
32133 * nice, it won't coerce the buffer to a string (and thus
32134 * intern it).
32135 */
32136
32137 nargs = duk_get_top(ctx);
32138
32139 /* [ arg1 ... argN this ] */
32140
32141 /*
32142 * Log level check
32143 */
32144
32145 duk_push_this(ctx);
32146
32148 logger_lev = (duk_small_int_t) duk_get_int(ctx, -1);
32149 if (entry_lev < logger_lev) {
32150 return 0;
32151 }
32152 /* log level could be popped but that's not necessary */
32153
32154 now = DUK_USE_DATE_GET_NOW(ctx);
32155 duk_bi_date_format_timeval(now, date_buf);
32156 date_len = DUK_STRLEN((const char *) date_buf);
32157
32159 duk_to_string(ctx, -1);
32160 DUK_ASSERT(duk_is_string(ctx, -1));
32161
32162 /* [ arg1 ... argN this loggerLevel loggerName ] */
32163
32164 /*
32165 * Pass 1
32166 */
32167
32168 /* Line format: <time> <entryLev> <loggerName>: <msg> */
32169
32170 tot_len = 0;
32171 tot_len += 3 + /* separators: space, space, colon */
32172 3 + /* level string */
32173 date_len + /* time */
32174 duk_get_length(ctx, -1); /* loggerName */
32175
32176 for (i = 0; i < nargs; i++) {
32177 /* When formatting an argument to a string, errors may happen from multiple
32178 * causes. In general we want to catch obvious errors like a toLogString()
32179 * throwing an error, but we don't currently try to catch every possible
32180 * error. In particular, internal errors (like out of memory or stack) are
32181 * not caught. Also, we expect Error toString() to not throw an error.
32182 */
32183 if (duk_is_object(ctx, i)) {
32184 /* duk_pcall_prop() may itself throw an error, but we're content
32185 * in catching the obvious errors (like toLogString() throwing an
32186 * error).
32187 */
32189 duk_dup(ctx, i);
32190 /* [ arg1 ... argN this loggerLevel loggerName 'fmt' arg ] */
32191 /* call: this.fmt(arg) */
32192 rc = duk_pcall_prop(ctx, -5 /*obj_index*/, 1 /*nargs*/);
32193 if (rc) {
32194 /* Keep the error as the result (coercing it might fail below,
32195 * but we don't catch that now).
32196 */
32197 ;
32198 }
32199 duk_replace(ctx, i);
32200 }
32201 (void) duk_to_lstring(ctx, i, &arg_len);
32202 tot_len++; /* sep (even before first one) */
32203 tot_len += arg_len;
32204 }
32205
32206 /*
32207 * Pass 2
32208 */
32209
32210 /* XXX: There used to be a shared log buffer here, but it was removed
32211 * when dynamic buffer spare was removed. The problem with using
32212 * bufwriter is that, without the spare, the buffer gets passed on
32213 * as an argument to the raw() call so it'd need to be resized
32214 * (reallocated) anyway. If raw() call convention is changed, this
32215 * could be made more efficient.
32216 */
32217
32218 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, tot_len);
32219 DUK_ASSERT(buf != NULL);
32220 p = buf;
32221
32222 DUK_MEMCPY((void *) p, (const void *) date_buf, (size_t) date_len);
32223 p += date_len;
32224 *p++ = (duk_uint8_t) DUK_ASC_SPACE;
32225
32226 q = duk__log_level_strings + (entry_lev * 3);
32227 DUK_MEMCPY((void *) p, (const void *) q, (size_t) 3);
32228 p += 3;
32229
32230 *p++ = (duk_uint8_t) DUK_ASC_SPACE;
32231
32232 arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, -2, &arg_len);
32233 DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
32234 p += arg_len;
32235
32236 *p++ = (duk_uint8_t) DUK_ASC_COLON;
32237
32238 for (i = 0; i < nargs; i++) {
32239 *p++ = (duk_uint8_t) DUK_ASC_SPACE;
32240
32241 arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &arg_len);
32242 DUK_ASSERT(arg_str != NULL);
32243 DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
32244 p += arg_len;
32245 }
32246 DUK_ASSERT(buf + tot_len == p);
32247
32248 /* [ arg1 ... argN this loggerLevel loggerName buffer ] */
32249
32250#if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_LOGGING)
32251 /* Do debugger forwarding before raw() because the raw() function
32252 * doesn't get the log level right now.
32253 */
32254 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
32255 const char *log_buf;
32256 duk_size_t sz_buf;
32257 log_buf = (const char *) duk_get_buffer(ctx, -1, &sz_buf);
32258 DUK_ASSERT(log_buf != NULL);
32259 duk_debug_write_notify(thr, DUK_DBG_CMD_LOG);
32260 duk_debug_write_int(thr, (duk_int32_t) entry_lev);
32261 duk_debug_write_string(thr, (const char *) log_buf, sz_buf);
32262 duk_debug_write_eom(thr);
32263 }
32264#endif
32265
32266 /* Call this.raw(msg); look up through the instance allows user to override
32267 * the raw() function in the instance or in the prototype for maximum
32268 * flexibility.
32269 */
32271 duk_dup(ctx, -2);
32272 /* [ arg1 ... argN this loggerLevel loggerName buffer 'raw' buffer ] */
32273 duk_call_prop(ctx, -6, 1); /* this.raw(buffer) */
32274
32275 return 0;
32276}
32278 * Math built-ins
32279 */
32281/* include removed: duk_internal.h */
32282
32283#if defined(DUK_USE_MATH_BUILTIN)
32284
32285/*
32286 * Use static helpers which can work with math.h functions matching
32287 * the following signatures. This is not portable if any of these math
32288 * functions is actually a macro.
32289 *
32290 * Typing here is intentionally 'double' wherever values interact with
32291 * the standard library APIs.
32292 */
32293
32294typedef double (*duk__one_arg_func)(double);
32295typedef double (*duk__two_arg_func)(double, double);
32296
32298 duk_idx_t n = duk_get_top(ctx);
32299 duk_idx_t i;
32300 duk_double_t res = initial;
32301 duk_double_t t;
32302
32303 /*
32304 * Note: fmax() does not match the E5 semantics. E5 requires
32305 * that if -any- input to Math.max() is a NaN, the result is a
32306 * NaN. fmax() will return a NaN only if -both- inputs are NaN.
32307 * Same applies to fmin().
32308 *
32309 * Note: every input value must be coerced with ToNumber(), even
32310 * if we know the result will be a NaN anyway: ToNumber() may have
32311 * side effects for which even order of evaluation matters.
32312 */
32313
32314 for (i = 0; i < n; i++) {
32315 t = duk_to_number(ctx, i);
32316 if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
32317 /* Note: not normalized, but duk_push_number() will normalize */
32319 } else {
32320 res = (duk_double_t) min_max(res, (double) t);
32321 }
32322 }
32323
32324 duk_push_number(ctx, res);
32325 return 1;
32326}
32327
32328DUK_LOCAL double duk__fmin_fixed(double x, double y) {
32329 /* fmin() with args -0 and +0 is not guaranteed to return
32330 * -0 as Ecmascript requires.
32331 */
32332 if (x == 0 && y == 0) {
32333 /* XXX: what's the safest way of creating a negative zero? */
32334 if (DUK_SIGNBIT(x) != 0 || DUK_SIGNBIT(y) != 0) {
32335 return -0.0;
32336 } else {
32337 return +0.0;
32338 }
32339 }
32340#ifdef DUK_USE_MATH_FMIN
32341 return DUK_FMIN(x, y);
32342#else
32343 return (x < y ? x : y);
32344#endif
32345}
32346
32347DUK_LOCAL double duk__fmax_fixed(double x, double y) {
32348 /* fmax() with args -0 and +0 is not guaranteed to return
32349 * +0 as Ecmascript requires.
32350 */
32351 if (x == 0 && y == 0) {
32352 if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
32353 return +0.0;
32354 } else {
32355 return -0.0;
32356 }
32357 }
32358#ifdef DUK_USE_MATH_FMAX
32359 return DUK_FMAX(x, y);
32360#else
32361 return (x > y ? x : y);
32362#endif
32363}
32364
32365DUK_LOCAL double duk__round_fixed(double x) {
32366 /* Numbers half-way between integers must be rounded towards +Infinity,
32367 * e.g. -3.5 must be rounded to -3 (not -4). When rounded to zero, zero
32368 * sign must be set appropriately. E5.1 Section 15.8.2.15.
32369 *
32370 * Note that ANSI C round() is "round to nearest integer, away from zero",
32371 * which is incorrect for negative values. Here we make do with floor().
32372 */
32373
32375 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
32376 return x;
32377 }
32378
32379 /*
32380 * x is finite and non-zero
32381 *
32382 * -1.6 -> floor(-1.1) -> -2
32383 * -1.5 -> floor(-1.0) -> -1 (towards +Inf)
32384 * -1.4 -> floor(-0.9) -> -1
32385 * -0.5 -> -0.0 (special case)
32386 * -0.1 -> -0.0 (special case)
32387 * +0.1 -> +0.0 (special case)
32388 * +0.5 -> floor(+1.0) -> 1 (towards +Inf)
32389 * +1.4 -> floor(+1.9) -> 1
32390 * +1.5 -> floor(+2.0) -> 2 (towards +Inf)
32391 * +1.6 -> floor(+2.1) -> 2
32392 */
32393
32394 if (x >= -0.5 && x < 0.5) {
32395 /* +0.5 is handled by floor, this is on purpose */
32396 if (x < 0.0) {
32397 return -0.0;
32398 } else {
32399 return +0.0;
32400 }
32401 }
32402
32403 return DUK_FLOOR(x + 0.5);
32404}
32405
32406DUK_LOCAL double duk__pow_fixed(double x, double y) {
32407 /* The ANSI C pow() semantics differ from Ecmascript.
32408 *
32409 * E.g. when x==1 and y is +/- infinite, the Ecmascript required
32410 * result is NaN, while at least Linux pow() returns 1.
32411 */
32412
32413 duk_small_int_t cx, cy, sx;
32414
32415 DUK_UNREF(cx);
32416 DUK_UNREF(sx);
32418
32419 if (cy == DUK_FP_NAN) {
32420 goto ret_nan;
32421 }
32422 if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
32423 goto ret_nan;
32424 }
32425#if defined(DUK_USE_POW_NETBSD_WORKAROUND)
32426 /* See test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least) does not
32427 * correctly handle some cases where x=+/-0. Specific fixes to these
32428 * here.
32429 */
32431 if (cx == DUK_FP_ZERO && y < 0.0) {
32432 sx = (duk_small_int_t) DUK_SIGNBIT(x);
32433 if (sx == 0) {
32434 /* Math.pow(+0,y) should be Infinity when y<0. NetBSD pow()
32435 * returns -Infinity instead when y is <0 and finite. The
32436 * if-clause also catches y == -Infinity (which works even
32437 * without the fix).
32438 */
32439 return DUK_DOUBLE_INFINITY;
32440 } else {
32441 /* Math.pow(-0,y) where y<0 should be:
32442 * - -Infinity if y<0 and an odd integer
32443 * - Infinity otherwise
32444 * NetBSD pow() returns -Infinity for all finite y<0. The
32445 * if-clause also catches y == -Infinity (which works even
32446 * without the fix).
32447 */
32448
32449 /* fmod() return value has same sign as input (negative) so
32450 * the result here will be in the range ]-2,0], 1 indicates
32451 * odd. If x is -Infinity, NaN is returned and the odd check
32452 * always concludes "not odd" which results in desired outcome.
32453 */
32454 double tmp = DUK_FMOD(y, 2);
32455 if (tmp == -1.0) {
32456 return -DUK_DOUBLE_INFINITY;
32457 } else {
32458 /* Not odd, or y == -Infinity */
32459 return DUK_DOUBLE_INFINITY;
32460 }
32462 }
32463#endif
32464 return DUK_POW(x, y);
32465
32466 ret_nan:
32468}
32469
32470/* Wrappers for calling standard math library methods. These may be required
32471 * on platforms where one or more of the math built-ins are defined as macros
32472 * or inline functions and are thus not suitable to be used as function pointers.
32474#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32475DUK_LOCAL double duk__fabs(double x) {
32476 return DUK_FABS(x);
32477}
32478DUK_LOCAL double duk__acos(double x) {
32479 return DUK_ACOS(x);
32480}
32481DUK_LOCAL double duk__asin(double x) {
32482 return DUK_ASIN(x);
32483}
32484DUK_LOCAL double duk__atan(double x) {
32485 return DUK_ATAN(x);
32486}
32487DUK_LOCAL double duk__ceil(double x) {
32488 return DUK_CEIL(x);
32489}
32490DUK_LOCAL double duk__cos(double x) {
32491 return DUK_COS(x);
32492}
32493DUK_LOCAL double duk__exp(double x) {
32494 return DUK_EXP(x);
32495}
32496DUK_LOCAL double duk__floor(double x) {
32497 return DUK_FLOOR(x);
32498}
32499DUK_LOCAL double duk__log(double x) {
32500 return DUK_LOG(x);
32501}
32502DUK_LOCAL double duk__sin(double x) {
32503 return DUK_SIN(x);
32504}
32505DUK_LOCAL double duk__sqrt(double x) {
32506 return DUK_SQRT(x);
32507}
32508DUK_LOCAL double duk__tan(double x) {
32509 return DUK_TAN(x);
32510}
32511DUK_LOCAL double duk__atan2(double x, double y) {
32512 return DUK_ATAN2(x, y);
32513}
32514#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
32515
32516/* order must match constants in genbuiltins.py */
32518#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32519 duk__fabs,
32520 duk__acos,
32521 duk__asin,
32522 duk__atan,
32523 duk__ceil,
32524 duk__cos,
32525 duk__exp,
32526 duk__floor,
32527 duk__log,
32529 duk__sin,
32530 duk__sqrt,
32531 duk__tan
32532#else
32534 DUK_ACOS,
32535 DUK_ASIN,
32536 DUK_ATAN,
32537 DUK_CEIL,
32538 DUK_COS,
32539 DUK_EXP,
32540 DUK_FLOOR,
32541 DUK_LOG,
32544 DUK_SQRT,
32545 DUK_TAN
32546#endif
32547};
32548
32549/* order must match constants in genbuiltins.py */
32551#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32552 duk__atan2,
32554#else
32555 DUK_ATAN2,
32557#endif
32558};
32559
32563
32564 DUK_ASSERT(fun_idx >= 0);
32566 fun = duk__one_arg_funcs[fun_idx];
32567 duk_push_number(ctx, (duk_double_t) fun((double) duk_to_number(ctx, 0)));
32568 return 1;
32574
32575 DUK_ASSERT(fun_idx >= 0);
32576 DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
32577 fun = duk__two_arg_funcs[fun_idx];
32578 duk_push_number(ctx, (duk_double_t) fun((double) duk_to_number(ctx, 0), (double) duk_to_number(ctx, 1)));
32579 return 1;
32580}
32581
32584}
32585
32588}
32589
32592 return 1;
32593}
32594
32595#else /* DUK_USE_MATH_BUILTIN */
32596
32597/* A stubbed built-in is useful for e.g. compilation torture testing with BCC. */
32598
32600 DUK_UNREF(ctx);
32602}
32603
32605 DUK_UNREF(ctx);
32607}
32608
32610 DUK_UNREF(ctx);
32612}
32613
32615 DUK_UNREF(ctx);
32617}
32618
32620 DUK_UNREF(ctx);
32622}
32623
32624#endif /* DUK_USE_MATH_BUILTIN */
32625/*
32626 * Number built-ins
32627 */
32628
32629/* include removed: duk_internal.h */
32630
32632 duk_hobject *h;
32633
32634 /* Number built-in accepts a plain number or a Number object (whose
32635 * internal value is operated on). Other types cause TypeError.
32636 */
32637
32638 duk_push_this(ctx);
32639 if (duk_is_number(ctx, -1)) {
32640 DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
32641 goto done;
32643 h = duk_get_hobject(ctx, -1);
32644 if (!h ||
32646 DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
32647 DUK_ERROR_TYPE((duk_hthread *) ctx, "number expected");
32648 }
32650 DUK_ASSERT(duk_is_number(ctx, -1));
32651 DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
32652 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
32653 duk_remove(ctx, -2);
32654
32655 done:
32656 return duk_get_number(ctx, -1);
32657}
32658
32660 duk_hthread *thr = (duk_hthread *) ctx;
32661 duk_idx_t nargs;
32662 duk_hobject *h_this;
32663
32664 DUK_UNREF(thr);
32665
32666 /*
32667 * The Number constructor uses ToNumber(arg) for number coercion
32668 * (coercing an undefined argument to NaN). However, if the
32669 * argument is not given at all, +0 must be used instead. To do
32670 * this, a vararg function is used.
32671 */
32672
32673 nargs = duk_get_top(ctx);
32674 if (nargs == 0) {
32675 duk_push_int(ctx, 0);
32676 }
32677 duk_to_number(ctx, 0);
32678 duk_set_top(ctx, 1);
32679 DUK_ASSERT_TOP(ctx, 1);
32680
32681 if (!duk_is_constructor_call(ctx)) {
32682 return 1;
32683 }
32684
32685 /*
32686 * E5 Section 15.7.2.1 requires that the constructed object
32687 * must have the original Number.prototype as its internal
32688 * prototype. However, since Number.prototype is non-writable
32689 * and non-configurable, this doesn't have to be enforced here:
32690 * The default object (bound to 'this') is OK, though we have
32691 * to change its class.
32692 *
32693 * Internal value set to ToNumber(arg) or +0; if no arg given,
32694 * ToNumber(undefined) = NaN, so special treatment is needed
32695 * (above). String internal value is immutable.
32697
32698 /* XXX: helper */
32699 duk_push_this(ctx);
32700 h_this = duk_get_hobject(ctx, -1);
32701 DUK_ASSERT(h_this != NULL);
32703
32707
32708 duk_dup(ctx, 0); /* -> [ val obj val ] */
32710 return 0; /* no return value -> don't replace created value */
32711}
32712
32714 (void) duk__push_this_number_plain(ctx);
32715 return 1;
32716}
32717
32719 duk_small_int_t radix;
32720 duk_small_uint_t n2s_flags;
32721
32723 if (duk_is_undefined(ctx, 0)) {
32724 radix = 10;
32725 } else {
32726 radix = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 2, 36);
32727 }
32728 DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
32729
32730 n2s_flags = 0;
32731
32733 radix /*radix*/,
32734 0 /*digits*/,
32735 n2s_flags /*flags*/);
32736 return 1;
32737}
32738
32740 /* XXX: just use toString() for now; permitted although not recommended.
32741 * nargs==1, so radix is passed to toString().
32742 */
32744}
32745
32746/*
32747 * toFixed(), toExponential(), toPrecision()
32748 */
32749
32750/* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
32751
32753 duk_small_int_t frac_digits;
32754 duk_double_t d;
32756 duk_small_uint_t n2s_flags;
32757
32758 frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
32760
32762 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
32763 goto use_to_string;
32764 }
32765
32766 if (d >= 1.0e21 || d <= -1.0e21) {
32767 goto use_to_string;
32769
32770 n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
32772
32774 10 /*radix*/,
32775 frac_digits /*digits*/,
32776 n2s_flags /*flags*/);
32777 return 1;
32778
32779 use_to_string:
32780 DUK_ASSERT_TOP(ctx, 2);
32781 duk_to_string(ctx, -1);
32782 return 1;
32783}
32784
32786 duk_bool_t frac_undefined;
32787 duk_small_int_t frac_digits;
32788 duk_double_t d;
32790 duk_small_uint_t n2s_flags;
32791
32793
32794 frac_undefined = duk_is_undefined(ctx, 0);
32795 duk_to_int(ctx, 0); /* for side effects */
32796
32798 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
32799 goto use_to_string;
32800 }
32801
32802 frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
32803
32804 n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
32805 (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
32806
32808 10 /*radix*/,
32809 frac_digits + 1 /*leading digit + fractions*/,
32810 n2s_flags /*flags*/);
32811 return 1;
32812
32813 use_to_string:
32814 DUK_ASSERT_TOP(ctx, 2);
32815 duk_to_string(ctx, -1);
32816 return 1;
32817}
32818
32820 /* The specification has quite awkward order of coercion and
32821 * checks for toPrecision(). The operations below are a bit
32822 * reordered, within constraints of observable side effects.
32823 */
32824
32825 duk_double_t d;
32826 duk_small_int_t prec;
32828 duk_small_uint_t n2s_flags;
32829
32830 DUK_ASSERT_TOP(ctx, 1);
32831
32833 if (duk_is_undefined(ctx, 0)) {
32834 goto use_to_string;
32835 }
32836 DUK_ASSERT_TOP(ctx, 2);
32837
32838 duk_to_int(ctx, 0); /* for side effects */
32839
32841 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
32842 goto use_to_string;
32843 }
32844
32845 prec = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 1, 21);
32846
32847 n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
32849
32851 10 /*radix*/,
32852 prec /*digits*/,
32853 n2s_flags /*flags*/);
32854 return 1;
32855
32856 use_to_string:
32857 /* Used when precision is undefined; also used for NaN (-> "NaN"),
32858 * and +/- infinity (-> "Infinity", "-Infinity").
32859 */
32860
32861 DUK_ASSERT_TOP(ctx, 2);
32862 duk_to_string(ctx, -1);
32863 return 1;
32864}
32865/*
32866 * Object built-ins
32867 */
32868
32869/* include removed: duk_internal.h */
32870
32872 if (!duk_is_constructor_call(ctx) &&
32873 !duk_is_null_or_undefined(ctx, 0)) {
32874 duk_to_object(ctx, 0);
32875 return 1;
32876 }
32877
32878 if (duk_is_object(ctx, 0)) {
32879 return 1;
32880 }
32881
32882 /* Pointer and buffer primitive values are treated like other
32883 * primitives values which have a fully fledged object counterpart:
32884 * promote to an object value. Lightfuncs are coerced with
32885 * ToObject() even they could also be returned as is.
32886 */
32893 duk_to_object(ctx, 0);
32894 return 1;
32895 }
32896
32901 return 1;
32902}
32903
32904/* Shared helper to implement Object.getPrototypeOf and the ES6
32905 * Object.prototype.__proto__ getter.
32906 *
32907 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
32908 */
32910 duk_hthread *thr = (duk_hthread *) ctx;
32911 duk_hobject *h;
32913
32914 DUK_UNREF(thr);
32915
32916 /* magic: 0=getter call, 1=Object.getPrototypeOf */
32917 if (duk_get_current_magic(ctx) == 0) {
32919 duk_insert(ctx, 0);
32920 }
32921
32922 h = duk_require_hobject_or_lfunc(ctx, 0);
32923 /* h is NULL for lightfunc */
32924
32925 /* XXX: should the API call handle this directly, i.e. attempt
32926 * to duk_push_hobject(ctx, null) would push a null instead?
32927 * (On the other hand 'undefined' would be just as logical, but
32928 * not wanted here.)
32929 */
32930
32931 if (h == NULL) {
32933 } else {
32935 if (proto) {
32936 duk_push_hobject(ctx, proto);
32937 } else {
32938 duk_push_null(ctx);
32939 }
32940 }
32941 return 1;
32942}
32943
32944/* Shared helper to implement ES6 Object.setPrototypeOf and
32945 * Object.prototype.__proto__ setter.
32946 *
32947 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
32948 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
32949 */
32951 duk_hthread *thr = (duk_hthread *) ctx;
32952 duk_hobject *h_obj;
32953 duk_hobject *h_new_proto;
32954 duk_hobject *h_curr;
32955 duk_ret_t ret_success = 1; /* retval for success path */
32956
32957 /* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4);
32958 * magic: 0=setter call, 1=Object.setPrototypeOf
32959 */
32960 if (duk_get_current_magic(ctx) == 0) {
32962 duk_insert(ctx, 0);
32964 return 0;
32965 }
32966
32967 /* __proto__ setter returns 'undefined' on success unlike the
32968 * setPrototypeOf() call which returns the target object.
32969 */
32970 ret_success = 0;
32971 } else {
32974 }
32975
32976 h_new_proto = duk_get_hobject(ctx, 1);
32977 /* h_new_proto may be NULL */
32978 if (duk_is_lightfunc(ctx, 0)) {
32979 if (h_new_proto == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]) {
32980 goto skip;
32981 }
32982 goto fail_nonextensible;
32983 }
32984 h_obj = duk_get_hobject(ctx, 0);
32985 if (!h_obj) {
32986 goto skip;
32987 }
32988 DUK_ASSERT(h_obj != NULL);
32989
32990 /* [[SetPrototypeOf]] standard behavior, E6 9.1.2 */
32991 /* TODO: implement Proxy object support here */
32992
32993 if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
32994 goto skip;
32995 }
32996 if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
32997 goto fail_nonextensible;
32998 }
32999 for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
33000 /* Loop prevention */
33001 if (h_curr == h_obj) {
33002 goto fail_loop;
33003 }
33004 }
33005 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
33006 /* fall thru */
33007
33008 skip:
33009 duk_set_top(ctx, 1);
33010 return ret_success;
33011
33012 fail_nonextensible:
33013 fail_loop:
33014 return DUK_RET_TYPE_ERROR;
33015}
33016
33018 /* XXX: no need for indirect call */
33020}
33021
33023 duk_tval *tv;
33025
33026 DUK_ASSERT_TOP(ctx, 2);
33027
33028 tv = duk_get_tval(ctx, 0);
33029 DUK_ASSERT(tv != NULL);
33030 if (DUK_TVAL_IS_NULL(tv)) {
33031 ;
33032 } else if (DUK_TVAL_IS_OBJECT(tv)) {
33034 DUK_ASSERT(proto != NULL);
33035 } else {
33036 return DUK_RET_TYPE_ERROR;
33037 }
33038
33042 proto);
33043
33044 if (!duk_is_undefined(ctx, 1)) {
33045 /* [ O Properties obj ] */
33047 duk_replace(ctx, 0);
33048
33049 /* [ obj Properties ] */
33050
33051 /* Just call the "original" Object.defineProperties() to
33052 * finish up.
33053 */
33054
33056 }
33057
33058 /* [ O Properties obj ] */
33059
33060 return 1;
33061}
33062
33064 duk_hobject *obj;
33065 duk_hstring *key;
33066 duk_hobject *get;
33067 duk_hobject *set;
33068 duk_idx_t idx_value;
33069 duk_uint_t defprop_flags;
33070
33071 DUK_ASSERT(ctx != NULL);
33072
33073 DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
33074 (void *) ctx,
33075 (duk_tval *) duk_get_tval(ctx, 0),
33076 (duk_tval *) duk_get_tval(ctx, 1),
33077 (duk_tval *) duk_get_tval(ctx, 2)));
33078
33079 /* [ obj key desc ] */
33080
33081 /* Lightfuncs are currently supported by coercing to a temporary
33082 * Function object; changes will be allowed (the coerced value is
33083 * extensible) but will be lost.
33084 */
33086 (void) duk_to_string(ctx, 1);
33087 key = duk_require_hstring(ctx, 1);
33088 (void) duk_require_hobject(ctx, 2);
33089
33090 DUK_ASSERT(obj != NULL);
33091 DUK_ASSERT(key != NULL);
33092 DUK_ASSERT(duk_get_hobject(ctx, 2) != NULL);
33093
33094 /*
33095 * Validate and convert argument property descriptor (an Ecmascript
33096 * object) into a set of defprop_flags and possibly property value,
33097 * getter, and/or setter values on the value stack.
33098 *
33099 * Lightfunc set/get values are coerced to full Functions.
33100 */
33101
33103 2 /*idx_desc*/,
33104 &defprop_flags,
33105 &idx_value,
33106 &get,
33107 &set);
33108
33109 /*
33110 * Use Object.defineProperty() helper for the actual operation.
33111 */
33112
33114 defprop_flags,
33115 obj,
33116 key,
33117 idx_value,
33118 get,
33119 set);
33120
33121 /* Ignore the normalize/validate helper outputs on the value stack,
33122 * they're popped automatically.
33123 */
33124
33125 /*
33126 * Return target object.
33127 */
33128
33129 duk_push_hobject(ctx, obj);
33130 return 1;
33131}
33132
33134 duk_small_uint_t pass;
33135 duk_uint_t defprop_flags;
33136 duk_hobject *obj;
33137 duk_idx_t idx_value;
33138 duk_hobject *get;
33139 duk_hobject *set;
33140
33141 /* Lightfunc handling by ToObject() coercion. */
33142 obj = duk_require_hobject_or_lfunc_coerce(ctx, 0); /* target */
33143 DUK_ASSERT(obj != NULL);
33144
33145 duk_to_object(ctx, 1); /* properties object */
33146
33147 DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
33148 (duk_tval *) duk_get_tval(ctx, 0),
33149 (duk_tval *) duk_get_tval(ctx, 1)));
33150
33151 /*
33152 * Two pass approach to processing the property descriptors.
33153 * On first pass validate and normalize all descriptors before
33154 * any changes are made to the target object. On second pass
33155 * make the actual modifications to the target object.
33156 *
33157 * Right now we'll just use the same normalize/validate helper
33158 * on both passes, ignoring its outputs on the first pass.
33159 */
33160
33161 for (pass = 0; pass < 2; pass++) {
33162 duk_set_top(ctx, 2); /* -> [ hobject props ] */
33163 duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/);
33164
33165 for (;;) {
33166 duk_hstring *key;
33167
33168 /* [ hobject props enum(props) ] */
33169
33170 duk_set_top(ctx, 3);
33171
33172 if (!duk_next(ctx, 2, 1 /*get_value*/)) {
33173 break;
33174 }
33175
33176 DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
33177 (duk_tval *) duk_get_tval(ctx, -2),
33178 (duk_tval *) duk_get_tval(ctx, -1)));
33179
33180 /* [ hobject props enum(props) key desc ] */
33181
33183 4 /*idx_desc*/,
33184 &defprop_flags,
33185 &idx_value,
33186 &get,
33187 &set);
33188
33189 /* [ hobject props enum(props) key desc value? getter? setter? ] */
33190
33191 if (pass == 0) {
33192 continue;
33193 }
33194
33195 key = duk_get_hstring(ctx, 3);
33196 DUK_ASSERT(key != NULL);
33197
33199 defprop_flags,
33200 obj,
33201 key,
33202 idx_value,
33203 get,
33204 set);
33205 }
33206 }
33207
33208 /*
33209 * Return target object
33210 */
33211
33212 duk_dup(ctx, 0);
33213 return 1;
33214}
33215
33217 duk_hthread *thr = (duk_hthread *) ctx;
33218 duk_hobject *h;
33219 duk_bool_t is_freeze;
33220
33222 if (!h) {
33223 /* Lightfunc, always success. */
33224 return 1;
33225 }
33226
33227 is_freeze = (duk_bool_t) duk_get_current_magic(ctx);
33228 duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
33229
33230 /* Sealed and frozen objects cannot gain any more properties,
33231 * so this is a good time to compact them.
33232 */
33234
33235 return 1;
33236}
33237
33239 duk_hthread *thr = (duk_hthread *) ctx;
33240 duk_hobject *h;
33241
33243 if (!h) {
33244 /* Lightfunc, always success. */
33245 return 1;
33246 }
33247 DUK_ASSERT(h != NULL);
33248
33250
33251 /* A non-extensible object cannot gain any more properties,
33252 * so this is a good time to compact.
33253 */
33255
33256 return 1;
33257}
33260 duk_hobject *h;
33261 duk_bool_t is_frozen;
33262 duk_bool_t rc;
33263
33264 h = duk_require_hobject_or_lfunc(ctx, 0);
33265 if (!h) {
33266 duk_push_true(ctx); /* frozen and sealed */
33267 } else {
33268 is_frozen = duk_get_current_magic(ctx);
33269 rc = duk_hobject_object_is_sealed_frozen_helper((duk_hthread *) ctx, h, is_frozen /*is_frozen*/);
33270 duk_push_boolean(ctx, rc);
33271 }
33272 return 1;
33274
33276 duk_hobject *h;
33277
33278 h = duk_require_hobject_or_lfunc(ctx, 0);
33279 if (!h) {
33280 duk_push_false(ctx);
33281 } else {
33283 }
33284 return 1;
33285}
33286
33287/* Shared helper for Object.getOwnPropertyNames() and Object.keys().
33288 * Magic: 0=getOwnPropertyNames, 1=Object.keys.
33289 */
33291 duk_hthread *thr = (duk_hthread *) ctx;
33292 duk_hobject *obj;
33293#if defined(DUK_USE_ES6_PROXY)
33294 duk_hobject *h_proxy_target;
33295 duk_hobject *h_proxy_handler;
33296 duk_hobject *h_trap_result;
33297 duk_uarridx_t i, len, idx;
33298#endif
33299 duk_small_uint_t enum_flags;
33300
33301 DUK_ASSERT_TOP(ctx, 1);
33302 DUK_UNREF(thr);
33303
33305 DUK_ASSERT(obj != NULL);
33306 DUK_UNREF(obj);
33307
33308#if defined(DUK_USE_ES6_PROXY)
33310 obj,
33311 &h_proxy_target,
33312 &h_proxy_handler))) {
33313 goto skip_proxy;
33314 }
33315
33316 duk_push_hobject(ctx, h_proxy_handler);
33318 /* Careful with reachability here: don't pop 'obj' before pushing
33319 * proxy target.
33320 */
33321 DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
33322 duk_pop_2(ctx);
33323 duk_push_hobject(ctx, h_proxy_target);
33324 duk_replace(ctx, 0);
33325 DUK_ASSERT_TOP(ctx, 1);
33326 goto skip_proxy;
33327 }
33328
33329 /* [ obj handler trap ] */
33330 duk_insert(ctx, -2);
33331 duk_push_hobject(ctx, h_proxy_target); /* -> [ obj trap handler target ] */
33332 duk_call_method(ctx, 1 /*nargs*/); /* -> [ obj trap_result ] */
33333 h_trap_result = duk_require_hobject(ctx, -1);
33334 DUK_UNREF(h_trap_result);
33335
33336 len = (duk_uarridx_t) duk_get_length(ctx, -1);
33337 idx = 0;
33338 duk_push_array(ctx);
33339 for (i = 0; i < len; i++) {
33340 /* [ obj trap_result res_arr ] */
33341 if (duk_get_prop_index(ctx, -2, i) && duk_is_string(ctx, -1)) {
33342 /* XXX: for Object.keys() we should check enumerability of key */
33343 /* [ obj trap_result res_arr propname ] */
33344 duk_put_prop_index(ctx, -2, idx);
33345 idx++;
33346 } else {
33347 duk_pop(ctx);
33348 }
33349 }
33350
33351 /* XXX: missing trap result validation for non-configurable target keys
33352 * (must be present), for non-extensible target all target keys must be
33353 * present and no extra keys can be present.
33354 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
33355 */
33356
33357 /* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
33358 * should be filtered so that only enumerable keys remain. Enumerability
33359 * should be checked with [[GetOwnProperty]] on the original object
33360 * (i.e., the proxy in this case). If the proxy has a getOwnPropertyDescriptor
33361 * trap, it should be triggered for every property. If the proxy doesn't have
33362 * the trap, enumerability should be checked against the target object instead.
33363 * We don't do any of this now, so Object.keys() and Object.getOwnPropertyNames()
33364 * return the same result now for proxy traps. We still do clean up the trap
33365 * result, so that Object.keys() and Object.getOwnPropertyNames() will return a
33366 * clean array of strings without gaps.
33367 */
33368 return 1;
33369
33370 skip_proxy:
33371#endif /* DUK_USE_ES6_PROXY */
33373 DUK_ASSERT_TOP(ctx, 1);
33374
33375 if (duk_get_current_magic(ctx)) {
33376 /* Object.keys */
33377 enum_flags = DUK_ENUM_OWN_PROPERTIES_ONLY |
33379 } else {
33380 /* Object.getOwnPropertyNames */
33381 enum_flags = DUK_ENUM_INCLUDE_NONENUMERABLE |
33384 }
33385
33386 return duk_hobject_get_enumerated_keys(ctx, enum_flags);
33387}
33388
33392 return 1;
33393}
33394
33396 DUK_ASSERT_TOP(ctx, 0);
33399 if (!duk_is_callable(ctx, 1)) {
33400 return DUK_RET_TYPE_ERROR;
33401 }
33402 duk_dup(ctx, 0); /* -> [ O toString O ] */
33403 duk_call_method(ctx, 0); /* XXX: call method tail call? */
33404 return 1;
33405}
33406
33409 return 1;
33410}
33411
33413 duk_hthread *thr = (duk_hthread *) ctx;
33414 duk_hobject *h_v;
33415 duk_hobject *h_obj;
33416
33417 DUK_ASSERT_TOP(ctx, 1);
33419 h_v = duk_get_hobject(ctx, 0);
33420 if (!h_v) {
33421 duk_push_false(ctx); /* XXX: tail call: return duk_push_false(ctx) */
33422 return 1;
33423 }
33424
33426 DUK_ASSERT(h_obj != NULL);
33427
33428 /* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
33429 * Prototype loops should cause an error to be thrown.
33430 */
33431 duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
33432 return 1;
33433}
33434
33436 return duk_hobject_object_ownprop_helper(ctx, 0 /*required_desc_flags*/);
33437}
33438
33440 return duk_hobject_object_ownprop_helper(ctx, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
33441}
33442/*
33443 * Pointer built-ins
33444 */
33445
33446/* include removed: duk_internal.h */
33447
33448/*
33449 * Constructor
33450 */
33451
33453 /* XXX: this behavior is quite useless now; it would be nice to be able
33454 * to create pointer values from e.g. numbers or strings. Numbers are
33455 * problematic on 64-bit platforms though. Hex encoded strings?
33456 */
33457 if (duk_get_top(ctx) == 0) {
33458 duk_push_pointer(ctx, NULL);
33459 } else {
33460 duk_to_pointer(ctx, 0);
33461 }
33462 DUK_ASSERT(duk_is_pointer(ctx, 0));
33463 duk_set_top(ctx, 1);
33464
33465 if (duk_is_constructor_call(ctx)) {
33470
33471 /* Pointer object internal value is immutable */
33472 duk_dup(ctx, 0);
33474 }
33475 /* Note: unbalanced stack on purpose */
33476
33477 return 1;
33478}
33479
33480/*
33481 * toString(), valueOf()
33482 */
33483
33485 duk_tval *tv;
33486 duk_small_int_t to_string = duk_get_current_magic(ctx);
33487
33488 duk_push_this(ctx);
33489 tv = duk_require_tval(ctx, -1);
33490 DUK_ASSERT(tv != NULL);
33491
33492 if (DUK_TVAL_IS_POINTER(tv)) {
33493 /* nop */
33494 } else if (DUK_TVAL_IS_OBJECT(tv)) {
33496 DUK_ASSERT(h != NULL);
33497
33498 /* Must be a "pointer object", i.e. class "Pointer" */
33500 goto type_error;
33501 }
33502
33504 } else {
33505 goto type_error;
33507
33508 if (to_string) {
33509 duk_to_string(ctx, -1);
33510 }
33511 return 1;
33512
33513 type_error:
33514 return DUK_RET_TYPE_ERROR;
33515}
33516/*
33517 * Proxy built-in (ES6)
33518 */
33519
33520/* include removed: duk_internal.h */
33521
33522#if defined(DUK_USE_ES6_PROXY)
33524 duk_hobject *h_target;
33525 duk_hobject *h_handler;
33526
33527 if (!duk_is_constructor_call(ctx)) {
33528 return DUK_RET_TYPE_ERROR;
33529 }
33530
33531 /* Reject a proxy object as the target because it would need
33532 * special handler in property lookups. (ES6 has no such restriction)
33533 */
33534 h_target = duk_require_hobject_or_lfunc_coerce(ctx, 0);
33535 DUK_ASSERT(h_target != NULL);
33536 if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_target)) {
33537 return DUK_RET_TYPE_ERROR;
33538 }
33539
33540 /* Reject a proxy object as the handler because it would cause
33541 * potentially unbounded recursion. (ES6 has no such restriction)
33542 */
33543 h_handler = duk_require_hobject_or_lfunc_coerce(ctx, 1);
33544 DUK_ASSERT(h_handler != NULL);
33545 if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_handler)) {
33546 return DUK_RET_TYPE_ERROR;
33547 }
33548
33549 /* XXX: the returned value is exotic in ES6, but we use a
33550 * simple object here with no prototype. Without a prototype,
33551 * [[DefaultValue]] coercion fails which is abit confusing.
33552 * No callable check/handling in the current Proxy subset.
33553 */
33558 NULL);
33559 DUK_ASSERT_TOP(ctx, 3);
33560
33561 /* Make _Target and _Handler non-configurable and non-writable.
33562 * They can still be forcibly changed by C code (both user and
33563 * Duktape internal), but not by Ecmascript code.
33564 */
33565
33566 /* Proxy target */
33567 duk_dup(ctx, 0);
33569
33570 /* Proxy handler */
33571 duk_dup(ctx, 1);
33574 return 1; /* replacement handler */
33575}
33576#else /* DUK_USE_ES6_PROXY */
33578 DUK_UNREF(ctx);
33580}
33581#endif /* DUK_USE_ES6_PROXY */
33582/*
33583 * RegExp built-ins
33585
33586/* include removed: duk_internal.h */
33587
33588#ifdef DUK_USE_REGEXP_SUPPORT
33589
33591 duk_hobject *h;
33592
33593 duk_push_this(ctx);
33595 DUK_ASSERT(h != NULL);
33596 DUK_UNREF(h);
33597 duk_insert(ctx, 0); /* prepend regexp to valstack 0 index */
33598}
33599
33600/* XXX: much to improve (code size) */
33602 duk_hthread *thr = (duk_hthread *) ctx;
33603 duk_hobject *h_pattern;
33604
33605 DUK_ASSERT_TOP(ctx, 2);
33606 h_pattern = duk_get_hobject(ctx, 0);
33607
33608 if (!duk_is_constructor_call(ctx) &&
33609 h_pattern != NULL &&
33611 duk_is_undefined(ctx, 1)) {
33612 /* Called as a function, pattern has [[Class]] "RegExp" and
33613 * flags is undefined -> return object as is.
33614 */
33615 duk_dup(ctx, 0);
33616 return 1;
33617 }
33618
33619 /* Else functionality is identical for function call and constructor
33620 * call.
33621 */
33622
33623 if (h_pattern != NULL &&
33625 if (duk_is_undefined(ctx, 1)) {
33626 duk_bool_t flag_g, flag_i, flag_m;
33631
33632 duk_push_sprintf(ctx, "%s%s%s",
33633 (const char *) (flag_g ? "g" : ""),
33634 (const char *) (flag_i ? "i" : ""),
33635 (const char *) (flag_m ? "m" : ""));
33636
33637 /* [ ... pattern flags ] */
33638 } else {
33639 return DUK_RET_TYPE_ERROR;
33640 }
33641 } else {
33642 if (duk_is_undefined(ctx, 0)) {
33643 duk_push_string(ctx, "");
33644 } else {
33645 duk_dup(ctx, 0);
33646 duk_to_string(ctx, -1);
33647 }
33648 if (duk_is_undefined(ctx, 1)) {
33649 duk_push_string(ctx, "");
33650 } else {
33651 duk_dup(ctx, 1);
33652 duk_to_string(ctx, -1);
33653 }
33654
33655 /* [ ... pattern flags ] */
33656 }
33658 DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
33659 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
33660
33661 /* [ ... pattern flags ] */
33662
33663 duk_regexp_compile(thr);
33664
33665 /* [ ... bytecode escaped_source ] */
33666
33668
33669 /* [ ... RegExp ] */
33670
33671 return 1;
33672}
33673
33676
33677 /* [ regexp input ] */
33678
33680
33681 /* [ result ] */
33682
33683 return 1;
33685
33688
33689 /* [ regexp input ] */
33690
33691 /* result object is created and discarded; wasteful but saves code space */
33693
33694 /* [ result ] */
33695
33696 duk_push_boolean(ctx, (duk_is_null(ctx, -1) ? 0 : 1));
33697
33698 return 1;
33699}
33700
33702 duk_hstring *h_bc;
33703 duk_small_int_t re_flags;
33704
33705#if 0
33706 /* A little tricky string approach to provide the flags string.
33707 * This depends on the specific flag values in duk_regexp.h,
33708 * which needs to be asserted for. In practice this doesn't
33709 * produce more compact code than the easier approach in use.
33710 */
33711
33712 const char *flag_strings = "gim\0gi\0gm\0g\0";
33713 duk_uint8_t flag_offsets[8] = {
33714 (duk_uint8_t) 3, /* flags: "" */
33715 (duk_uint8_t) 10, /* flags: "g" */
33716 (duk_uint8_t) 5, /* flags: "i" */
33717 (duk_uint8_t) 4, /* flags: "gi" */
33718 (duk_uint8_t) 2, /* flags: "m" */
33719 (duk_uint8_t) 7, /* flags: "gm" */
33720 (duk_uint8_t) 1, /* flags: "im" */
33721 (duk_uint8_t) 0, /* flags: "gim" */
33722 };
33726#endif
33727
33729
33730 /* [ regexp ] */
33731
33734 h_bc = duk_get_hstring(ctx, -1);
33735 DUK_ASSERT(h_bc != NULL);
33738 DUK_ASSERT(DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);
33739 re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
33740
33741 /* [ regexp source bytecode ] */
33742
33743#if 1
33744 /* This is a cleaner approach and also produces smaller code than
33745 * the other alternative. Use duk_require_string() for format
33746 * safety (although the source property should always exist).
33747 */
33748 duk_push_sprintf(ctx, "/%s/%s%s%s",
33749 (const char *) duk_require_string(ctx, -2), /* require to be safe */
33750 (re_flags & DUK_RE_FLAG_GLOBAL) ? "g" : "",
33751 (re_flags & DUK_RE_FLAG_IGNORE_CASE) ? "i" : "",
33752 (re_flags & DUK_RE_FLAG_MULTILINE) ? "m" : "");
33753#else
33754 /* This should not be necessary because no-one should tamper with the
33755 * regexp bytecode, but is prudent to avoid potential segfaults if that
33756 * were to happen for some reason.
33757 */
33758 re_flags &= 0x07;
33759 DUK_ASSERT(re_flags >= 0 && re_flags <= 7); /* three flags */
33760 duk_push_sprintf(ctx, "/%s/%s",
33761 (const char *) duk_require_string(ctx, -2),
33762 (const char *) (flag_strings + flag_offsets[re_flags]));
33763#endif
33764
33765 return 1;
33766}
33767
33768#else /* DUK_USE_REGEXP_SUPPORT */
33769
33771 DUK_UNREF(ctx);
33773}
33774
33776 DUK_UNREF(ctx);
33778}
33779
33781 DUK_UNREF(ctx);
33783}
33784
33786 DUK_UNREF(ctx);
33788}
33789
33790#endif /* DUK_USE_REGEXP_SUPPORT */
33791/*
33792 * String built-ins
33794
33795/* XXX: There are several limitations in the current implementation for
33796 * strings with >= 0x80000000UL characters. In some cases one would need
33797 * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
33798 * Generally character and byte length are assumed to fit into signed 32
33799 * bits (< 0x80000000UL). Places with issues are not marked explicitly
33800 * below in all cases, look for signed type usage (duk_int_t etc) for
33801 * offsets/lengths.
33802 */
33803
33804/* include removed: duk_internal.h */
33805
33806/*
33807 * Constructor
33808 */
33809
33811 /* String constructor needs to distinguish between an argument not given at all
33812 * vs. given as 'undefined'. We're a vararg function to handle this properly.
33813 */
33814
33815 if (duk_get_top(ctx) == 0) {
33817 } else {
33818 duk_to_string(ctx, 0);
33819 }
33820 DUK_ASSERT(duk_is_string(ctx, 0));
33821 duk_set_top(ctx, 1);
33823 if (duk_is_constructor_call(ctx)) {
33829
33830 /* String object internal value is immutable */
33831 duk_dup(ctx, 0);
33833 }
33834 /* Note: unbalanced stack on purpose */
33835
33836 return 1;
33837}
33838
33840 duk_hthread *thr = (duk_hthread *) ctx;
33841 duk_bufwriter_ctx bw_alloc;
33843 duk_idx_t i, n;
33845
33846 /* XXX: It would be nice to build the string directly but ToUint16()
33847 * coercion is needed so a generic helper would not be very
33848 * helpful (perhaps coerce the value stack first here and then
33849 * build a string from a duk_tval number sequence in one go?).
33850 */
33851
33852 n = duk_get_top(ctx);
33853
33854 bw = &bw_alloc;
33855 DUK_BW_INIT_PUSHBUF(thr, bw, n); /* initial estimate for ASCII only codepoints */
33856
33857 for (i = 0; i < n; i++) {
33858 /* XXX: could improve bufwriter handling to write multiple codepoints
33859 * with one ensure call but the relative benefit would be quite small.
33860 */
33861
33862#if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
33863 /* ToUint16() coercion is mandatory in the E5.1 specification, but
33864 * this non-compliant behavior makes more sense because we support
33865 * non-BMP codepoints. Don't use CESU-8 because that'd create
33866 * surrogate pairs.
33867 */
33868
33870 DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
33871#else
33872 cp = (duk_ucodepoint_t) duk_to_uint16(ctx, i);
33873 DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
33874#endif
33875 }
33876
33877 DUK_BW_COMPACT(thr, bw);
33878 duk_to_string(ctx, -1);
33879 return 1;
33880}
33881
33882/*
33883 * toString(), valueOf()
33884 */
33885
33887 duk_tval *tv;
33888
33889 duk_push_this(ctx);
33890 tv = duk_require_tval(ctx, -1);
33891 DUK_ASSERT(tv != NULL);
33892
33893 if (DUK_TVAL_IS_STRING(tv)) {
33894 /* return as is */
33895 return 1;
33896 } else if (DUK_TVAL_IS_OBJECT(tv)) {
33898 DUK_ASSERT(h != NULL);
33899
33900 /* Must be a "string object", i.e. class "String" */
33902 goto type_error;
33903 }
33904
33907
33908 return 1;
33909 } else {
33910 goto type_error;
33911 }
33912
33913 /* never here, but fall through */
33914
33915 type_error:
33916 return DUK_RET_TYPE_ERROR;
33918
33919/*
33920 * Character and charcode access
33921 */
33922
33924 duk_int_t pos;
33925
33926 /* XXX: faster implementation */
33927
33929 pos = duk_to_int(ctx, 0);
33930 duk_substring(ctx, -1, pos, pos + 1);
33931 return 1;
33932}
33933
33935 duk_hthread *thr = (duk_hthread *) ctx;
33936 duk_int_t pos;
33937 duk_hstring *h;
33938 duk_bool_t clamped;
33939
33940 /* XXX: faster implementation */
33941
33942 DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(ctx, 0)));
33943
33945 DUK_ASSERT(h != NULL);
33946
33947 pos = duk_to_int_clamped_raw(ctx,
33948 0 /*index*/,
33949 0 /*min(incl)*/,
33950 DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
33951 &clamped /*out_clamped*/);
33952 if (clamped) {
33954 return 1;
33955 }
33956
33957 duk_push_u32(ctx, (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, pos));
33958 return 1;
33959}
33960
33961/*
33962 * substring(), substr(), slice()
33963 */
33964
33965/* XXX: any chance of merging these three similar but still slightly
33966 * different algorithms so that footprint would be reduced?
33967 */
33968
33970 duk_hstring *h;
33971 duk_int_t start_pos, end_pos;
33972 duk_int_t len;
33973
33975 DUK_ASSERT(h != NULL);
33977
33978 /* [ start end str ] */
33979
33980 start_pos = duk_to_int_clamped(ctx, 0, 0, len);
33981 if (duk_is_undefined(ctx, 1)) {
33982 end_pos = len;
33983 } else {
33984 end_pos = duk_to_int_clamped(ctx, 1, 0, len);
33986 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
33987 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
33988
33989 if (start_pos > end_pos) {
33990 duk_int_t tmp = start_pos;
33991 start_pos = end_pos;
33992 end_pos = tmp;
33993 }
33994
33995 DUK_ASSERT(end_pos >= start_pos);
33996
33997 duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
33998 return 1;
33999}
34000
34001#ifdef DUK_USE_SECTION_B
34003 duk_hstring *h;
34004 duk_int_t start_pos, end_pos;
34005 duk_int_t len;
34006
34007 /* Unlike non-obsolete String calls, substr() algorithm in E5.1
34008 * specification will happily coerce undefined and null to strings
34009 * ("undefined" and "null").
34010 */
34011 duk_push_this(ctx);
34012 h = duk_to_hstring(ctx, -1);
34013 DUK_ASSERT(h != NULL);
34015
34016 /* [ start length str ] */
34017
34018 /* The implementation for computing of start_pos and end_pos differs
34019 * from the standard algorithm, but is intended to result in the exactly
34020 * same behavior. This is not always obvious.
34021 */
34022
34023 /* combines steps 2 and 5; -len ensures max() not needed for step 5 */
34024 start_pos = duk_to_int_clamped(ctx, 0, -len, len);
34025 if (start_pos < 0) {
34026 start_pos = len + start_pos;
34027 }
34028 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34029
34030 /* combines steps 3, 6; step 7 is not needed */
34031 if (duk_is_undefined(ctx, 1)) {
34032 end_pos = len;
34033 } else {
34034 DUK_ASSERT(start_pos <= len);
34035 end_pos = start_pos + duk_to_int_clamped(ctx, 1, 0, len - start_pos);
34036 }
34037 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34038 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34039 DUK_ASSERT(end_pos >= start_pos);
34040
34041 duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34042 return 1;
34043}
34044#else /* DUK_USE_SECTION_B */
34046 DUK_UNREF(ctx);
34048}
34049#endif /* DUK_USE_SECTION_B */
34050
34052 duk_hstring *h;
34053 duk_int_t start_pos, end_pos;
34054 duk_int_t len;
34055
34057 DUK_ASSERT(h != NULL);
34059
34060 /* [ start end str ] */
34061
34062 start_pos = duk_to_int_clamped(ctx, 0, -len, len);
34063 if (start_pos < 0) {
34064 start_pos = len + start_pos;
34065 }
34066 if (duk_is_undefined(ctx, 1)) {
34067 end_pos = len;
34068 } else {
34069 end_pos = duk_to_int_clamped(ctx, 1, -len, len);
34070 if (end_pos < 0) {
34071 end_pos = len + end_pos;
34072 }
34073 }
34074 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34075 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34076
34077 if (end_pos < start_pos) {
34078 end_pos = start_pos;
34079 }
34080
34081 DUK_ASSERT(end_pos >= start_pos);
34082
34083 duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34084 return 1;
34085}
34086
34088 * Case conversion
34089 */
34090
34092 duk_hthread *thr = (duk_hthread *) ctx;
34093 duk_small_int_t uppercase = duk_get_current_magic(ctx);
34094
34097 return 1;
34098}
34099
34100/*
34101 * indexOf() and lastIndexOf()
34102 */
34103
34105 duk_hthread *thr = (duk_hthread *) ctx;
34106 duk_hstring *h_this;
34107 duk_hstring *h_search;
34108 duk_int_t clen_this;
34109 duk_int_t cpos;
34110 duk_int_t bpos;
34111 const duk_uint8_t *p_start, *p_end, *p;
34112 const duk_uint8_t *q_start;
34113 duk_int_t q_blen;
34114 duk_uint8_t firstbyte;
34115 duk_uint8_t t;
34116 duk_small_int_t is_lastindexof = duk_get_current_magic(ctx); /* 0=indexOf, 1=lastIndexOf */
34117
34119 DUK_ASSERT(h_this != NULL);
34120 clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
34121
34122 h_search = duk_to_hstring(ctx, 0);
34123 DUK_ASSERT(h_search != NULL);
34124 q_start = DUK_HSTRING_GET_DATA(h_search);
34125 q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
34126
34127 duk_to_number(ctx, 1);
34128 if (duk_is_nan(ctx, 1) && is_lastindexof) {
34129 /* indexOf: NaN should cause pos to be zero.
34130 * lastIndexOf: NaN should cause pos to be +Infinity
34131 * (and later be clamped to len).
34132 */
34133 cpos = clen_this;
34134 } else {
34135 cpos = duk_to_int_clamped(ctx, 1, 0, clen_this);
34136 }
34137
34138 /* Empty searchstring always matches; cpos must be clamped here.
34139 * (If q_blen were < 0 due to clamped coercion, it would also be
34140 * caught here.)
34141 */
34142 if (q_blen <= 0) {
34143 duk_push_int(ctx, cpos);
34144 return 1;
34145 }
34146 DUK_ASSERT(q_blen > 0);
34147
34148 bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
34149
34150 p_start = DUK_HSTRING_GET_DATA(h_this);
34151 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
34152 p = p_start + bpos;
34153
34154 /* This loop is optimized for size. For speed, there should be
34155 * two separate loops, and we should ensure that memcmp() can be
34156 * used without an extra "will searchstring fit" check. Doing
34157 * the preconditioning for 'p' and 'p_end' is easy but cpos
34158 * must be updated if 'p' is wound back (backward scanning).
34159 */
34160
34161 firstbyte = q_start[0]; /* leading byte of match string */
34162 while (p <= p_end && p >= p_start) {
34163 t = *p;
34164
34165 /* For Ecmascript strings, this check can only match for
34166 * initial UTF-8 bytes (not continuation bytes). For other
34167 * strings all bets are off.
34168 */
34169
34170 if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
34171 DUK_ASSERT(q_blen > 0); /* no issues with memcmp() zero size, even if broken */
34172 if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34173 duk_push_int(ctx, cpos);
34174 return 1;
34175 }
34176 }
34177
34178 /* track cpos while scanning */
34179 if (is_lastindexof) {
34180 /* when going backwards, we decrement cpos 'early';
34181 * 'p' may point to a continuation byte of the char
34182 * at offset 'cpos', but that's OK because we'll
34183 * backtrack all the way to the initial byte.
34184 */
34185 if ((t & 0xc0) != 0x80) {
34186 cpos--;
34187 }
34188 p--;
34189 } else {
34190 if ((t & 0xc0) != 0x80) {
34191 cpos++;
34192 }
34193 p++;
34194 }
34195 }
34196
34197 /* Not found. Empty string case is handled specially above. */
34198 duk_push_int(ctx, -1);
34199 return 1;
34201
34202/*
34203 * replace()
34204 */
34205
34206/* XXX: the current implementation works but is quite clunky; it compiles
34207 * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
34208 * shared helpers, etc). Some ideas for refactoring:
34209 *
34210 * - a primitive to convert a string into a regexp matcher (reduces matching
34211 * code at the cost of making matching much slower)
34212 * - use replace() as a basic helper for match() and split(), which are both
34213 * much simpler
34214 * - API call to get_prop and to_boolean
34215 */
34216
34218 duk_hthread *thr = (duk_hthread *) ctx;
34219 duk_hstring *h_input;
34220 duk_hstring *h_match;
34221 duk_hstring *h_search;
34222 duk_hobject *h_re;
34223 duk_bufwriter_ctx bw_alloc;
34225#ifdef DUK_USE_REGEXP_SUPPORT
34226 duk_bool_t is_regexp;
34227 duk_bool_t is_global;
34228#endif
34229 duk_bool_t is_repl_func;
34230 duk_uint32_t match_start_coff, match_start_boff;
34231#ifdef DUK_USE_REGEXP_SUPPORT
34232 duk_int_t match_caps;
34233#endif
34234 duk_uint32_t prev_match_end_boff;
34235 const duk_uint8_t *r_start, *r_end, *r; /* repl string scan */
34236 duk_size_t tmp_sz;
34237
34238 DUK_ASSERT_TOP(ctx, 2);
34239 h_input = duk_push_this_coercible_to_string(ctx);
34240 DUK_ASSERT(h_input != NULL);
34241
34242 bw = &bw_alloc;
34243 DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* input size is good output starting point */
34244
34245 DUK_ASSERT_TOP(ctx, 4);
34246
34247 /* stack[0] = search value
34248 * stack[1] = replace value
34249 * stack[2] = input string
34250 * stack[3] = result buffer
34251 */
34252
34254 if (h_re) {
34255#ifdef DUK_USE_REGEXP_SUPPORT
34256 is_regexp = 1;
34258
34259 if (is_global) {
34260 /* start match from beginning */
34261 duk_push_int(ctx, 0);
34263 }
34264#else /* DUK_USE_REGEXP_SUPPORT */
34266#endif /* DUK_USE_REGEXP_SUPPORT */
34267 } else {
34268 duk_to_string(ctx, 0);
34269#ifdef DUK_USE_REGEXP_SUPPORT
34270 is_regexp = 0;
34271 is_global = 0;
34272#endif
34273 }
34274
34275 if (duk_is_function(ctx, 1)) {
34276 is_repl_func = 1;
34277 r_start = NULL;
34278 r_end = NULL;
34279 } else {
34280 duk_hstring *h_repl;
34281
34282 is_repl_func = 0;
34283 h_repl = duk_to_hstring(ctx, 1);
34284 DUK_ASSERT(h_repl != NULL);
34285 r_start = DUK_HSTRING_GET_DATA(h_repl);
34286 r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
34287 }
34288
34289 prev_match_end_boff = 0;
34290
34291 for (;;) {
34292 /*
34293 * If matching with a regexp:
34294 * - non-global RegExp: lastIndex not touched on a match, zeroed
34295 * on a non-match
34296 * - global RegExp: on match, lastIndex will be updated by regexp
34297 * executor to point to next char after the matching part (so that
34298 * characters in the matching part are not matched again)
34299 *
34300 * If matching with a string:
34301 * - always non-global match, find first occurrence
34302 *
34303 * We need:
34304 * - The character offset of start-of-match for the replacer function
34305 * - The byte offsets for start-of-match and end-of-match to implement
34306 * the replacement values $&, $`, and $', and to copy non-matching
34307 * input string portions (including header and trailer) verbatim.
34308 *
34309 * NOTE: the E5.1 specification is a bit vague how the RegExp should
34310 * behave in the replacement process; e.g. is matching done first for
34311 * all matches (in the global RegExp case) before any replacer calls
34312 * are made? See: test-bi-string-proto-replace.js for discussion.
34313 */
34314
34315 DUK_ASSERT_TOP(ctx, 4);
34316
34317#ifdef DUK_USE_REGEXP_SUPPORT
34318 if (is_regexp) {
34319 duk_dup(ctx, 0);
34320 duk_dup(ctx, 2);
34321 duk_regexp_match(thr); /* [ ... regexp input ] -> [ res_obj ] */
34322 if (!duk_is_object(ctx, -1)) {
34323 duk_pop(ctx);
34324 break;
34325 }
34326
34328 DUK_ASSERT(duk_is_number(ctx, -1));
34329 match_start_coff = duk_get_int(ctx, -1);
34330 duk_pop(ctx);
34331
34332 duk_get_prop_index(ctx, -1, 0);
34333 DUK_ASSERT(duk_is_string(ctx, -1));
34334 h_match = duk_get_hstring(ctx, -1);
34335 DUK_ASSERT(h_match != NULL);
34336 duk_pop(ctx); /* h_match is borrowed, remains reachable through match_obj */
34337
34338 if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
34339 /* This should be equivalent to match() algorithm step 8.f.iii.2:
34340 * detect an empty match and allow it, but don't allow it twice.
34341 */
34342 duk_uint32_t last_index;
34343
34345 last_index = (duk_uint32_t) duk_get_uint(ctx, -1);
34346 DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
34347 (long) last_index, (long) (last_index + 1)));
34348 duk_pop(ctx);
34349 duk_push_int(ctx, last_index + 1);
34351 }
34352
34353 DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_INT_MAX); /* string limits */
34354 match_caps = (duk_int_t) duk_get_length(ctx, -1);
34355 } else {
34356#else /* DUK_USE_REGEXP_SUPPORT */
34357 { /* unconditionally */
34358#endif /* DUK_USE_REGEXP_SUPPORT */
34359 const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
34360 const duk_uint8_t *q_start; /* match string */
34361 duk_size_t q_blen;
34362
34363#ifdef DUK_USE_REGEXP_SUPPORT
34364 DUK_ASSERT(!is_global); /* single match always */
34365#endif
34366
34367 p_start = DUK_HSTRING_GET_DATA(h_input);
34368 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
34369 p = p_start;
34370
34371 h_search = duk_get_hstring(ctx, 0);
34372 DUK_ASSERT(h_search != NULL);
34373 q_start = DUK_HSTRING_GET_DATA(h_search);
34374 q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
34375
34376 p_end -= q_blen; /* ensure full memcmp() fits in while */
34377
34378 match_start_coff = 0;
34379
34380 while (p <= p_end) {
34381 DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
34382 if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34383 duk_dup(ctx, 0);
34384 h_match = duk_get_hstring(ctx, -1);
34385 DUK_ASSERT(h_match != NULL);
34386#ifdef DUK_USE_REGEXP_SUPPORT
34387 match_caps = 0;
34388#endif
34389 goto found;
34390 }
34391
34392 /* track utf-8 non-continuation bytes */
34393 if ((p[0] & 0xc0) != 0x80) {
34394 match_start_coff++;
34395 }
34396 p++;
34397 }
34398
34399 /* not found */
34400 break;
34401 }
34402 found:
34403
34404 /* stack[0] = search value
34405 * stack[1] = replace value
34406 * stack[2] = input string
34407 * stack[3] = result buffer
34408 * stack[4] = regexp match OR match string
34409 */
34410
34411 match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
34412
34413 tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
34414 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
34415
34416 prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
34417
34418 if (is_repl_func) {
34419 duk_idx_t idx_args;
34420 duk_hstring *h_repl;
34421
34422 /* regexp res_obj is at index 4 */
34423
34424 duk_dup(ctx, 1);
34425 idx_args = duk_get_top(ctx);
34426
34427#ifdef DUK_USE_REGEXP_SUPPORT
34428 if (is_regexp) {
34429 duk_int_t idx;
34430 duk_require_stack(ctx, match_caps + 2);
34431 for (idx = 0; idx < match_caps; idx++) {
34432 /* match followed by capture(s) */
34433 duk_get_prop_index(ctx, 4, idx);
34434 }
34435 } else {
34436#else /* DUK_USE_REGEXP_SUPPORT */
34437 { /* unconditionally */
34438#endif /* DUK_USE_REGEXP_SUPPORT */
34439 /* match == search string, by definition */
34440 duk_dup(ctx, 0);
34441 }
34442 duk_push_int(ctx, match_start_coff);
34443 duk_dup(ctx, 2);
34444
34445 /* [ ... replacer match [captures] match_char_offset input ] */
34446
34447 duk_call(ctx, duk_get_top(ctx) - idx_args);
34448 h_repl = duk_to_hstring(ctx, -1); /* -> [ ... repl_value ] */
34449 DUK_ASSERT(h_repl != NULL);
34450
34451 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
34452
34453 duk_pop(ctx); /* repl_value */
34454 } else {
34455 r = r_start;
34456
34457 while (r < r_end) {
34458 duk_int_t ch1;
34459 duk_int_t ch2;
34460#ifdef DUK_USE_REGEXP_SUPPORT
34461 duk_int_t ch3;
34462#endif
34464
34465 ch1 = *r++;
34466 if (ch1 != DUK_ASC_DOLLAR) {
34467 goto repl_write;
34468 }
34469 left = r_end - r;
34470
34471 if (left <= 0) {
34472 goto repl_write;
34473 }
34474
34475 ch2 = r[0];
34476 switch ((int) ch2) {
34477 case DUK_ASC_DOLLAR: {
34478 ch1 = (1 << 8) + DUK_ASC_DOLLAR;
34479 goto repl_write;
34480 }
34481 case DUK_ASC_AMP: {
34482 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
34483 r++;
34484 continue;
34485 }
34486 case DUK_ASC_GRAVE: {
34487 tmp_sz = (duk_size_t) match_start_boff;
34488 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
34489 r++;
34490 continue;
34491 }
34492 case DUK_ASC_SINGLEQUOTE: {
34493 duk_uint32_t match_end_boff;
34494
34495 /* Use match charlen instead of bytelen, just in case the input and
34496 * match codepoint encodings would have different lengths.
34497 */
34498 match_end_boff = duk_heap_strcache_offset_char2byte(thr,
34499 h_input,
34500 match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match));
34501
34502 tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
34503 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
34504 r++;
34505 continue;
34506 }
34507 default: {
34508#ifdef DUK_USE_REGEXP_SUPPORT
34509 duk_int_t capnum, captmp, capadv;
34510 /* XXX: optional check, match_caps is zero if no regexp,
34511 * so dollar will be interpreted literally anyway.
34512 */
34513
34514 if (!is_regexp) {
34515 goto repl_write;
34516 }
34517
34518 if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
34519 goto repl_write;
34520 }
34521 capnum = ch2 - DUK_ASC_0;
34522 capadv = 1;
34523
34524 if (left >= 2) {
34525 ch3 = r[1];
34526 if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
34527 captmp = capnum * 10 + (ch3 - DUK_ASC_0);
34528 if (captmp < match_caps) {
34529 capnum = captmp;
34530 capadv = 2;
34531 }
34532 }
34533 }
34534
34535 if (capnum > 0 && capnum < match_caps) {
34536 DUK_ASSERT(is_regexp != 0); /* match_caps == 0 without regexps */
34537
34538 /* regexp res_obj is at offset 4 */
34539 duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum);
34540 if (duk_is_string(ctx, -1)) {
34541 duk_hstring *h_tmp_str;
34542
34543 h_tmp_str = duk_get_hstring(ctx, -1);
34544 DUK_ASSERT(h_tmp_str != NULL);
34545
34546 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
34547 } else {
34548 /* undefined -> skip (replaced with empty) */
34549 }
34550 duk_pop(ctx);
34551 r += capadv;
34552 continue;
34553 } else {
34554 goto repl_write;
34555 }
34556#else /* DUK_USE_REGEXP_SUPPORT */
34557 goto repl_write; /* unconditionally */
34558#endif /* DUK_USE_REGEXP_SUPPORT */
34559 } /* default case */
34560 } /* switch (ch2) */
34561
34562 repl_write:
34563 /* ch1 = (r_increment << 8) + byte */
34564
34565 DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
34566 r += ch1 >> 8;
34567 } /* while repl */
34568 } /* if (is_repl_func) */
34569
34570 duk_pop(ctx); /* pop regexp res_obj or match string */
34571
34572#ifdef DUK_USE_REGEXP_SUPPORT
34573 if (!is_global) {
34574#else
34575 { /* unconditionally; is_global==0 */
34576#endif
34577 break;
34578 }
34579 }
34580
34581 /* trailer */
34582 tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
34583 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
34584
34585 DUK_ASSERT_TOP(ctx, 4);
34586 DUK_BW_COMPACT(thr, bw);
34587 duk_to_string(ctx, -1);
34588 return 1;
34589}
34590
34591/*
34592 * split()
34593 */
34594
34595/* XXX: very messy now, but works; clean up, remove unused variables (nomimally
34596 * used so compiler doesn't complain).
34597 */
34598
34600 duk_hthread *thr = (duk_hthread *) ctx;
34601 duk_hstring *h_input;
34602 duk_hstring *h_sep;
34603 duk_uint32_t limit;
34604 duk_uint32_t arr_idx;
34605#ifdef DUK_USE_REGEXP_SUPPORT
34606 duk_bool_t is_regexp;
34607#endif
34608 duk_bool_t matched; /* set to 1 if any match exists (needed for empty input special case) */
34609 duk_uint32_t prev_match_end_coff, prev_match_end_boff;
34610 duk_uint32_t match_start_boff, match_start_coff;
34611 duk_uint32_t match_end_boff, match_end_coff;
34612
34613 DUK_UNREF(thr);
34614
34615 h_input = duk_push_this_coercible_to_string(ctx);
34616 DUK_ASSERT(h_input != NULL);
34617
34618 duk_push_array(ctx);
34619
34620 if (duk_is_undefined(ctx, 1)) {
34621 limit = 0xffffffffUL;
34622 } else {
34623 limit = duk_to_uint32(ctx, 1);
34624 }
34625
34626 if (limit == 0) {
34627 return 1;
34628 }
34629
34630 /* If the separator is a RegExp, make a "clone" of it. The specification
34631 * algorithm calls [[Match]] directly for specific indices; we emulate this
34632 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
34633 * which will use global-style matching even when the RegExp itself is non-global.
34634 */
34635
34636 if (duk_is_undefined(ctx, 0)) {
34637 /* The spec algorithm first does "R = ToString(separator)" before checking
34638 * whether separator is undefined. Since this is side effect free, we can
34639 * skip the ToString() here.
34640 */
34641 duk_dup(ctx, 2);
34642 duk_put_prop_index(ctx, 3, 0);
34643 return 1;
34645#ifdef DUK_USE_REGEXP_SUPPORT
34647 duk_dup(ctx, 0);
34648 duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */
34649 duk_replace(ctx, 0);
34650 /* lastIndex is initialized to zero by new RegExp() */
34651 is_regexp = 1;
34652#else
34654#endif
34655 } else {
34656 duk_to_string(ctx, 0);
34657#ifdef DUK_USE_REGEXP_SUPPORT
34658 is_regexp = 0;
34659#endif
34660 }
34661
34662 /* stack[0] = separator (string or regexp)
34663 * stack[1] = limit
34664 * stack[2] = input string
34665 * stack[3] = result array
34666 */
34667
34668 prev_match_end_boff = 0;
34669 prev_match_end_coff = 0;
34670 arr_idx = 0;
34671 matched = 0;
34672
34673 for (;;) {
34674 /*
34675 * The specification uses RegExp [[Match]] to attempt match at specific
34676 * offsets. We don't have such a primitive, so we use an actual RegExp
34677 * and tweak lastIndex. Since the RegExp may be non-global, we use a
34678 * special variant which forces global-like behavior for matching.
34679 */
34680
34681 DUK_ASSERT_TOP(ctx, 4);
34682
34683#ifdef DUK_USE_REGEXP_SUPPORT
34684 if (is_regexp) {
34685 duk_dup(ctx, 0);
34686 duk_dup(ctx, 2);
34687 duk_regexp_match_force_global(thr); /* [ ... regexp input ] -> [ res_obj ] */
34688 if (!duk_is_object(ctx, -1)) {
34689 duk_pop(ctx);
34690 break;
34691 }
34692 matched = 1;
34693
34695 DUK_ASSERT(duk_is_number(ctx, -1));
34696 match_start_coff = duk_get_int(ctx, -1);
34697 match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
34698 duk_pop(ctx);
34699
34700 if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
34701 /* don't allow an empty match at the end of the string */
34702 duk_pop(ctx);
34703 break;
34704 }
34705
34707 DUK_ASSERT(duk_is_number(ctx, -1));
34708 match_end_coff = duk_get_int(ctx, -1);
34709 match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
34710 duk_pop(ctx);
34711
34712 /* empty match -> bump and continue */
34713 if (prev_match_end_boff == match_end_boff) {
34714 duk_push_int(ctx, match_end_coff + 1);
34716 duk_pop(ctx);
34717 continue;
34718 }
34719 } else {
34720#else /* DUK_USE_REGEXP_SUPPORT */
34721 { /* unconditionally */
34722#endif /* DUK_USE_REGEXP_SUPPORT */
34723 const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
34724 const duk_uint8_t *q_start; /* match string */
34725 duk_size_t q_blen, q_clen;
34726
34727 p_start = DUK_HSTRING_GET_DATA(h_input);
34728 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
34729 p = p_start + prev_match_end_boff;
34730
34731 h_sep = duk_get_hstring(ctx, 0);
34732 DUK_ASSERT(h_sep != NULL);
34733 q_start = DUK_HSTRING_GET_DATA(h_sep);
34734 q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
34735 q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
34736
34737 p_end -= q_blen; /* ensure full memcmp() fits in while */
34738
34739 match_start_coff = prev_match_end_coff;
34740
34741 if (q_blen == 0) {
34742 /* Handle empty separator case: it will always match, and always
34743 * triggers the check in step 13.c.iii initially. Note that we
34744 * must skip to either end of string or start of first codepoint,
34745 * skipping over any continuation bytes!
34746 *
34747 * Don't allow an empty string to match at the end of the input.
34748 */
34749
34750 matched = 1; /* empty separator can always match */
34751
34752 match_start_coff++;
34753 p++;
34754 while (p < p_end) {
34755 if ((p[0] & 0xc0) != 0x80) {
34756 goto found;
34757 }
34758 p++;
34759 }
34760 goto not_found;
34761 }
34762
34763 DUK_ASSERT(q_blen > 0 && q_clen > 0);
34764 while (p <= p_end) {
34765 DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
34766 DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */
34767 if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34768 /* never an empty match, so step 13.c.iii can't be triggered */
34769 goto found;
34770 }
34771
34772 /* track utf-8 non-continuation bytes */
34773 if ((p[0] & 0xc0) != 0x80) {
34774 match_start_coff++;
34775 }
34776 p++;
34777 }
34778
34779 not_found:
34780 /* not found */
34781 break;
34782
34783 found:
34784 matched = 1;
34785 match_start_boff = (duk_uint32_t) (p - p_start);
34786 match_end_coff = (duk_uint32_t) (match_start_coff + q_clen); /* constrained by string length */
34787 match_end_boff = (duk_uint32_t) (match_start_boff + q_blen); /* ditto */
34788
34789 /* empty match (may happen with empty separator) -> bump and continue */
34790 if (prev_match_end_boff == match_end_boff) {
34791 prev_match_end_boff++;
34792 prev_match_end_coff++;
34793 continue;
34794 }
34795 } /* if (is_regexp) */
34796
34797 /* stack[0] = separator (string or regexp)
34798 * stack[1] = limit
34799 * stack[2] = input string
34800 * stack[3] = result array
34801 * stack[4] = regexp res_obj (if is_regexp)
34802 */
34803
34804 DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
34805 (long) match_start_boff, (long) match_start_coff,
34806 (long) match_end_boff, (long) match_end_coff,
34807 (long) prev_match_end_boff, (long) prev_match_end_coff));
34808
34809 duk_push_lstring(ctx,
34810 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
34811 (duk_size_t) (match_start_boff - prev_match_end_boff));
34812 duk_put_prop_index(ctx, 3, arr_idx);
34813 arr_idx++;
34814 if (arr_idx >= limit) {
34815 goto hit_limit;
34816 }
34817
34818#ifdef DUK_USE_REGEXP_SUPPORT
34819 if (is_regexp) {
34820 duk_size_t i, len;
34821
34822 len = duk_get_length(ctx, 4);
34823 for (i = 1; i < len; i++) {
34824 DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* cannot have >4G captures */
34825 duk_get_prop_index(ctx, 4, (duk_uarridx_t) i);
34826 duk_put_prop_index(ctx, 3, arr_idx);
34827 arr_idx++;
34828 if (arr_idx >= limit) {
34829 goto hit_limit;
34830 }
34831 }
34832
34833 duk_pop(ctx);
34834 /* lastIndex already set up for next match */
34835 } else {
34836#else /* DUK_USE_REGEXP_SUPPORT */
34837 { /* unconditionally */
34838#endif /* DUK_USE_REGEXP_SUPPORT */
34839 /* no action */
34840 }
34841
34842 prev_match_end_boff = match_end_boff;
34843 prev_match_end_coff = match_end_coff;
34844 continue;
34845 } /* for */
34846
34847 /* Combined step 11 (empty string special case) and 14-15. */
34848
34849 DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
34850 (long) prev_match_end_boff, (long) prev_match_end_coff));
34851
34852 if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) {
34853 /* Add trailer if:
34854 * a) non-empty input
34855 * b) empty input and no (zero size) match found (step 11)
34856 */
34857
34858 duk_push_lstring(ctx,
34859 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
34860 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
34861 duk_put_prop_index(ctx, 3, arr_idx);
34862 /* No arr_idx update or limit check */
34863 }
34864
34865 return 1;
34866
34867 hit_limit:
34868#ifdef DUK_USE_REGEXP_SUPPORT
34869 if (is_regexp) {
34870 duk_pop(ctx);
34871 }
34872#endif
34873
34874 return 1;
34875}
34876
34877/*
34878 * Various
34879 */
34880
34881#ifdef DUK_USE_REGEXP_SUPPORT
34883 duk_hobject *h;
34884
34885 /* Shared helper for match() steps 3-4, search() steps 3-4. */
34886
34887 DUK_ASSERT(index >= 0);
34888
34889 if (force_new) {
34890 goto do_new;
34892
34894 if (!h) {
34895 goto do_new;
34896 }
34897 return;
34898
34899 do_new:
34901 duk_dup(ctx, index);
34902 duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */
34903 duk_replace(ctx, index);
34904}
34905#endif /* DUK_USE_REGEXP_SUPPORT */
34906
34907#ifdef DUK_USE_REGEXP_SUPPORT
34909 duk_hthread *thr = (duk_hthread *) ctx;
34910
34911 /* Easiest way to implement the search required by the specification
34912 * is to do a RegExp test() with lastIndex forced to zero. To avoid
34913 * side effects on the argument, "clone" the RegExp if a RegExp was
34914 * given as input.
34915 *
34916 * The global flag of the RegExp should be ignored; setting lastIndex
34917 * to zero (which happens when "cloning" the RegExp) should have an
34918 * equivalent effect.
34919 */
34920
34921 DUK_ASSERT_TOP(ctx, 1);
34922 (void) duk_push_this_coercible_to_string(ctx); /* at index 1 */
34923 duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/);
34924
34925 /* stack[0] = regexp
34926 * stack[1] = string
34927 */
34928
34929 /* Avoid using RegExp.prototype methods, as they're writable and
34930 * configurable and may have been changed.
34931 */
34932
34933 duk_dup(ctx, 0);
34934 duk_dup(ctx, 1); /* [ ... re_obj input ] */
34935 duk_regexp_match(thr); /* -> [ ... res_obj ] */
34936
34937 if (!duk_is_object(ctx, -1)) {
34938 duk_push_int(ctx, -1);
34939 return 1;
34940 }
34941
34943 DUK_ASSERT(duk_is_number(ctx, -1));
34944 return 1;
34945}
34946#else /* DUK_USE_REGEXP_SUPPORT */
34948 DUK_UNREF(ctx);
34950}
34951#endif /* DUK_USE_REGEXP_SUPPORT */
34952
34953#ifdef DUK_USE_REGEXP_SUPPORT
34955 duk_hthread *thr = (duk_hthread *) ctx;
34956 duk_bool_t global;
34957 duk_int_t prev_last_index;
34958 duk_int_t this_index;
34959 duk_int_t arr_idx;
34960
34961 DUK_ASSERT_TOP(ctx, 1);
34963 duk__to_regexp_helper(ctx, 0 /*index*/, 0 /*force_new*/);
34965 DUK_ASSERT_TOP(ctx, 2);
34966
34967 /* stack[0] = regexp
34968 * stack[1] = string
34969 */
34970
34971 if (!global) {
34972 duk_regexp_match(thr); /* -> [ res_obj ] */
34973 return 1; /* return 'res_obj' */
34974 }
34975
34976 /* Global case is more complex. */
34977
34978 /* [ regexp string ] */
34979
34980 duk_push_int(ctx, 0);
34982 duk_push_array(ctx);
34983
34984 /* [ regexp string res_arr ] */
34985
34986 prev_last_index = 0;
34987 arr_idx = 0;
34988
34989 for (;;) {
34990 DUK_ASSERT_TOP(ctx, 3);
34991
34992 duk_dup(ctx, 0);
34993 duk_dup(ctx, 1);
34994 duk_regexp_match(thr); /* -> [ ... regexp string ] -> [ ... res_obj ] */
34995
34996 if (!duk_is_object(ctx, -1)) {
34997 duk_pop(ctx);
34998 break;
34999 }
35000
35002 DUK_ASSERT(duk_is_number(ctx, -1));
35003 this_index = duk_get_int(ctx, -1);
35004 duk_pop(ctx);
35005
35006 if (this_index == prev_last_index) {
35007 this_index++;
35008 duk_push_int(ctx, this_index);
35010 }
35011 prev_last_index = this_index;
35012
35013 duk_get_prop_index(ctx, -1, 0); /* match string */
35014 duk_put_prop_index(ctx, 2, arr_idx);
35015 arr_idx++;
35016 duk_pop(ctx); /* res_obj */
35017 }
35018
35019 if (arr_idx == 0) {
35020 duk_push_null(ctx);
35021 }
35022
35023 return 1; /* return 'res_arr' or 'null' */
35024}
35025#else /* DUK_USE_REGEXP_SUPPORT */
35027 DUK_UNREF(ctx);
35029}
35030#endif /* DUK_USE_REGEXP_SUPPORT */
35033 /* duk_concat() coerces arguments with ToString() in correct order */
35035 duk_insert(ctx, 0); /* this is relatively expensive */
35036 duk_concat(ctx, duk_get_top(ctx));
35037 return 1;
35038}
35039
35041 DUK_ASSERT_TOP(ctx, 0);
35043 duk_trim(ctx, 0);
35044 DUK_ASSERT_TOP(ctx, 1);
35045 return 1;
35046}
35047
35049 duk_hstring *h1;
35050 duk_hstring *h2;
35051 duk_size_t h1_len, h2_len, prefix_len;
35052 duk_small_int_t ret = 0;
35053 duk_small_int_t rc;
35054
35055 /* The current implementation of localeCompare() is simply a codepoint
35056 * by codepoint comparison, implemented with a simple string compare
35057 * because UTF-8 should preserve codepoint ordering (assuming valid
35058 * shortest UTF-8 encoding).
35059 *
35060 * The specification requires that the return value must be related
35061 * to the sort order: e.g. negative means that 'this' comes before
35062 * 'that' in sort order. We assume an ascending sort order.
35063 */
35064
35065 /* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
35066
35068 DUK_ASSERT(h1 != NULL);
35069
35070 h2 = duk_to_hstring(ctx, 0);
35071 DUK_ASSERT(h2 != NULL);
35072
35073 h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
35074 h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
35075 prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
35076
35077 /* Zero size compare not an issue with DUK_MEMCMP. */
35078 rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),
35079 (const void *) DUK_HSTRING_GET_DATA(h2),
35080 (size_t) prefix_len);
35081
35082 if (rc < 0) {
35083 ret = -1;
35084 goto done;
35085 } else if (rc > 0) {
35086 ret = 1;
35087 goto done;
35088 }
35089
35090 /* prefix matches, lengths matter now */
35091 if (h1_len > h2_len) {
35092 ret = 1;
35093 goto done;
35094 } else if (h1_len == h2_len) {
35095 DUK_ASSERT(ret == 0);
35096 goto done;
35097 }
35098 ret = -1;
35099 goto done;
35100
35101 done:
35102 duk_push_int(ctx, (duk_int_t) ret);
35103 return 1;
35104}
35105/*
35106 * Thread builtins
35107 */
35108
35109/* include removed: duk_internal.h */
35110
35111/*
35112 * Constructor
35113 */
35114
35116 duk_hthread *new_thr;
35117 duk_hobject *func;
35118
35119 /* XXX: need a duk_require_func_or_lfunc_coerce() */
35120 if (!duk_is_callable(ctx, 0)) {
35121 return DUK_RET_TYPE_ERROR;
35122 }
35124 DUK_ASSERT(func != NULL);
35125
35126 duk_push_thread(ctx);
35127 new_thr = (duk_hthread *) duk_get_hobject(ctx, -1);
35128 DUK_ASSERT(new_thr != NULL);
35130
35131 /* push initial function call to new thread stack; this is
35132 * picked up by resume().
35133 */
35134 duk_push_hobject((duk_context *) new_thr, func);
35135
35136 return 1; /* return thread */
35138
35139/*
35140 * Resume a thread.
35141 *
35142 * The thread must be in resumable state, either (a) new thread which hasn't
35143 * yet started, or (b) a thread which has previously yielded. This method
35144 * must be called from an Ecmascript function.
35145 *
35146 * Args:
35147 * - thread
35148 * - value
35149 * - isError (defaults to false)
35150 *
35151 * Note: yield and resume handling is currently asymmetric.
35152 */
35153
35155 duk_hthread *thr = (duk_hthread *) ctx;
35156 duk_hthread *thr_resume;
35157 duk_tval *tv;
35158 duk_hobject *func;
35159 duk_hobject *caller_func;
35160 duk_small_int_t is_error;
35161
35162 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
35163 (duk_tval *) duk_get_tval(ctx, 0),
35164 (duk_tval *) duk_get_tval(ctx, 1),
35165 (duk_tval *) duk_get_tval(ctx, 2)));
35166
35168 DUK_ASSERT(thr->heap->curr_thread == thr);
35169
35170 thr_resume = duk_require_hthread(ctx, 0);
35171 is_error = (duk_small_int_t) duk_to_boolean(ctx, 2);
35172 duk_set_top(ctx, 2);
35173
35174 /* [ thread value ] */
35175
35176 /*
35177 * Thread state and calling context checks
35178 */
35179
35180 if (thr->callstack_top < 2) {
35181 DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
35182 goto state_error;
35183 }
35184 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
35186 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
35187
35188 caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
35189 if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
35190 DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
35191 goto state_error;
35192 }
35193
35194 /* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
35195 * like for yield.
35196 */
35197
35198 if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
35199 thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
35200 DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
35201 goto state_error;
35202 }
35203
35205 thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
35206
35207 /* Further state-dependent pre-checks */
35208
35209 if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
35210 /* no pre-checks now, assume a previous yield() has left things in
35211 * tip-top shape (longjmp handler will assert for these).
35212 */
35213 } else {
35215
35216 if ((thr_resume->callstack_top != 0) ||
35217 (thr_resume->valstack_top - thr_resume->valstack != 1)) {
35218 goto state_invalid_initial;
35219 }
35220 tv = &thr_resume->valstack_top[-1];
35221 DUK_ASSERT(tv >= thr_resume->valstack && tv < thr_resume->valstack_top);
35222 if (!DUK_TVAL_IS_OBJECT(tv)) {
35223 goto state_invalid_initial;
35224 }
35225 func = DUK_TVAL_GET_OBJECT(tv);
35226 DUK_ASSERT(func != NULL);
35228 /* Note: cannot be a bound function either right now,
35229 * this would be easy to relax though.
35230 */
35231 goto state_invalid_initial;
35232 }
35233
35234 }
35235
35236 /*
35237 * The error object has been augmented with a traceback and other
35238 * info from its creation point -- usually another thread. The
35239 * error handler is called here right before throwing, but it also
35240 * runs in the resumer's thread. It might be nice to get a traceback
35241 * from the resumee but this is not the case now.
35242 */
35243
35244#if defined(DUK_USE_AUGMENT_ERROR_THROW)
35245 if (is_error) {
35246 DUK_ASSERT_TOP(ctx, 2); /* value (error) is at stack top */
35247 duk_err_augment_error_throw(thr); /* in resumer's context */
35248 }
35249#endif
35250
35251#ifdef DUK_USE_DEBUG
35252 if (is_error) {
35253 DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
35254 (duk_tval *) duk_get_tval(ctx, 0),
35255 (duk_tval *) duk_get_tval(ctx, 1)));
35256 } else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
35257 DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
35258 (duk_tval *) duk_get_tval(ctx, 0),
35259 (duk_tval *) duk_get_tval(ctx, 1)));
35260 } else {
35261 DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
35262 (duk_tval *) duk_get_tval(ctx, 0),
35263 (duk_tval *) duk_get_tval(ctx, 1)));
35264 }
35265#endif
35266
35268
35269 /* lj value2: thread */
35271 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]); /* side effects */
35272
35273 /* lj value1: value */
35274 DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
35275 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
35277
35278 thr->heap->lj.iserror = is_error;
35279
35280 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
35281 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
35282 return 0; /* never here */
35283
35284 state_invalid_initial:
35285 DUK_ERROR_TYPE(thr, "invalid initial thread state/stack");
35286 return 0; /* never here */
35287
35288 state_error:
35289 DUK_ERROR_TYPE(thr, "invalid state");
35290 return 0; /* never here */
35292
35293/*
35294 * Yield the current thread.
35295 *
35296 * The thread must be in yieldable state: it must have a resumer, and there
35297 * must not be any yield-preventing calls (native calls and constructor calls,
35298 * currently) in the thread's call stack (otherwise a resume would not be
35299 * possible later). This method must be called from an Ecmascript function.
35300 *
35301 * Args:
35302 * - value
35303 * - isError (defaults to false)
35304 *
35305 * Note: yield and resume handling is currently asymmetric.
35306 */
35307
35309 duk_hthread *thr = (duk_hthread *) ctx;
35310 duk_hobject *caller_func;
35311 duk_small_int_t is_error;
35312
35313 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
35314 (duk_tval *) duk_get_tval(ctx, 0),
35315 (duk_tval *) duk_get_tval(ctx, 1)));
35316
35318 DUK_ASSERT(thr->heap->curr_thread == thr);
35319
35320 is_error = (duk_small_int_t) duk_to_boolean(ctx, 1);
35321 duk_set_top(ctx, 1);
35322
35323 /* [ value ] */
35324
35325 /*
35326 * Thread state and calling context checks
35327 */
35328
35329 if (!thr->resumer) {
35330 DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
35331 goto state_error;
35332 }
35334
35335 if (thr->callstack_top < 2) {
35336 DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
35337 goto state_error;
35338 }
35339 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
35341 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
35342
35343 caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
35344 if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
35345 DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
35346 goto state_error;
35347 }
35348
35349 DUK_ASSERT(thr->callstack_preventcount >= 1); /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
35350 if (thr->callstack_preventcount != 1) {
35351 /* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
35352 DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
35353 (long) thr->callstack_preventcount));
35354 goto state_error;
35355 }
35356
35357 /*
35358 * The error object has been augmented with a traceback and other
35359 * info from its creation point -- usually the current thread.
35360 * The error handler, however, is called right before throwing
35361 * and runs in the yielder's thread.
35362 */
35363
35364#if defined(DUK_USE_AUGMENT_ERROR_THROW)
35365 if (is_error) {
35366 DUK_ASSERT_TOP(ctx, 1); /* value (error) is at stack top */
35367 duk_err_augment_error_throw(thr); /* in yielder's context */
35368 }
35369#endif
35370
35371#ifdef DUK_USE_DEBUG
35372 if (is_error) {
35373 DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
35374 (duk_tval *) duk_get_tval(ctx, 0)));
35375 } else {
35376 DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
35377 (duk_tval *) duk_get_tval(ctx, 0)));
35378 }
35379#endif
35380
35381 /*
35382 * Process yield
35383 *
35384 * After longjmp(), processing continues in bytecode executor longjmp
35385 * handler, which will e.g. update thr->resumer to NULL.
35386 */
35387
35388 thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
35390 /* lj value1: value */
35392 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
35394
35395 thr->heap->lj.iserror = is_error;
35396
35397 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
35398 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
35399 return 0; /* never here */
35400
35401 state_error:
35402 DUK_ERROR_TYPE(thr, "invalid state");
35403 return 0; /* never here */
35404}
35405
35408 return 1;
35409}
35410/*
35411 * Type error thrower, E5 Section 13.2.3.
35412 */
35413
35414/* include removed: duk_internal.h */
35415
35417 DUK_UNREF(ctx);
35418 return DUK_RET_TYPE_ERROR;
35419}
35420/*
35421 * Fixed buffer helper useful for debugging, requires no allocation
35422 * which is critical for debugging.
35423 */
35424
35425/* include removed: duk_internal.h */
35426
35427#ifdef DUK_USE_DEBUG
35428
35429DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
35430 duk_size_t avail;
35431 duk_size_t copylen;
35432
35433 avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
35434 if (length > avail) {
35435 copylen = avail;
35436 fb->truncated = 1;
35437 } else {
35438 copylen = length;
35439 }
35440 DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);
35441 fb->offset += copylen;
35442}
35443
35444DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
35445 duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
35446}
35447
35448DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
35449 duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
35450}
35451
35452DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
35453 duk_size_t avail;
35454 va_list ap;
35455
35456 va_start(ap, fmt);
35457 avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
35458 if (avail > 0) {
35459 duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
35460 if (res < 0) {
35461 /* error */
35462 } else if ((duk_size_t) res >= avail) {
35463 /* (maybe) truncated */
35464 fb->offset += avail;
35465 if ((duk_size_t) res > avail) {
35466 /* actual chars dropped (not just NUL term) */
35467 fb->truncated = 1;
35468 }
35469 } else {
35470 /* normal */
35471 fb->offset += res;
35472 }
35473 }
35474 va_end(ap);
35475}
35476
35477DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
35478 char buf[64+1];
35479 duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
35480 buf[sizeof(buf) - 1] = (char) 0;
35481 duk_fb_put_cstring(fb, buf);
35482}
35483
35484DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
35485 return (fb->offset >= fb->length);
35486}
35487
35488#endif /* DUK_USE_DEBUG */
35489/*
35490 * Debug dumping of duk_heap.
35491 */
35492
35493/* include removed: duk_internal.h */
35494
35495#ifdef DUK_USE_DEBUG
35496
35497#if 0 /*unused*/
35498DUK_LOCAL void duk__sanitize_snippet(char *buf, duk_size_t buf_size, duk_hstring *str) {
35499 duk_size_t i;
35500 duk_size_t nchars;
35501 duk_size_t maxchars;
35502 duk_uint8_t *data;
35503
35504 DUK_MEMZERO(buf, buf_size);
35505
35506 maxchars = (duk_size_t) (buf_size - 1);
35507 data = DUK_HSTRING_GET_DATA(str);
35508 nchars = ((duk_size_t) str->blen < maxchars ? (duk_size_t) str->blen : maxchars);
35509 for (i = 0; i < nchars; i++) {
35510 duk_small_int_t c = (duk_small_int_t) data[i];
35511 if (c < 0x20 || c > 0x7e) {
35512 c = '.';
35513 }
35514 buf[i] = (char) c;
35515 }
35516}
35517#endif
35518
35519#if 0
35520DUK_LOCAL const char *duk__get_heap_type_string(duk_heaphdr *hdr) {
35521 switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
35522 case DUK_HTYPE_STRING:
35523 return "string";
35524 case DUK_HTYPE_OBJECT:
35525 return "object";
35526 case DUK_HTYPE_BUFFER:
35527 return "buffer";
35528 default:
35529 return "???";
35530 }
35531}
35532#endif
35533
35534#if 0
35535DUK_LOCAL void duk__dump_indented(duk_heaphdr *obj, int index) {
35536 DUK_UNREF(obj);
35538 DUK_UNREF(duk__get_heap_type_string);
35539
35540#ifdef DUK_USE_REFERENCE_COUNTING
35541 DUK_D(DUK_DPRINT(" [%ld]: %p %s (flags: 0x%08lx, ref: %ld) -> %!O",
35542 (long) index,
35543 (void *) obj,
35544 (const char *) duk__get_heap_type_string(obj),
35545 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
35546 (long) DUK_HEAPHDR_GET_REFCOUNT(obj),
35547 (duk_heaphdr *) obj));
35548#else
35549 DUK_D(DUK_DPRINT(" [%ld]: %p %s (flags: 0x%08lx) -> %!O",
35550 (long) index,
35551 (void *) obj,
35552 (const char *) duk__get_heap_type_string(obj),
35553 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
35554 (duk_heaphdr *) obj));
35555#endif
35556}
35557#endif
35558
35559#if 0 /*unused*/
35560DUK_LOCAL void duk__dump_heaphdr_list(duk_heap *heap, duk_heaphdr *root, const char *name) {
35561 duk_int_t count;
35562 duk_heaphdr *curr;
35563
35564 DUK_UNREF(heap);
35565 DUK_UNREF(name);
35566
35567 count = 0;
35568 curr = root;
35569 while (curr) {
35570 count++;
35571 curr = DUK_HEAPHDR_GET_NEXT(curr);
35572 }
35573
35574 DUK_D(DUK_DPRINT("%s, %ld objects", (const char *) name, (long) count));
35575
35576 count = 0;
35577 curr = root;
35578 while (curr) {
35579 count++;
35580 duk__dump_indented(curr, count);
35581 curr = DUK_HEAPHDR_GET_NEXT(curr);
35582 }
35583}
35584#endif
35585
35586#if 0 /*unused*/
35587DUK_LOCAL void duk__dump_stringtable(duk_heap *heap) {
35589 char buf[64+1];
35590
35591 DUK_D(DUK_DPRINT("stringtable %p, used %ld, size %ld, load %ld%%",
35592 (void *) heap->strtable,
35593 (long) heap->st_used,
35594 (long) heap->st_size,
35595 (long) (((double) heap->st_used) / ((double) heap->st_size) * 100.0)));
35596
35597 for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
35598 duk_hstring *e = heap->strtable[i];
35599
35600 if (!e) {
35601 DUK_D(DUK_DPRINT(" [%ld]: NULL", (long) i));
35602 } else if (e == DUK_STRTAB_DELETED_MARKER(heap)) {
35603 DUK_D(DUK_DPRINT(" [%ld]: DELETED", (long) i));
35604 } else {
35605 duk__sanitize_snippet(buf, sizeof(buf), e);
35606
35607#ifdef DUK_USE_REFERENCE_COUNTING
35608 DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx, ref: %ld) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
35609 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
35610 (long) i,
35611 (void *) e,
35612 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
35614 (const char *) buf,
35615 (unsigned long) e->hash,
35616 (long) e->blen,
35617 (long) e->clen,
35618 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
35619 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
35620 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
35621 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
35622 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
35623#else
35624 DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
35625 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
35626 (long) i,
35627 (void *) e,
35628 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
35629 (const char *) buf,
35630 (long) e->hash,
35631 (long) e->blen,
35632 (long) e->clen,
35633 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
35634 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
35635 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
35636 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
35637 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
35638#endif
35639 }
35640 }
35641}
35642#endif
35643
35644#if 0 /*unused*/
35645DUK_LOCAL void duk__dump_strcache(duk_heap *heap) {
35647 char buf[64+1];
35648
35649 DUK_D(DUK_DPRINT("stringcache"));
35650
35651 for (i = 0; i < (duk_uint_fast32_t) DUK_HEAP_STRCACHE_SIZE; i++) {
35652 duk_strcache *c = &heap->strcache[i];
35653 if (!c->h) {
35654 DUK_D(DUK_DPRINT(" [%ld]: bidx=%ld, cidx=%ld, str=NULL",
35655 (long) i, (long) c->bidx, (long) c->cidx));
35656 } else {
35657 duk__sanitize_snippet(buf, sizeof(buf), c->h);
35658 DUK_D(DUK_DPRINT(" [%ld]: bidx=%ld cidx=%ld str=%s",
35659 (long) i, (long) c->bidx, (long) c->cidx, (const char *) buf));
35660 }
35661 }
35662}
35663#endif
35664
35665#if 0 /*unused*/
35666DUK_INTERNAL void duk_debug_dump_heap(duk_heap *heap) {
35667 char buf[64+1];
35668
35669 DUK_D(DUK_DPRINT("=== heap %p ===", (void *) heap));
35670 DUK_D(DUK_DPRINT(" flags: 0x%08lx", (unsigned long) heap->flags));
35671
35672 /* Note: there is no standard formatter for function pointers */
35673#ifdef DUK_USE_GCC_PRAGMAS
35674#pragma GCC diagnostic push
35675#pragma GCC diagnostic ignored "-pedantic"
35676#endif
35677 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->alloc_func, sizeof(heap->alloc_func));
35678 DUK_D(DUK_DPRINT(" alloc_func: %s", (const char *) buf));
35679 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->realloc_func, sizeof(heap->realloc_func));
35680 DUK_D(DUK_DPRINT(" realloc_func: %s", (const char *) buf));
35681 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->free_func, sizeof(heap->free_func));
35682 DUK_D(DUK_DPRINT(" free_func: %s", (const char *) buf));
35683 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->fatal_func, sizeof(heap->fatal_func));
35684 DUK_D(DUK_DPRINT(" fatal_func: %s", (const char *) buf));
35685#ifdef DUK_USE_GCC_PRAGMAS
35686#pragma GCC diagnostic pop
35687#endif
35688
35689 DUK_D(DUK_DPRINT(" heap_udata: %p", (void *) heap->heap_udata));
35690
35691#ifdef DUK_USE_MARK_AND_SWEEP
35692#ifdef DUK_USE_VOLUNTARY_GC
35693 DUK_D(DUK_DPRINT(" mark-and-sweep trig counter: %ld", (long) heap->mark_and_sweep_trigger_counter));
35694#endif
35695 DUK_D(DUK_DPRINT(" mark-and-sweep rec depth: %ld", (long) heap->mark_and_sweep_recursion_depth));
35696 DUK_D(DUK_DPRINT(" mark-and-sweep base flags: 0x%08lx", (unsigned long) heap->mark_and_sweep_base_flags));
35697#endif
35698
35699 DUK_D(DUK_DPRINT(" lj.jmpbuf_ptr: %p", (void *) heap->lj.jmpbuf_ptr));
35700 DUK_D(DUK_DPRINT(" lj.type: %ld", (long) heap->lj.type));
35701 DUK_D(DUK_DPRINT(" lj.value1: %!T", (duk_tval *) &heap->lj.value1));
35702 DUK_D(DUK_DPRINT(" lj.value2: %!T", (duk_tval *) &heap->lj.value2));
35703 DUK_D(DUK_DPRINT(" lj.iserror: %ld", (long) heap->lj.iserror));
35704
35705 DUK_D(DUK_DPRINT(" handling_error: %ld", (long) heap->handling_error));
35706
35707 DUK_D(DUK_DPRINT(" heap_thread: %!@O", (duk_heaphdr *) heap->heap_thread));
35708 DUK_D(DUK_DPRINT(" curr_thread: %!@O", (duk_heaphdr *) heap->curr_thread));
35709 DUK_D(DUK_DPRINT(" heap_object: %!@O", (duk_heaphdr *) heap->heap_object));
35710
35711 DUK_D(DUK_DPRINT(" call_recursion_depth: %ld", (long) heap->call_recursion_depth));
35712 DUK_D(DUK_DPRINT(" call_recursion_limit: %ld", (long) heap->call_recursion_limit));
35713
35714 DUK_D(DUK_DPRINT(" hash_seed: 0x%08lx", (unsigned long) heap->hash_seed));
35715 DUK_D(DUK_DPRINT(" rnd_state: 0x%08lx", (unsigned long) heap->rnd_state));
35716
35717 duk__dump_strcache(heap);
35718
35719 duk__dump_heaphdr_list(heap, heap->heap_allocated, "heap allocated");
35720
35721#ifdef DUK_USE_REFERENCE_COUNTING
35722 duk__dump_heaphdr_list(heap, heap->refzero_list, "refcounting refzero list");
35723#endif
35724
35725#ifdef DUK_USE_MARK_AND_SWEEP
35726 duk__dump_heaphdr_list(heap, heap->finalize_list, "mark-and-sweep finalize list");
35727#endif
35728
35729 duk__dump_stringtable(heap);
35730
35731 /* heap->strs: not worth dumping */
35732}
35733#endif
35734
35735#endif /* DUK_USE_DEBUG */
35736/*
35737 * Custom formatter for debug printing, allowing Duktape specific data
35738 * structures (such as tagged values and heap objects) to be printed with
35739 * a nice format string. Because debug printing should not affect execution
35740 * state, formatting here must be independent of execution (see implications
35741 * below) and must not allocate memory.
35742 *
35743 * Custom format tags begin with a '%!' to safely distinguish them from
35744 * standard format tags. The following conversions are supported:
35745 *
35746 * %!T tagged value (duk_tval *)
35747 * %!O heap object (duk_heaphdr *)
35748 * %!I decoded bytecode instruction
35749 * %!C bytecode instruction opcode name (arg is long)
35750 *
35751 * Everything is serialized in a JSON-like manner. The default depth is one
35752 * level, internal prototype is not followed, and internal properties are not
35753 * serialized. The following modifiers change this behavior:
35754 *
35755 * @ print pointers
35756 * # print binary representations (where applicable)
35757 * d deep traversal of own properties (not prototype)
35758 * p follow prototype chain (useless without 'd')
35759 * i include internal properties (other than prototype)
35760 * x hexdump buffers
35761 * h heavy formatting
35762 *
35763 * For instance, the following serializes objects recursively, but does not
35764 * follow the prototype chain nor print internal properties: "%!dO".
35765 *
35766 * Notes:
35767 *
35768 * * Standard snprintf return value semantics seem to vary. This
35769 * implementation returns the number of bytes it actually wrote
35770 * (excluding the null terminator). If retval == buffer size,
35771 * output was truncated (except for corner cases).
35772 *
35773 * * Output format is intentionally different from Ecmascript
35774 * formatting requirements, as formatting here serves debugging
35775 * of internals.
35776 *
35777 * * Depth checking (and updating) is done in each type printer
35778 * separately, to allow them to call each other freely.
35779 *
35780 * * Some pathological structures might take ages to print (e.g.
35781 * self recursion with 100 properties pointing to the object
35782 * itself). To guard against these, each printer also checks
35783 * whether the output buffer is full; if so, early exit.
35784 *
35785 * * Reference loops are detected using a loop stack.
35786 */
35787
35788/* include removed: duk_internal.h */
35789
35790#ifdef DUK_USE_DEBUG
35791
35792#include <stdio.h>
35793#include <stdarg.h>
35794#include <string.h>
35795
35796/* list of conversion specifiers that terminate a format tag;
35797 * this is unfortunately guesswork.
35798 */
35799#define DUK__ALLOWED_STANDARD_SPECIFIERS "diouxXeEfFgGaAcsCSpnm"
35800
35801/* maximum length of standard format tag that we support */
35802#define DUK__MAX_FORMAT_TAG_LENGTH 32
35803
35804/* heapobj recursion depth when deep printing is selected */
35805#define DUK__DEEP_DEPTH_LIMIT 8
35806
35807/* maximum recursion depth for loop detection stacks */
35808#define DUK__LOOP_STACK_DEPTH 256
35809
35810/* must match bytecode defines now; build autogenerate? */
35811DUK_LOCAL const char *duk__bc_optab[64] = {
35812 "LDREG", "STREG", "LDCONST", "LDINT", "LDINTX", "MPUTOBJ", "MPUTOBJI", "MPUTARR", "MPUTARRI", "NEW",
35813 "NEWI", "REGEXP", "CSREG", "CSREGI", "GETVAR", "PUTVAR", "DECLVAR", "DELVAR", "CSVAR", "CSVARI",
35814 "CLOSURE", "GETPROP", "PUTPROP", "DELPROP", "CSPROP", "CSPROPI", "ADD", "SUB", "MUL", "DIV",
35815 "MOD", "BAND", "BOR", "BXOR", "BASL", "BLSR", "BASR", "EQ", "NEQ", "SEQ",
35816 "SNEQ", "GT", "GE", "LT", "LE", "IF", "JUMP", "RETURN", "CALL", "CALLI",
35817 "TRYCATCH", "EXTRA", "PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
35818 "PREINCP", "PREDECP", "POSTINCP", "POSTDECP"
35819};
35820
35821DUK_LOCAL const char *duk__bc_extraoptab[256] = {
35822 "NOP", "INVALID", "LDTHIS", "LDUNDEF", "LDNULL", "LDTRUE", "LDFALSE", "NEWOBJ", "NEWARR", "SETALEN",
35823 "TYPEOF", "TYPEOFID", "INITENUM", "NEXTENUM", "INITSET", "INITSETI", "INITGET", "INITGETI", "ENDTRY", "ENDCATCH",
35824 "ENDFIN", "THROW", "INVLHS", "UNM", "UNP", "DEBUGGER", "BREAK", "CONTINUE", "BNOT", "LNOT",
35825 "INSTOF", "IN", "LABEL", "ENDLABEL", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35826 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35827
35828 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35829 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35830 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35831 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35832 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35833
35834 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35835 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35836 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35837 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35838 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35839
35840 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35841 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35842 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35843 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35844 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35845
35846 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35847 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35848 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35849 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35850 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35851
35852 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX"
35853};
35854
35855typedef struct duk__dprint_state duk__dprint_state;
35856struct duk__dprint_state {
35857 duk_fixedbuffer *fb;
35858
35859 /* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
35860 * to not couple these two mechanisms unnecessarily.
35861 */
35862 duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
35863 duk_int_t loop_stack_index;
35864 duk_int_t loop_stack_limit;
35865
35867 duk_int_t depth_limit;
35868
35869 duk_bool_t pointer;
35870 duk_bool_t heavy;
35871 duk_bool_t binary;
35872 duk_bool_t follow_proto;
35873 duk_bool_t internal;
35874 duk_bool_t hexdump;
35875};
35876
35877/* helpers */
35878DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
35879DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
35880DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
35881DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
35882DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
35883DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
35884DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
35885DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
35886
35887DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
35888 duk_fixedbuffer *fb = st->fb;
35889
35890 if (st->heavy) {
35891 duk_fb_sprintf(fb, "(%p)", (void *) h);
35892 }
35893
35894 if (!h) {
35895 return;
35896 }
35897
35898 if (st->binary) {
35899 duk_size_t i;
35900 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
35901 for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
35902 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
35903 }
35904 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
35905 }
35906
35907#ifdef DUK_USE_REFERENCE_COUNTING /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
35908 if (st->heavy) {
35909 duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
35910 "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
35911 (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
35912 (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
35913 (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
35914 (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
35915 (long) DUK_HEAPHDR_GET_TYPE(h),
35916 (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
35917 (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
35918 (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
35919 (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
35920 }
35921#else
35922 if (st->heavy) {
35923 duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
35924 (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
35925 (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
35926 (long) DUK_HEAPHDR_GET_TYPE(h),
35927 (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
35928 (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
35929 (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
35930 (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
35931 }
35932#endif
35933}
35934
35935DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
35936 duk_fixedbuffer *fb = st->fb;
35937
35938 if (st->heavy) {
35939 duk_fb_sprintf(fb, "(%p)", (void *) h);
35940 }
35941
35942 if (!h) {
35943 return;
35944 }
35945
35946 if (st->binary) {
35947 duk_size_t i;
35948 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
35949 for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
35950 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
35951 }
35952 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
35953 }
35954
35955#ifdef DUK_USE_REFERENCE_COUNTING
35956 if (st->heavy) {
35957 duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
35958 (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
35959 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
35960 (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
35961 (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
35962 (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
35963 (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
35964 (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
35965 }
35966#else
35967 if (st->heavy) {
35968 duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
35969 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
35970 (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
35971 (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
35972 (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
35973 (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
35974 (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
35975 }
35976#endif
35977}
35978
35979DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
35980 duk_fixedbuffer *fb = st->fb;
35981 const duk_uint8_t *p;
35982 const duk_uint8_t *p_end;
35983
35984 /* terminal type: no depth check */
35985
35986 if (duk_fb_is_full(fb)) {
35987 return;
35988 }
35989
35990 duk__print_shared_heaphdr_string(st, &h->hdr);
35991
35992 if (!h) {
35993 duk_fb_put_cstring(fb, "NULL");
35994 return;
35995 }
35996
35997 p = DUK_HSTRING_GET_DATA(h);
35998 p_end = p + DUK_HSTRING_GET_BYTELEN(h);
35999
36000 if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
36001 /* if property key begins with underscore, encode it with
36002 * forced quotes (e.g. "_Foo") to distinguish it from encoded
36003 * internal properties (e.g. \xffBar -> _Bar).
36004 */
36005 quotes = 1;
36006 }
36007
36008 if (quotes) {
36009 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
36010 }
36011 while (p < p_end) {
36012 duk_uint8_t ch = *p++;
36013
36014 /* two special escapes: '\' and '"', other printables as is */
36015 if (ch == '\\') {
36016 duk_fb_sprintf(fb, "\\\\");
36017 } else if (ch == '"') {
36018 duk_fb_sprintf(fb, "\\\"");
36019 } else if (ch >= 0x20 && ch <= 0x7e) {
36020 duk_fb_put_byte(fb, ch);
36021 } else if (ch == 0xff && !quotes) {
36022 /* encode \xffBar as _Bar if no quotes are applied, this is for
36023 * readable internal keys.
36024 */
36025 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
36026 } else {
36027 duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
36028 }
36029 }
36030 if (quotes) {
36031 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
36032 }
36033#ifdef DUK_USE_REFERENCE_COUNTING
36034 /* XXX: limit to quoted strings only, to save keys from being cluttered? */
36035 duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
36036#endif
36037}
36038
36039#ifdef DUK__COMMA
36040#undef DUK__COMMA
36041#endif
36042#define DUK__COMMA() do { \
36043 if (first) { \
36044 first = 0; \
36045 } else { \
36046 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
36047 } \
36048 } while (0)
36049
36050DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
36051 duk_fixedbuffer *fb = st->fb;
36053 duk_tval *tv;
36054 duk_hstring *key;
36055 duk_bool_t first = 1;
36056 const char *brace1 = "{";
36057 const char *brace2 = "}";
36058 duk_bool_t pushed_loopstack = 0;
36059
36060 if (duk_fb_is_full(fb)) {
36061 return;
36062 }
36063
36064 duk__print_shared_heaphdr(st, &h->hdr);
36065
36066 if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
36067 brace1 = "[";
36068 brace2 = "]";
36069 }
36070
36071 if (!h) {
36072 duk_fb_put_cstring(fb, "NULL");
36073 goto finished;
36074 }
36075
36076 if (st->depth >= st->depth_limit) {
36078 duk_fb_sprintf(fb, "%sobject/compiledfunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36079 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
36080 duk_fb_sprintf(fb, "%sobject/nativefunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36081 } else if (DUK_HOBJECT_IS_THREAD(h)) {
36082 duk_fb_sprintf(fb, "%sobject/thread %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36083 } else {
36084 duk_fb_sprintf(fb, "%sobject %p%s", (const char *) brace1, (void *) h, (const char *) brace2); /* may be NULL */
36085 }
36086 return;
36087 }
36088
36089 for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
36090 if (st->loop_stack[i] == h) {
36091 duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36092 return;
36093 }
36094 }
36095
36096 /* after this, return paths should 'goto finished' for decrement */
36097 st->depth++;
36098
36099 if (st->loop_stack_index >= st->loop_stack_limit) {
36100 duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
36101 goto finished;
36102 }
36103 st->loop_stack[st->loop_stack_index++] = h;
36104 pushed_loopstack = 1;
36105
36106 /*
36107 * Notation: double underscore used for internal properties which are not
36108 * stored in the property allocation (e.g. '__valstack').
36109 */
36110
36111 duk_fb_put_cstring(fb, brace1);
36112
36113 if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
36114 duk_uint32_t a_limit;
36115
36116 a_limit = DUK_HOBJECT_GET_ASIZE(h);
36117 if (st->internal) {
36118 /* dump all allocated entries, unused entries print as 'unused',
36119 * note that these may extend beyond current 'length' and look
36120 * a bit funny.
36121 */
36122 } else {
36123 /* leave out trailing 'unused' elements */
36124 while (a_limit > 0) {
36125 tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
36126 if (!DUK_TVAL_IS_UNUSED(tv)) {
36127 break;
36128 }
36129 a_limit--;
36130 }
36131 }
36132
36133 for (i = 0; i < a_limit; i++) {
36135 DUK__COMMA();
36136 duk__print_tval(st, tv);
36137 }
36138 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
36139 key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
36140 if (!key) {
36141 continue;
36142 }
36143 if (!st->internal &&
36144 DUK_HSTRING_GET_BYTELEN(key) > 0 &&
36145 DUK_HSTRING_GET_DATA(key)[0] == 0xff) {
36146 /* XXX: use DUK_HSTRING_FLAG_INTERNAL? */
36147 continue;
36148 }
36149 DUK__COMMA();
36150 duk__print_hstring(st, key, 0);
36151 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
36153 duk_fb_sprintf(fb, "[get:%p,set:%p]",
36154 (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
36155 (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
36156 } else {
36157 tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
36158 duk__print_tval(st, tv);
36159 }
36160 if (st->heavy) {
36161 duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
36162 }
36163 }
36164 }
36165 if (st->internal) {
36167 DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
36168 } else {
36169 ;
36170 }
36172 DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
36173 } else {
36174 ;
36175 }
36176 if (DUK_HOBJECT_HAS_BOUND(h)) {
36177 DUK__COMMA(); duk_fb_sprintf(fb, "__bound:true");
36178 } else {
36179 ;
36180 }
36182 DUK__COMMA(); duk_fb_sprintf(fb, "__compiledfunction:true");
36183 } else {
36184 ;
36185 }
36187 DUK__COMMA(); duk_fb_sprintf(fb, "__nativefunction:true");
36188 } else {
36189 ;
36190 }
36191 if (DUK_HOBJECT_HAS_THREAD(h)) {
36192 DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
36193 } else {
36194 ;
36195 }
36197 DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
36198 } else {
36199 ;
36200 }
36201 if (DUK_HOBJECT_HAS_STRICT(h)) {
36202 DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
36203 } else {
36204 ;
36205 }
36206 if (DUK_HOBJECT_HAS_NEWENV(h)) {
36207 DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
36208 } else {
36209 ;
36210 }
36212 DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
36213 } else {
36214 ;
36215 }
36217 DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
36218 } else {
36219 ;
36220 }
36222 DUK__COMMA(); duk_fb_sprintf(fb, "__envrecclosed:true");
36223 } else {
36224 ;
36225 }
36227 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
36228 } else {
36229 ;
36230 }
36232 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
36233 } else {
36234 ;
36235 }
36237 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
36238 } else {
36239 ;
36240 }
36242 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_dukfunc:true");
36243 } else {
36244 ;
36245 }
36247 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufferobj:true");
36248 } else {
36249 ;
36250 }
36252 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
36253 } else {
36254 ;
36255 }
36256 }
36257 if (st->internal && DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
36259 DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
36260 duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
36261 DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
36262 DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
36263#if defined(DUK_USE_DEBUGGER_SUPPORT)
36264 DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
36265 DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
36266#endif
36267 DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
36268 duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
36269 } else if (st->internal && DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
36271 DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
36272 duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
36273 DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
36274 DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
36275 } else if (st->internal && DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
36277 DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
36278 duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
36279 DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
36280 DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
36281 DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
36282 DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
36283 } else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
36284 duk_hthread *t = (duk_hthread *) h;
36285 DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
36286 DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
36287 DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
36288 DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
36289 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_max:%ld", (long) t->valstack_max);
36290 DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_max:%ld", (long) t->callstack_max);
36291 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_max:%ld", (long) t->catchstack_max);
36292 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
36293 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
36294 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
36295 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
36296 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack:%p", (void *) t->catchstack);
36297 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_size:%ld", (long) t->catchstack_size);
36298 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_top:%ld", (long) t->catchstack_top);
36299 DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
36300 /* XXX: print built-ins array? */
36301
36302 }
36303#ifdef DUK_USE_REFERENCE_COUNTING
36304 if (st->internal) {
36305 DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
36306 }
36307#endif
36308 if (st->internal) {
36309 DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
36310 }
36311
36312 DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h); /* own pointer */
36313
36314 /* prototype should be last, for readability */
36316 if (st->follow_proto) {
36317 DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
36318 } else {
36319 DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
36320 }
36321 }
36322
36323 duk_fb_put_cstring(fb, brace2);
36324
36325#if defined(DUK_USE_HOBJECT_HASH_PART)
36326 if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
36327 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
36328 for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
36330 if (i > 0) {
36331 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
36332 }
36333 if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
36334 duk_fb_sprintf(fb, "u");
36335 } else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
36336 duk_fb_sprintf(fb, "d");
36337 } else {
36338 duk_fb_sprintf(fb, "%ld", (long) h_idx);
36339 }
36340 }
36341 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
36342 }
36343#endif
36344
36345 finished:
36346 st->depth--;
36347 if (pushed_loopstack) {
36348 st->loop_stack_index--;
36349 st->loop_stack[st->loop_stack_index] = NULL;
36350 }
36351}
36352
36353#undef DUK__COMMA
36354
36355DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
36356 duk_fixedbuffer *fb = st->fb;
36357 duk_size_t i, n;
36358 duk_uint8_t *p;
36359
36360 if (duk_fb_is_full(fb)) {
36361 return;
36362 }
36363
36364 /* terminal type: no depth check */
36365
36366 if (!h) {
36367 duk_fb_put_cstring(fb, "NULL");
36368 return;
36369 }
36370
36371 if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
36372 if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
36374 duk_fb_sprintf(fb, "buffer:external:%p:%ld",
36377 } else {
36379 duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
36382 }
36383 } else {
36384 duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
36385 }
36386
36387#ifdef DUK_USE_REFERENCE_COUNTING
36388 duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
36389#endif
36390
36391 if (st->hexdump) {
36392 duk_fb_sprintf(fb, "=[");
36393 n = DUK_HBUFFER_GET_SIZE(h);
36394 p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
36395 for (i = 0; i < n; i++) {
36396 duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
36397 }
36398 duk_fb_sprintf(fb, "]");
36399 }
36400}
36401
36402DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
36403 duk_fixedbuffer *fb = st->fb;
36404
36405 if (duk_fb_is_full(fb)) {
36406 return;
36407 }
36408
36409 if (!h) {
36410 duk_fb_put_cstring(fb, "NULL");
36411 return;
36412 }
36413
36414 switch (DUK_HEAPHDR_GET_TYPE(h)) {
36415 case DUK_HTYPE_STRING:
36416 duk__print_hstring(st, (duk_hstring *) h, 1);
36417 break;
36418 case DUK_HTYPE_OBJECT:
36419 duk__print_hobject(st, (duk_hobject *) h);
36420 break;
36421 case DUK_HTYPE_BUFFER:
36422 duk__print_hbuffer(st, (duk_hbuffer *) h);
36423 break;
36424 default:
36425 duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
36426 break;
36427 }
36428}
36429
36430DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
36431 duk_fixedbuffer *fb = st->fb;
36432
36433 if (duk_fb_is_full(fb)) {
36434 return;
36435 }
36436
36437 /* depth check is done when printing an actual type */
36438
36439 if (st->heavy) {
36440 duk_fb_sprintf(fb, "(%p)", (void *) tv);
36441 }
36442
36443 if (!tv) {
36444 duk_fb_put_cstring(fb, "NULL");
36445 return;
36446 }
36447
36448 if (st->binary) {
36449 duk_size_t i;
36450 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
36451 for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
36452 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
36453 }
36454 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
36455 }
36456
36457 if (st->heavy) {
36458 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
36459 }
36460 switch (DUK_TVAL_GET_TAG(tv)) {
36461 case DUK_TAG_UNDEFINED: {
36462 duk_fb_put_cstring(fb, "undefined");
36463 break;
36464 }
36465 case DUK_TAG_UNUSED: {
36466 duk_fb_put_cstring(fb, "unused");
36467 break;
36468 }
36469 case DUK_TAG_NULL: {
36470 duk_fb_put_cstring(fb, "null");
36471 break;
36472 }
36473 case DUK_TAG_BOOLEAN: {
36474 duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
36475 break;
36476 }
36477 case DUK_TAG_STRING: {
36478 /* Note: string is a terminal heap object, so no depth check here */
36479 duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
36480 break;
36481 }
36482 case DUK_TAG_OBJECT: {
36483 duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
36484 break;
36485 }
36486 case DUK_TAG_BUFFER: {
36487 duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
36488 break;
36489 }
36490 case DUK_TAG_POINTER: {
36491 duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
36492 break;
36493 }
36494 case DUK_TAG_LIGHTFUNC: {
36495 duk_c_function func;
36496 duk_small_uint_t lf_flags;
36497
36498 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
36499 duk_fb_sprintf(fb, "lightfunc:");
36500 duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
36501 duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
36502 break;
36503 }
36504#if defined(DUK_USE_FASTINT)
36505 case DUK_TAG_FASTINT:
36506#endif
36507 default: {
36508 /* IEEE double is approximately 16 decimal digits; print a couple extra */
36511 duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
36512 break;
36513 }
36514 }
36515 if (st->heavy) {
36516 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
36517 }
36518}
36519
36520DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
36521 duk_fixedbuffer *fb = st->fb;
36522 duk_small_int_t op;
36523 const char *op_name;
36524 const char *extraop_name;
36525
36526 op = (duk_small_int_t) DUK_DEC_OP(ins);
36527 op_name = duk__bc_optab[op];
36528
36529 /* XXX: option to fix opcode length so it lines up nicely */
36530
36531 if (op == DUK_OP_EXTRA) {
36532 extraop_name = duk__bc_extraoptab[DUK_DEC_A(ins)];
36533
36534 duk_fb_sprintf(fb, "%s %ld, %ld",
36535 (const char *) extraop_name, (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
36536 } else if (op == DUK_OP_JUMP) {
36537 duk_int_t diff1 = DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS; /* from next pc */
36538 duk_int_t diff2 = diff1 + 1; /* from curr pc */
36539
36540 duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
36541 (const char *) op_name, (long) diff1,
36542 (int) (diff2 >= 0 ? '+' : '-'), /* char format: use int */
36543 (long) (diff2 >= 0 ? diff2 : -diff2));
36544 } else {
36545 duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
36546 (const char *) op_name, (long) DUK_DEC_A(ins),
36547 (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
36548 }
36549}
36550
36551DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
36552 duk_fixedbuffer *fb = st->fb;
36553
36554 if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
36555 duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
36556 } else {
36557 duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
36558 }
36559}
36560
36561DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
36562 duk_fixedbuffer fb;
36563 const char *p = format;
36564 const char *p_end = p + DUK_STRLEN(format);
36565 duk_int_t retval;
36566
36567 DUK_MEMZERO(&fb, sizeof(fb));
36568 fb.buffer = (duk_uint8_t *) str;
36569 fb.length = size;
36570 fb.offset = 0;
36571 fb.truncated = 0;
36572
36573 while (p < p_end) {
36574 char ch = *p++;
36575 const char *p_begfmt = NULL;
36576 duk_bool_t got_exclamation = 0;
36577 duk_bool_t got_long = 0; /* %lf, %ld etc */
36578 duk__dprint_state st;
36579
36580 if (ch != DUK_ASC_PERCENT) {
36581 duk_fb_put_byte(&fb, (duk_uint8_t) ch);
36582 continue;
36583 }
36584
36585 /*
36586 * Format tag parsing. Since we don't understand all the
36587 * possible format tags allowed, we just scan for a terminating
36588 * specifier and keep track of relevant modifiers that we do
36589 * understand. See man 3 printf.
36590 */
36591
36592 DUK_MEMZERO(&st, sizeof(st));
36593 st.fb = &fb;
36594 st.depth = 0;
36595 st.depth_limit = 1;
36596 st.loop_stack_index = 0;
36597 st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
36598
36599 p_begfmt = p - 1;
36600 while (p < p_end) {
36601 ch = *p++;
36602
36603 if (ch == DUK_ASC_STAR) {
36604 /* unsupported: would consume multiple args */
36605 goto error;
36606 } else if (ch == DUK_ASC_PERCENT) {
36607 duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
36608 break;
36609 } else if (ch == DUK_ASC_EXCLAMATION) {
36610 got_exclamation = 1;
36611 } else if (!got_exclamation && ch == DUK_ASC_LC_L) {
36612 got_long = 1;
36613 } else if (got_exclamation && ch == DUK_ASC_LC_D) {
36614 st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
36615 } else if (got_exclamation && ch == DUK_ASC_LC_P) {
36616 st.follow_proto = 1;
36617 } else if (got_exclamation && ch == DUK_ASC_LC_I) {
36618 st.internal = 1;
36619 } else if (got_exclamation && ch == DUK_ASC_LC_X) {
36620 st.hexdump = 1;
36621 } else if (got_exclamation && ch == DUK_ASC_LC_H) {
36622 st.heavy = 1;
36623 } else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
36624 st.pointer = 1;
36625 } else if (got_exclamation && ch == DUK_ASC_HASH) {
36626 st.binary = 1;
36627 } else if (got_exclamation && ch == DUK_ASC_UC_T) {
36628 duk_tval *t = va_arg(ap, duk_tval *);
36629 if (st.pointer && !st.heavy) {
36630 duk_fb_sprintf(&fb, "(%p)", (void *) t);
36631 }
36632 duk__print_tval(&st, t);
36633 break;
36634 } else if (got_exclamation && ch == DUK_ASC_UC_O) {
36635 duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
36636 if (st.pointer && !st.heavy) {
36637 duk_fb_sprintf(&fb, "(%p)", (void *) t);
36638 }
36639 duk__print_heaphdr(&st, t);
36640 break;
36641 } else if (got_exclamation && ch == DUK_ASC_UC_I) {
36642 duk_instr_t t = va_arg(ap, duk_instr_t);
36643 duk__print_instr(&st, t);
36644 break;
36645 } else if (got_exclamation && ch == DUK_ASC_UC_C) {
36646 long t = va_arg(ap, long);
36647 duk__print_opcode(&st, (duk_small_int_t) t);
36648 break;
36649 } else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
36650 char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
36651 duk_size_t fmtlen;
36652
36653 DUK_ASSERT(p >= p_begfmt);
36654 fmtlen = (duk_size_t) (p - p_begfmt);
36655 if (fmtlen >= sizeof(fmtbuf)) {
36656 /* format is too large, abort */
36657 goto error;
36658 }
36659 DUK_MEMZERO(fmtbuf, sizeof(fmtbuf));
36660 DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);
36661
36662 /* assume exactly 1 arg, which is why '*' is forbidden; arg size still
36663 * depends on type though.
36664 */
36665
36666 if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
36667 /* %f and %lf both consume a 'long' */
36668 double arg = va_arg(ap, double);
36669 duk_fb_sprintf(&fb, fmtbuf, arg);
36670 } else if (ch == DUK_ASC_LC_D && got_long) {
36671 /* %ld */
36672 long arg = va_arg(ap, long);
36673 duk_fb_sprintf(&fb, fmtbuf, arg);
36674 } else if (ch == DUK_ASC_LC_D) {
36675 /* %d; only 16 bits are guaranteed */
36676 int arg = va_arg(ap, int);
36677 duk_fb_sprintf(&fb, fmtbuf, arg);
36678 } else if (ch == DUK_ASC_LC_U && got_long) {
36679 /* %lu */
36680 unsigned long arg = va_arg(ap, unsigned long);
36681 duk_fb_sprintf(&fb, fmtbuf, arg);
36682 } else if (ch == DUK_ASC_LC_U) {
36683 /* %u; only 16 bits are guaranteed */
36684 unsigned int arg = va_arg(ap, unsigned int);
36685 duk_fb_sprintf(&fb, fmtbuf, arg);
36686 } else if (ch == DUK_ASC_LC_X && got_long) {
36687 /* %lx */
36688 unsigned long arg = va_arg(ap, unsigned long);
36689 duk_fb_sprintf(&fb, fmtbuf, arg);
36690 } else if (ch == DUK_ASC_LC_X) {
36691 /* %x; only 16 bits are guaranteed */
36692 unsigned int arg = va_arg(ap, unsigned int);
36693 duk_fb_sprintf(&fb, fmtbuf, arg);
36694 } else if (ch == DUK_ASC_LC_S) {
36695 /* %s */
36696 const char *arg = va_arg(ap, const char *);
36697 if (arg == NULL) {
36698 /* '%s' and NULL is not portable, so special case
36699 * it for debug printing.
36700 */
36701 duk_fb_sprintf(&fb, "NULL");
36702 } else {
36703 duk_fb_sprintf(&fb, fmtbuf, arg);
36704 }
36705 } else if (ch == DUK_ASC_LC_P) {
36706 /* %p */
36707 void *arg = va_arg(ap, void *);
36708 if (arg == NULL) {
36709 /* '%p' and NULL is portable, but special case it
36710 * anyway to get a standard NULL marker in logs.
36711 */
36712 duk_fb_sprintf(&fb, "NULL");
36713 } else {
36714 duk_fb_sprintf(&fb, fmtbuf, arg);
36715 }
36716 } else if (ch == DUK_ASC_LC_C) {
36717 /* '%c', passed concretely as int */
36718 int arg = va_arg(ap, int);
36719 duk_fb_sprintf(&fb, fmtbuf, arg);
36720 } else {
36721 /* Should not happen. */
36722 duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
36723 }
36724 break;
36725 } else {
36726 /* ignore */
36727 }
36728 }
36729 }
36730 goto done;
36731
36732 error:
36733 duk_fb_put_cstring(&fb, "FMTERR");
36734 /* fall through */
36735
36736 done:
36737 retval = (duk_int_t) fb.offset;
36738 duk_fb_put_byte(&fb, (duk_uint8_t) 0);
36739
36740 /* return total chars written excluding terminator */
36741 return retval;
36742}
36743
36744#if 0 /*unused*/
36745DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
36746 duk_int_t retval;
36747 va_list ap;
36748 va_start(ap, format);
36749 retval = duk_debug_vsnprintf(str, size, format, ap);
36750 va_end(ap);
36751 return retval;
36752}
36753#endif
36754
36755/* Formatting function pointers is tricky: there is no standard pointer for
36756 * function pointers and the size of a function pointer may depend on the
36757 * specific pointer type. This helper formats a function pointer based on
36758 * its memory layout to get something useful on most platforms.
36759 */
36760DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
36761 duk_size_t i;
36762 duk_uint8_t *p = (duk_uint8_t *) buf;
36763 duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
36764
36765 DUK_MEMZERO(buf, buf_size);
36766
36767 for (i = 0; i < fptr_size; i++) {
36768 duk_int_t left = (duk_int_t) (p_end - p);
36769 duk_uint8_t ch;
36770 if (left <= 0) {
36771 break;
36772 }
36773
36774 /* Quite approximate but should be useful for little and big endian. */
36775#ifdef DUK_USE_INTEGER_BE
36776 ch = fptr[i];
36777#else
36778 ch = fptr[fptr_size - 1 - i];
36779#endif
36780 p += DUK_SNPRINTF((char *) p, left, "%02lx", (unsigned long) ch);
36781 }
36782}
36783
36784#endif /* DUK_USE_DEBUG */
36785/*
36786 * Duktape debugger
36787 */
36788
36789/* include removed: duk_internal.h */
36790
36791#if defined(DUK_USE_DEBUGGER_SUPPORT)
36792
36793/*
36794 * Helper structs
36795 */
36796
36797typedef union {
36798 void *p;
36799 duk_uint_t b[1];
36800 /* Use b[] to access the size of the union, which is strictly not
36801 * correct. Can't use fixed size unless there's feature detection
36802 * for pointer byte size.
36803 */
36804} duk__ptr_union;
36805
36806/*
36807 * Detach handling
36808 */
36809
36810#define DUK__SET_CONN_BROKEN(thr,reason) do { \
36811 /* For now shared handler is fine. */ \
36812 duk__debug_do_detach1((thr)->heap, (reason)); \
36813 } while (0)
36814
36815DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
36816 /* Can be called multiple times with no harm. Mark the transport
36817 * bad (dbg_read_cb == NULL) and clear state except for the detached
36818 * callback and the udata field. The detached callback is delayed
36819 * to the message loop so that it can be called between messages;
36820 * this avoids corner cases related to immediate debugger reattach
36821 * inside the detached callback.
36822 */
36823
36824 if (heap->dbg_detaching) {
36825 DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
36826 return;
36827 }
36828
36829 DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
36830
36831 heap->dbg_detaching = 1; /* prevent multiple in-progress detaches */
36832
36833 if (heap->dbg_write_cb != NULL) {
36834 duk_hthread *thr;
36835
36836 thr = heap->heap_thread;
36837 DUK_ASSERT(thr != NULL);
36838
36839 duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
36840 duk_debug_write_int(thr, reason);
36841 duk_debug_write_eom(thr);
36842 }
36843
36844 heap->dbg_read_cb = NULL;
36845 heap->dbg_write_cb = NULL;
36846 heap->dbg_peek_cb = NULL;
36847 heap->dbg_read_flush_cb = NULL;
36848 heap->dbg_write_flush_cb = NULL;
36849 heap->dbg_request_cb = NULL;
36850 /* heap->dbg_detached_cb: keep */
36851 /* heap->dbg_udata: keep */
36852 /* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
36853 heap->dbg_paused = 0;
36854 heap->dbg_state_dirty = 0;
36855 heap->dbg_force_restart = 0;
36856 heap->dbg_step_type = 0;
36857 heap->dbg_step_thread = NULL;
36858 heap->dbg_step_csindex = 0;
36859 heap->dbg_step_startline = 0;
36860 heap->dbg_have_next_byte = 0;
36861
36862 /* Ensure there are no stale active breakpoint pointers.
36863 * Breakpoint list is currently kept - we could empty it
36864 * here but we'd need to handle refcounts correctly, and
36865 * we'd need a 'thr' reference for that.
36866 *
36867 * XXX: clear breakpoint on either attach or detach?
36868 */
36869 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
36870}
36871
36872DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
36873 duk_debug_detached_function detached_cb;
36874 void *detached_udata;
36875
36876 /* Safe to call multiple times. */
36877
36878 detached_cb = heap->dbg_detached_cb;
36879 detached_udata = heap->dbg_udata;
36880 heap->dbg_detached_cb = NULL;
36881 heap->dbg_udata = NULL;
36882
36883 if (detached_cb) {
36884 /* Careful here: state must be wiped before the call
36885 * so that we can cleanly handle a re-attach from
36886 * inside the callback.
36887 */
36888 DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
36889 detached_cb(detached_udata);
36890 }
36891
36892 heap->dbg_detaching = 0;
36893}
36894
36895DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
36896 duk__debug_do_detach1(heap, 0);
36897 duk__debug_do_detach2(heap);
36898}
36899
36900/* Called on a read/write error: NULL all callbacks except the detached
36901 * callback so that we never accidentally call them after a read/write
36902 * error has been indicated. This is especially important for the transport
36903 * I/O callbacks to fulfill guaranteed callback semantics.
36904 */
36905DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
36906 duk_heap *heap;
36907 heap = thr->heap;
36908 DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
36909 heap->dbg_read_cb = NULL;
36910 heap->dbg_write_cb = NULL; /* this is especially critical to avoid another write call in detach1() */
36911 heap->dbg_peek_cb = NULL;
36912 heap->dbg_read_flush_cb = NULL;
36913 heap->dbg_write_flush_cb = NULL;
36914 heap->dbg_request_cb = NULL;
36915 /* keep heap->dbg_detached_cb */
36916}
36917
36918/*
36919 * Debug connection peek and flush primitives
36920 */
36921
36922DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
36923 duk_heap *heap;
36924
36925 DUK_ASSERT(thr != NULL);
36926 heap = thr->heap;
36927 DUK_ASSERT(heap != NULL);
36928
36929 if (heap->dbg_read_cb == NULL) {
36930 DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
36931 return 0;
36932 }
36933 if (heap->dbg_peek_cb == NULL) {
36934 DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
36935 return 0;
36936 }
36937
36938 return (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
36939}
36940
36941DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
36942 duk_heap *heap;
36943
36944 DUK_ASSERT(thr != NULL);
36945 heap = thr->heap;
36946 DUK_ASSERT(heap != NULL);
36947
36948 if (heap->dbg_read_cb == NULL) {
36949 DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
36950 return;
36951 }
36952 if (heap->dbg_read_flush_cb == NULL) {
36953 DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
36954 return;
36955 }
36956
36957 heap->dbg_read_flush_cb(heap->dbg_udata);
36958}
36959
36960DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
36961 duk_heap *heap;
36962
36963 DUK_ASSERT(thr != NULL);
36964 heap = thr->heap;
36965 DUK_ASSERT(heap != NULL);
36966
36967 if (heap->dbg_read_cb == NULL) {
36968 DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
36969 return;
36970 }
36971 if (heap->dbg_write_flush_cb == NULL) {
36972 DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
36973 return;
36974 }
36975
36976 heap->dbg_write_flush_cb(heap->dbg_udata);
36977}
36978
36979/*
36980 * Debug connection skip primitives
36981 */
36982
36983/* Skip fully. */
36984DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
36985 duk_uint8_t dummy[64];
36986 duk_size_t now;
36987
36988 DUK_ASSERT(thr != NULL);
36989
36990 while (length > 0) {
36991 now = (length > sizeof(dummy) ? sizeof(dummy) : length);
36992 duk_debug_read_bytes(thr, dummy, now);
36993 length -= now;
36994 }
36995}
36996
36997DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
36998 DUK_ASSERT(thr != NULL);
36999
37000 (void) duk_debug_read_byte(thr);
37001}
37002
37003/*
37004 * Debug connection read primitives
37005 */
37006
37007/* Peek ahead in the stream one byte. */
37008DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
37009 /* It is important not to call this if the last byte read was an EOM.
37010 * Reading ahead in this scenario would cause unnecessary blocking if
37011 * another message is not available.
37012 */
37013
37014 duk_uint8_t x;
37015
37016 x = duk_debug_read_byte(thr);
37017 thr->heap->dbg_have_next_byte = 1;
37018 thr->heap->dbg_next_byte = x;
37019 return x;
37020}
37021
37022/* Read fully. */
37023DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
37024 duk_heap *heap;
37025 duk_uint8_t *p;
37027 duk_size_t got;
37028
37029 DUK_ASSERT(thr != NULL);
37030 heap = thr->heap;
37031 DUK_ASSERT(heap != NULL);
37032
37033 if (heap->dbg_read_cb == NULL) {
37034 DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
37035 goto fail;
37036 }
37037
37038 /* NOTE: length may be zero */
37039 p = data;
37040 if (length >= 1 && heap->dbg_have_next_byte) {
37041 heap->dbg_have_next_byte = 0;
37042 *p++ = heap->dbg_next_byte;
37043 }
37044 for (;;) {
37045 left = (duk_size_t) ((data + length) - p);
37046 if (left == 0) {
37047 break;
37048 }
37049 DUK_ASSERT(heap->dbg_read_cb != NULL);
37050 DUK_ASSERT(left >= 1);
37051#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
37052 left = 1;
37053#endif
37054 got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
37055 if (got == 0 || got > left) {
37056 DUK_D(DUK_DPRINT("connection error during read, return zero data"));
37057 duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
37058 DUK__SET_CONN_BROKEN(thr, 1);
37059 goto fail;
37060 }
37061 p += got;
37062 }
37063 return;
37064
37065 fail:
37066 DUK_MEMZERO((void *) data, (size_t) length);
37067}
37068
37069DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
37070 duk_uint8_t x;
37071
37072 x = 0; /* just in case callback is broken and won't write 'x' */
37073 duk_debug_read_bytes(thr, &x, 1);
37074 return x;
37075}
37076
37077DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
37078 duk_uint8_t buf[4];
37079
37080 DUK_ASSERT(thr != NULL);
37081
37082 duk_debug_read_bytes(thr, buf, 4);
37083 return ((duk_uint32_t) buf[0] << 24) |
37084 ((duk_uint32_t) buf[1] << 16) |
37085 ((duk_uint32_t) buf[2] << 8) |
37086 (duk_uint32_t) buf[3];
37087}
37088
37089DUK_LOCAL duk_uint32_t duk__debug_read_int32_raw(duk_hthread *thr) {
37090 return (duk_int32_t) duk__debug_read_uint32_raw(thr);
37091}
37092
37093DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
37094 duk_uint8_t buf[2];
37095
37096 DUK_ASSERT(thr != NULL);
37097
37098 duk_debug_read_bytes(thr, buf, 2);
37099 return ((duk_uint16_t) buf[0] << 8) |
37100 (duk_uint16_t) buf[1];
37101}
37102
37103DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
37106
37107 DUK_ASSERT(thr != NULL);
37108
37109 x = duk_debug_read_byte(thr);
37110 if (x >= 0xc0) {
37111 t = duk_debug_read_byte(thr);
37112 return (duk_int32_t) (((x - 0xc0) << 8) + t);
37113 } else if (x >= 0x80) {
37114 return (duk_int32_t) (x - 0x80);
37115 } else if (x == DUK_DBG_IB_INT4) {
37116 return (duk_int32_t) duk__debug_read_uint32_raw(thr);
37117 }
37118
37119 DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
37120 DUK__SET_CONN_BROKEN(thr, 1);
37121 return 0;
37122}
37123
37124DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
37125 duk_context *ctx = (duk_context *) thr;
37126 duk_uint8_t buf[31];
37127 duk_uint8_t *p;
37128
37129 if (len <= sizeof(buf)) {
37130 duk_debug_read_bytes(thr, buf, (duk_size_t) len);
37131 duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len);
37132 } else {
37133 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
37134 DUK_ASSERT(p != NULL);
37135 duk_debug_read_bytes(thr, p, (duk_size_t) len);
37136 duk_to_string(ctx, -1);
37137 }
37138
37139 return duk_require_hstring(ctx, -1);
37140}
37141
37142DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
37143 duk_context *ctx = (duk_context *) thr;
37145 duk_uint32_t len;
37146
37147 DUK_ASSERT(thr != NULL);
37148
37149 x = duk_debug_read_byte(thr);
37150 if (x >= 0x60 && x <= 0x7f) {
37151 /* For short strings, use a fixed temp buffer. */
37152 len = (duk_uint32_t) (x - 0x60);
37153 } else if (x == DUK_DBG_IB_STR2) {
37154 len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
37155 } else if (x == DUK_DBG_IB_STR4) {
37156 len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
37157 } else {
37158 goto fail;
37159 }
37160
37161 return duk__debug_read_hstring_raw(thr, len);
37162
37163 fail:
37164 DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
37165 DUK__SET_CONN_BROKEN(thr, 1);
37166 duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING); /* always push some string */
37167 return duk_require_hstring(ctx, -1);
37168}
37169
37170DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
37171 duk_context *ctx = (duk_context *) thr;
37172 duk_uint8_t *p;
37173
37174 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
37175 DUK_ASSERT(p != NULL);
37176 duk_debug_read_bytes(thr, p, (duk_size_t) len);
37177
37178 return duk_require_hbuffer(ctx, -1);
37179}
37180
37181DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
37183 duk__ptr_union pu;
37184
37185 DUK_ASSERT(thr != NULL);
37186
37187 x = duk_debug_read_byte(thr);
37188 if (x != sizeof(pu)) {
37189 goto fail;
37190 }
37191 duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
37192#if defined(DUK_USE_INTEGER_LE)
37193 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37194#endif
37195 return (void *) pu.p;
37196
37197 fail:
37198 DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
37199 DUK__SET_CONN_BROKEN(thr, 1);
37200 return (void *) NULL;
37201}
37202
37203DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
37205
37206 DUK_ASSERT(sizeof(du.uc) == 8);
37207 duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
37209 return du.d;
37210}
37211
37212#if 0
37213DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
37215
37216 DUK_ASSERT(thr != NULL);
37217
37218 x = duk_debug_read_byte(thr);
37219 if (x != DUK_DBG_IB_HEAPPTR) {
37220 goto fail;
37221 }
37222
37223 return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37224
37225 fail:
37226 DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
37227 DUK__SET_CONN_BROKEN(thr, 1);
37228 return NULL;
37229}
37230#endif
37231
37232DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
37234
37235 DUK_ASSERT(thr != NULL);
37236
37237 x = duk_debug_read_byte(thr);
37238 switch (x) {
37239 case DUK_DBG_IB_OBJECT:
37240 case DUK_DBG_IB_POINTER:
37241 case DUK_DBG_IB_HEAPPTR:
37242 /* Accept any pointer-like value; for 'object' dvalue, read
37243 * and ignore the class number.
37244 */
37245 if (x == DUK_DBG_IB_OBJECT) {
37246 duk_debug_skip_byte(thr);
37247 }
37248 break;
37249 default:
37250 goto fail;
37251 }
37252
37253 return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37254
37255 fail:
37256 DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
37257 DUK__SET_CONN_BROKEN(thr, 1);
37258 return NULL;
37259}
37260
37261DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
37262 duk_context *ctx = (duk_context *) thr;
37263 duk_uint8_t x;
37264 duk_uint_t t;
37265 duk_uint32_t len;
37266
37267 DUK_ASSERT(thr != NULL);
37268
37269 x = duk_debug_read_byte(thr);
37270
37271 if (x >= 0xc0) {
37272 t = (duk_uint_t) (x - 0xc0);
37273 t = (t << 8) + duk_debug_read_byte(thr);
37274 duk_push_uint(ctx, (duk_uint_t) t);
37275 goto return_ptr;
37276 }
37277 if (x >= 0x80) {
37278 duk_push_uint(ctx, (duk_uint_t) (x - 0x80));
37279 goto return_ptr;
37280 }
37281 if (x >= 0x60) {
37282 len = (duk_uint32_t) (x - 0x60);
37283 duk__debug_read_hstring_raw(thr, len);
37284 goto return_ptr;
37285 }
37286
37287 switch (x) {
37288 case DUK_DBG_IB_INT4: {
37289 duk_int32_t i = duk__debug_read_int32_raw(thr);
37290 duk_push_i32(ctx, i);
37291 break;
37292 }
37293 case DUK_DBG_IB_STR4: {
37294 len = duk__debug_read_uint32_raw(thr);
37295 duk__debug_read_hstring_raw(thr, len);
37296 break;
37297 }
37298 case DUK_DBG_IB_STR2: {
37299 len = duk__debug_read_uint16_raw(thr);
37300 duk__debug_read_hstring_raw(thr, len);
37301 break;
37302 }
37303 case DUK_DBG_IB_BUF4: {
37304 len = duk__debug_read_uint32_raw(thr);
37305 duk__debug_read_hbuffer_raw(thr, len);
37306 break;
37307 }
37308 case DUK_DBG_IB_BUF2: {
37309 len = duk__debug_read_uint16_raw(thr);
37310 duk__debug_read_hbuffer_raw(thr, len);
37311 break;
37312 }
37313 case DUK_DBG_IB_UNDEFINED: {
37314 duk_push_undefined(ctx);
37315 break;
37316 }
37317 case DUK_DBG_IB_NULL: {
37318 duk_push_null(ctx);
37319 break;
37320 }
37321 case DUK_DBG_IB_TRUE: {
37322 duk_push_true(ctx);
37323 break;
37324 }
37325 case DUK_DBG_IB_FALSE: {
37326 duk_push_false(ctx);
37327 break;
37328 }
37329 case DUK_DBG_IB_NUMBER: {
37330 duk_double_t d;
37331 d = duk__debug_read_double_raw(thr);
37332 duk_push_number(ctx, d);
37333 break;
37334 }
37335 case DUK_DBG_IB_OBJECT: {
37336 duk_heaphdr *h;
37337 duk_debug_skip_byte(thr);
37338 h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37339 duk_push_heapptr(thr, (void *) h);
37340 break;
37341 }
37342 case DUK_DBG_IB_POINTER: {
37343 void *ptr;
37344 ptr = duk__debug_read_pointer_raw(thr);
37345 duk_push_pointer(thr, ptr);
37346 break;
37347 }
37348 case DUK_DBG_IB_LIGHTFUNC: {
37349 /* XXX: Not needed for now, so not implemented. Note that
37350 * function pointers may have different size/layout than
37351 * a void pointer.
37352 */
37353 DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
37354 goto fail;
37355 }
37356 case DUK_DBG_IB_HEAPPTR: {
37357 duk_heaphdr *h;
37358 h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37359 duk_push_heapptr(thr, (void *) h);
37360 break;
37361 }
37362 case DUK_DBG_IB_UNUSED: /* unused: not accepted in inbound messages */
37363 default:
37364 goto fail;
37365 }
37366
37367 return_ptr:
37368 return DUK_GET_TVAL_NEGIDX(thr, -1);
37369
37370 fail:
37371 DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
37372 DUK__SET_CONN_BROKEN(thr, 1);
37373 return NULL;
37374}
37375
37376/*
37377 * Debug connection write primitives
37378 */
37379
37380/* Write fully. */
37381DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
37382 duk_heap *heap;
37383 const duk_uint8_t *p;
37385 duk_size_t got;
37386
37387 DUK_ASSERT(thr != NULL);
37388 DUK_ASSERT(length == 0 || data != NULL);
37389 heap = thr->heap;
37390 DUK_ASSERT(heap != NULL);
37391
37392 if (heap->dbg_write_cb == NULL) {
37393 DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
37394 return;
37395 }
37396 if (length == 0) {
37397 /* Avoid doing an actual write callback with length == 0,
37398 * because that's reserved for a write flush.
37399 */
37400 return;
37401 }
37402 DUK_ASSERT(data != NULL);
37403
37404 p = data;
37405 for (;;) {
37406 left = (duk_size_t) ((data + length) - p);
37407 if (left == 0) {
37408 break;
37409 }
37410 DUK_ASSERT(heap->dbg_write_cb != NULL);
37411 DUK_ASSERT(left >= 1);
37412#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
37413 left = 1;
37414#endif
37415 got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
37416 if (got == 0 || got > left) {
37417 duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
37418 DUK_D(DUK_DPRINT("connection error during write"));
37419 DUK__SET_CONN_BROKEN(thr, 1);
37420 return;
37421 }
37422 p += got;
37423 }
37424}
37425
37426DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
37427 duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
37428}
37429
37430DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
37431 duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
37432}
37433
37434DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
37435 duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
37436}
37437
37438#if defined(DUK_USE_DEBUGGER_INSPECT)
37439DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
37440 duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
37441}
37442#endif
37443
37444DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
37445 duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
37446}
37447
37448/* Write signed 32-bit integer. */
37449DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
37450 duk_uint8_t buf[5];
37451 duk_size_t len;
37452
37453 DUK_ASSERT(thr != NULL);
37454
37455 if (x >= 0 && x <= 0x3fL) {
37456 buf[0] = (duk_uint8_t) (0x80 + x);
37457 len = 1;
37458 } else if (x >= 0 && x <= 0x3fffL) {
37459 buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
37460 buf[1] = (duk_uint8_t) (x & 0xff);
37461 len = 2;
37462 } else {
37463 /* Signed integers always map to 4 bytes now. */
37464 buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
37465 buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
37466 buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
37467 buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
37468 buf[4] = (duk_uint8_t) (x & 0xff);
37469 len = 5;
37470 }
37471 duk_debug_write_bytes(thr, buf, len);
37472}
37473
37474/* Write unsigned 32-bit integer. */
37475DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
37476 /* The debugger protocol doesn't support a plain integer encoding for
37477 * the full 32-bit unsigned range (only 32-bit signed). For now,
37478 * unsigned 32-bit values simply written as signed ones. This is not
37479 * a concrete issue except for 32-bit heaphdr fields. Proper solutions
37480 * would be to (a) write such integers as IEEE doubles or (b) add an
37481 * unsigned 32-bit dvalue.
37482 */
37483 if (x >= 0x80000000UL) {
37484 DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
37485 (long) x));
37486 }
37487 duk_debug_write_int(thr, (duk_int32_t) x);
37488}
37489
37490DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
37491 duk_uint8_t buf[5];
37492 duk_size_t buflen;
37493
37494 DUK_ASSERT(thr != NULL);
37495 DUK_ASSERT(length == 0 || data != NULL);
37496
37497 if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
37498 /* For strings, special form for short lengths. */
37499 buf[0] = (duk_uint8_t) (0x60 + length);
37500 buflen = 1;
37501 } else if (length <= 0xffffUL) {
37502 buf[0] = (duk_uint8_t) (marker_base + 1);
37503 buf[1] = (duk_uint8_t) (length >> 8);
37504 buf[2] = (duk_uint8_t) (length & 0xff);
37505 buflen = 3;
37506 } else {
37507 buf[0] = (duk_uint8_t) marker_base;
37508 buf[1] = (duk_uint8_t) (length >> 24);
37509 buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
37510 buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
37511 buf[4] = (duk_uint8_t) (length & 0xff);
37512 buflen = 5;
37513 }
37514
37515 duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
37516 duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
37517}
37518
37519DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
37520 duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
37521}
37522
37523DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
37524 DUK_ASSERT(thr != NULL);
37525
37526 duk_debug_write_string(thr,
37527 data,
37528 data ? DUK_STRLEN(data) : 0);
37529}
37530
37531DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
37532 DUK_ASSERT(thr != NULL);
37533
37534 /* XXX: differentiate null pointer from empty string? */
37535 duk_debug_write_string(thr,
37536 (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
37537 (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
37538}
37539
37540DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
37541 duk_context *ctx = (duk_context *) thr;
37542 duk_debug_write_hstring(thr, duk_safe_to_hstring(ctx, -1));
37543}
37544
37545DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
37546 duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
37547}
37548
37549DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
37550 DUK_ASSERT(thr != NULL);
37551
37552 duk_debug_write_buffer(thr,
37553 (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
37554 (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
37555}
37556
37557DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
37558 duk_uint8_t buf[2];
37559 duk__ptr_union pu;
37560
37561 DUK_ASSERT(thr != NULL);
37562 DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
37563 /* ptr may be NULL */
37564
37565 buf[0] = ibyte;
37566 buf[1] = sizeof(pu);
37567 duk_debug_write_bytes(thr, buf, 2);
37568 pu.p = (void *) ptr;
37569#if defined(DUK_USE_INTEGER_LE)
37570 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37571#endif
37572 duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
37573}
37574
37575DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
37576 duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
37577}
37578
37579#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
37580DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
37581 duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
37582}
37583#endif /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
37584
37585DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
37586 duk_uint8_t buf[3];
37587 duk__ptr_union pu;
37588
37589 DUK_ASSERT(thr != NULL);
37590 DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
37591 DUK_ASSERT(obj != NULL);
37592
37593 buf[0] = DUK_DBG_IB_OBJECT;
37594 buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
37595 buf[2] = sizeof(pu);
37596 duk_debug_write_bytes(thr, buf, 3);
37597 pu.p = (void *) obj;
37598#if defined(DUK_USE_INTEGER_LE)
37599 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37600#endif
37601 duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
37602}
37603
37604DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
37605 duk_c_function lf_func;
37606 duk_small_uint_t lf_flags;
37607 duk_uint8_t buf[4];
37608 duk_double_union du1;
37609 duk_double_union du2;
37610 duk_int32_t i32;
37611
37612 DUK_ASSERT(thr != NULL);
37613 DUK_ASSERT(tv != NULL);
37614
37615 switch (DUK_TVAL_GET_TAG(tv)) {
37616 case DUK_TAG_UNDEFINED:
37617 duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
37618 break;
37619 case DUK_TAG_UNUSED:
37620 duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
37621 break;
37622 case DUK_TAG_NULL:
37623 duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
37624 break;
37625 case DUK_TAG_BOOLEAN:
37627 DUK_TVAL_GET_BOOLEAN(tv) == 1);
37628 duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
37629 break;
37630 case DUK_TAG_POINTER:
37631 duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
37632 break;
37633 case DUK_TAG_LIGHTFUNC:
37634 DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
37635 buf[0] = DUK_DBG_IB_LIGHTFUNC;
37636 buf[1] = (duk_uint8_t) (lf_flags >> 8);
37637 buf[2] = (duk_uint8_t) (lf_flags & 0xff);
37638 buf[3] = sizeof(lf_func);
37639 duk_debug_write_bytes(thr, buf, 4);
37640 duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
37641 break;
37642 case DUK_TAG_STRING:
37643 duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
37644 break;
37645 case DUK_TAG_OBJECT:
37646 duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
37647 break;
37648 case DUK_TAG_BUFFER:
37649 duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
37650 break;
37651#if defined(DUK_USE_FASTINT)
37652 case DUK_TAG_FASTINT:
37653#endif
37654 default:
37655 /* Numbers are normalized to big (network) endian. We can
37656 * (but are not required) to use integer dvalues when there's
37657 * no loss of precision.
37658 *
37659 * XXX: share check with other code; this check is slow but
37660 * reliable and doesn't require careful exponent/mantissa
37661 * mask tricks as in the fastint downgrade code.
37662 */
37665 du1.d = DUK_TVAL_GET_NUMBER(tv);
37666 i32 = (duk_int32_t) du1.d;
37667 du2.d = (duk_double_t) i32;
37668
37669 DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
37670 "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
37671 (long) i32,
37672 (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
37673 (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
37674 (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
37675 (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
37676 (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
37677 (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
37678 (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
37679 (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
37680
37681 if (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
37682 duk_debug_write_int(thr, i32);
37683 } else {
37684 DUK_DBLUNION_DOUBLE_HTON(&du1);
37685 duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
37686 duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
37687 }
37688 }
37689}
37690
37691#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
37692/* Variant for writing duk_tvals so that any heap allocated values are
37693 * written out as tagged heap pointers.
37694 */
37695DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
37698 duk_debug_write_heapptr(thr, h);
37699 } else {
37700 duk_debug_write_tval(thr, tv);
37701 }
37702}
37703#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
37704
37705/*
37706 * Debug connection message write helpers
37707 */
37708
37709#if 0 /* unused */
37710DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
37711 duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
37712 duk_debug_write_int(thr, command);
37713}
37714#endif
37715
37716DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
37717 duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
37718}
37719
37720DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
37721 /* Allow NULL 'msg' */
37722 duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
37723 duk_debug_write_int(thr, (duk_int32_t) err_code);
37724 duk_debug_write_cstring(thr, msg);
37725 duk_debug_write_eom(thr);
37726}
37727
37728DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
37729 duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
37730 duk_debug_write_int(thr, command);
37731}
37732
37733DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
37734 duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
37735
37736 /* As an initial implementation, write flush after every EOM (and the
37737 * version identifier). A better implementation would flush only when
37738 * Duktape is finished processing messages so that a flush only happens
37739 * after all outbound messages are finished on that occasion.
37740 */
37741 duk_debug_write_flush(thr);
37742}
37743
37744/*
37745 * Status message and helpers
37746 */
37747
37748DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
37749 duk_context *ctx = (duk_context *) thr;
37750 duk_activation *act;
37751 duk_uint_fast32_t line;
37753
37754 act = duk_hthread_get_current_activation(thr); /* may be NULL */
37755 if (act == NULL) {
37756 return 0;
37757 }
37758
37759 /* We're conceptually between two opcodes; act->pc indicates the next
37760 * instruction to be executed. This is usually the correct pc/line to
37761 * indicate in Status. (For the 'debugger' statement this now reports
37762 * the pc/line after the debugger statement because the debugger opcode
37763 * has already been executed.)
37764 */
37765
37766 pc = duk_hthread_get_act_curr_pc(thr, act);
37767
37768 /* XXX: this should be optimized to be a raw query and avoid valstack
37769 * operations if possible.
37770 */
37771 duk_push_tval(ctx, &act->tv_func);
37772 line = duk_hobject_pc2line_query(ctx, -1, pc);
37773 duk_pop(ctx);
37774 return line;
37775}
37776
37777DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
37778 duk_context *ctx = (duk_context *) thr;
37779 duk_activation *act;
37780
37781 duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
37782 duk_debug_write_int(thr, thr->heap->dbg_paused);
37783
37784 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* unsigned */
37785 if (thr->callstack_top == 0) {
37786 duk_debug_write_undefined(thr);
37787 duk_debug_write_undefined(thr);
37788 duk_debug_write_int(thr, 0);
37789 duk_debug_write_int(thr, 0);
37790 } else {
37791 act = thr->callstack + thr->callstack_top - 1;
37792 duk_push_tval(ctx, &act->tv_func);
37793 duk_get_prop_string(ctx, -1, "fileName");
37794 duk__debug_write_hstring_safe_top(thr);
37795 duk_get_prop_string(ctx, -2, "name");
37796 duk__debug_write_hstring_safe_top(thr);
37797 duk_pop_3(ctx);
37798 /* Report next pc/line to be executed. */
37799 duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
37800 duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
37801 }
37802
37803 duk_debug_write_eom(thr);
37804}
37805
37806#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
37807DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
37808 /*
37809 * NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
37810 */
37811
37812 duk_context *ctx = (duk_context *) thr;
37813 duk_activation *act;
37814 duk_uint32_t pc;
37815
37816 DUK_ASSERT(thr->valstack_top > thr->valstack); /* At least: ... [err] */
37817
37818 duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
37819 duk_debug_write_int(thr, fatal);
37820
37821 /* Report thrown value to client coerced to string */
37822 duk_dup(ctx, -1);
37823 duk__debug_write_hstring_safe_top(thr);
37824 duk_pop(ctx);
37825
37826 if (duk_is_error(ctx, -1)) {
37827 /* Error instance, use augmented error data directly */
37829 duk__debug_write_hstring_safe_top(thr);
37831 duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
37832 } else {
37833 /* For anything other than an Error instance, we calculate the error
37834 * location directly from the current activation.
37835 */
37836 act = thr->callstack + thr->callstack_top - 1;
37837 duk_push_tval(ctx, &act->tv_func);
37838 duk_get_prop_string(ctx, -1, "fileName");
37839 duk__debug_write_hstring_safe_top(thr);
37840 pc = duk_hthread_get_act_prev_pc(thr, act);
37841 duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
37842 }
37843 duk_pop_2(ctx); /* shared pop */
37844
37845 duk_debug_write_eom(thr);
37846}
37847#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY */
37848
37849/*
37850 * Debug message processing
37851 */
37852
37853/* Skip dvalue. */
37854DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
37855 duk_uint8_t x;
37856 duk_uint32_t len;
37857
37858 x = duk_debug_read_byte(thr);
37859
37860 if (x >= 0xc0) {
37861 duk_debug_skip_byte(thr);
37862 return 0;
37863 }
37864 if (x >= 0x80) {
37865 return 0;
37866 }
37867 if (x >= 0x60) {
37868 duk_debug_skip_bytes(thr, x - 0x60);
37869 return 0;
37870 }
37871 switch(x) {
37872 case DUK_DBG_IB_EOM:
37873 return 1; /* Return 1: got EOM */
37874 case DUK_DBG_IB_REQUEST:
37875 case DUK_DBG_IB_REPLY:
37876 case DUK_DBG_IB_ERROR:
37877 case DUK_DBG_IB_NOTIFY:
37878 break;
37879 case DUK_DBG_IB_INT4:
37880 (void) duk__debug_read_uint32_raw(thr);
37881 break;
37882 case DUK_DBG_IB_STR4:
37883 case DUK_DBG_IB_BUF4:
37884 len = duk__debug_read_uint32_raw(thr);
37885 duk_debug_skip_bytes(thr, len);
37886 break;
37887 case DUK_DBG_IB_STR2:
37888 case DUK_DBG_IB_BUF2:
37889 len = duk__debug_read_uint16_raw(thr);
37890 duk_debug_skip_bytes(thr, len);
37891 break;
37892 case DUK_DBG_IB_UNUSED:
37894 case DUK_DBG_IB_NULL:
37895 case DUK_DBG_IB_TRUE:
37896 case DUK_DBG_IB_FALSE:
37897 break;
37898 case DUK_DBG_IB_NUMBER:
37899 duk_debug_skip_bytes(thr, 8);
37900 break;
37901 case DUK_DBG_IB_OBJECT:
37902 duk_debug_skip_byte(thr);
37903 len = duk_debug_read_byte(thr);
37904 duk_debug_skip_bytes(thr, len);
37905 break;
37906 case DUK_DBG_IB_POINTER:
37907 case DUK_DBG_IB_HEAPPTR:
37908 len = duk_debug_read_byte(thr);
37909 duk_debug_skip_bytes(thr, len);
37910 break;
37912 duk_debug_skip_bytes(thr, 2);
37913 len = duk_debug_read_byte(thr);
37914 duk_debug_skip_bytes(thr, len);
37915 break;
37916 default:
37917 goto fail;
37918 }
37919
37920 return 0;
37921
37922 fail:
37923 DUK__SET_CONN_BROKEN(thr, 1);
37924 return 1; /* Pretend like we got EOM */
37925}
37926
37927/* Skip dvalues to EOM. */
37928DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
37929 for (;;) {
37930 if (duk__debug_skip_dvalue(thr)) {
37931 break;
37932 }
37933 }
37934}
37935
37936/*
37937 * Simple commands
37938 */
37939
37940DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
37941 DUK_UNREF(heap);
37942 DUK_D(DUK_DPRINT("debug command Version"));
37943
37944 duk_debug_write_reply(thr);
37945 duk_debug_write_int(thr, DUK_VERSION);
37946 duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
37947 duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
37948#if defined(DUK_USE_DOUBLE_LE)
37949 duk_debug_write_int(thr, 1);
37950#elif defined(DUK_USE_DOUBLE_ME)
37951 duk_debug_write_int(thr, 2);
37952#elif defined(DUK_USE_DOUBLE_BE)
37953 duk_debug_write_int(thr, 3);
37954#else
37955 duk_debug_write_int(thr, 0);
37956#endif
37957 duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
37958 duk_debug_write_eom(thr);
37959}
37960
37961DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
37962 DUK_UNREF(heap);
37963 DUK_D(DUK_DPRINT("debug command TriggerStatus"));
37964
37965 duk_debug_write_reply(thr);
37966 duk_debug_write_eom(thr);
37967 heap->dbg_state_dirty = 1;
37968}
37969
37970DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
37971 DUK_D(DUK_DPRINT("debug command Pause"));
37972
37973 DUK_HEAP_SET_PAUSED(heap);
37974 duk_debug_write_reply(thr);
37975 duk_debug_write_eom(thr);
37976}
37977
37978DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
37979 DUK_D(DUK_DPRINT("debug command Resume"));
37980
37981 DUK_HEAP_CLEAR_PAUSED(heap);
37982 duk_debug_write_reply(thr);
37983 duk_debug_write_eom(thr);
37984}
37985
37986DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
37987 duk_small_uint_t step_type;
37988 duk_uint_fast32_t line;
37989
37990 DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
37991
37992 if (cmd == DUK_DBG_CMD_STEPINTO) {
37993 step_type = DUK_STEP_TYPE_INTO;
37994 } else if (cmd == DUK_DBG_CMD_STEPOVER) {
37995 step_type = DUK_STEP_TYPE_OVER;
37996 } else {
37998 step_type = DUK_STEP_TYPE_OUT;
37999 }
38000
38001 line = duk_debug_curr_line(thr);
38002 if (line > 0) {
38003 heap->dbg_paused = 0;
38004 heap->dbg_step_type = step_type;
38005 heap->dbg_step_thread = thr;
38006 heap->dbg_step_csindex = thr->callstack_top - 1;
38007 heap->dbg_step_startline = line;
38008 heap->dbg_state_dirty = 1;
38009 } else {
38010 DUK_D(DUK_DPRINT("cannot determine current line, stepinto/stepover/stepout ignored"));
38011 }
38012 duk_debug_write_reply(thr);
38013 duk_debug_write_eom(thr);
38014}
38015
38016DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
38018
38019 DUK_D(DUK_DPRINT("debug command ListBreak"));
38020 duk_debug_write_reply(thr);
38021 for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
38022 duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
38023 duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
38024 }
38025 duk_debug_write_eom(thr);
38026}
38027
38028DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
38029 duk_hstring *filename;
38030 duk_uint32_t linenumber;
38031 duk_small_int_t idx;
38032
38033 DUK_UNREF(heap);
38034
38035 filename = duk_debug_read_hstring(thr);
38036 linenumber = (duk_uint32_t) duk_debug_read_int(thr);
38037 DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
38038 idx = duk_debug_add_breakpoint(thr, filename, linenumber);
38039 if (idx >= 0) {
38040 duk_debug_write_reply(thr);
38041 duk_debug_write_int(thr, (duk_int32_t) idx);
38042 duk_debug_write_eom(thr);
38043 } else {
38044 duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
38045 }
38046}
38047
38048DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
38049 duk_small_uint_t idx;
38050
38051 DUK_UNREF(heap);
38052
38053 DUK_D(DUK_DPRINT("debug command DelBreak"));
38054 idx = (duk_small_uint_t) duk_debug_read_int(thr);
38055 if (duk_debug_remove_breakpoint(thr, idx)) {
38056 duk_debug_write_reply(thr);
38057 duk_debug_write_eom(thr);
38058 } else {
38059 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
38060 }
38061}
38062
38063DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
38064 duk_context *ctx = (duk_context *) thr;
38065 duk_hstring *str;
38066 duk_bool_t rc;
38067 duk_int32_t level;
38068
38069 DUK_UNREF(heap);
38070 DUK_D(DUK_DPRINT("debug command GetVar"));
38071
38072 str = duk_debug_read_hstring(thr); /* push to stack */
38073 DUK_ASSERT(str != NULL);
38074 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38075 level = duk_debug_read_int(thr); /* optional callstack level */
38076 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38077 DUK_D(DUK_DPRINT("invalid callstack level for GetVar"));
38078 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38079 return;
38080 }
38081 } else {
38082 level = -1;
38083 }
38084
38085 if (thr->callstack_top > 0) {
38086 rc = duk_js_getvar_activation(thr,
38087 thr->callstack + thr->callstack_top + level,
38088 str,
38089 0);
38090 } else {
38091 /* No activation, no variable access. Could also pretend
38092 * we're in the global program context and read stuff off
38093 * the global object.
38094 */
38095 DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore getvar"));
38096 rc = 0;
38097 }
38098
38099 duk_debug_write_reply(thr);
38100 if (rc) {
38101 duk_debug_write_int(thr, 1);
38102 DUK_ASSERT(duk_get_tval(ctx, -2) != NULL);
38103 duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
38104 } else {
38105 duk_debug_write_int(thr, 0);
38106 duk_debug_write_unused(thr);
38107 }
38108 duk_debug_write_eom(thr);
38109}
38110
38111DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
38112 duk_hstring *str;
38113 duk_tval *tv;
38114 duk_int32_t level;
38115
38116 DUK_UNREF(heap);
38117 DUK_D(DUK_DPRINT("debug command PutVar"));
38118
38119 str = duk_debug_read_hstring(thr); /* push to stack */
38120 DUK_ASSERT(str != NULL);
38121 tv = duk_debug_read_tval(thr);
38122 if (tv == NULL) {
38123 /* detached */
38124 return;
38125 }
38126 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38127 level = duk_debug_read_int(thr); /* optional callstack level */
38128 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38129 DUK_D(DUK_DPRINT("invalid callstack level for PutVar"));
38130 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38131 return;
38132 }
38133 } else {
38134 level = -1;
38135 }
38136
38137 if (thr->callstack_top > 0) {
38139 thr->callstack + thr->callstack_top + level,
38140 str,
38141 tv,
38142 0);
38143 } else {
38144 DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore putvar"));
38145 }
38146
38147 /* XXX: Current putvar implementation doesn't have a success flag,
38148 * add one and send to debug client?
38149 */
38150 duk_debug_write_reply(thr);
38151 duk_debug_write_eom(thr);
38152}
38153
38154DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
38155 duk_context *ctx = (duk_context *) thr;
38156 duk_hthread *curr_thr = thr;
38157 duk_activation *curr_act;
38159 duk_uint_fast32_t line;
38160 duk_size_t i;
38161
38162 DUK_ASSERT(thr != NULL);
38163 DUK_UNREF(heap);
38164
38165 duk_debug_write_reply(thr);
38166 while (curr_thr != NULL) {
38167 i = curr_thr->callstack_top;
38168 while (i > 0) {
38169 i--;
38170 curr_act = curr_thr->callstack + i;
38171
38172 /* PC/line semantics here are:
38173 * - For callstack top we're conceptually between two
38174 * opcodes and current PC indicates next line to
38175 * execute, so report that (matches Status).
38176 * - For other activations we're conceptually still
38177 * executing the instruction at PC-1, so report that
38178 * (matches error stacktrace behavior).
38179 * - See: https://github.com/svaarala/duktape/issues/281
38180 */
38181
38182 /* XXX: optimize to use direct reads, i.e. avoid
38183 * value stack operations.
38184 */
38185 duk_push_tval(ctx, &curr_act->tv_func);
38187 duk__debug_write_hstring_safe_top(thr);
38189 duk__debug_write_hstring_safe_top(thr);
38190 pc = duk_hthread_get_act_curr_pc(thr, curr_act);
38191 if (i != curr_thr->callstack_top - 1 && pc > 0) {
38192 pc--;
38193 }
38194 line = duk_hobject_pc2line_query(ctx, -3, pc);
38195 duk_debug_write_uint(thr, (duk_uint32_t) line);
38196 duk_debug_write_uint(thr, (duk_uint32_t) pc);
38197 duk_pop_3(ctx);
38198 }
38199 curr_thr = curr_thr->resumer;
38200 }
38201 /* SCANBUILD: warning about 'thr' potentially being NULL here,
38202 * warning is incorrect because thr != NULL always here.
38203 */
38204 duk_debug_write_eom(thr);
38205}
38206
38207DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
38208 duk_context *ctx = (duk_context *) thr;
38209 duk_activation *curr_act;
38210 duk_int32_t level;
38211 duk_hstring *varname;
38212
38213 DUK_UNREF(heap);
38214
38215 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38216 level = duk_debug_read_int(thr); /* optional callstack level */
38217 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38218 DUK_D(DUK_DPRINT("invalid callstack level for GetLocals"));
38219 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38220 return;
38221 }
38222 duk_debug_write_reply(thr);
38223 } else {
38224 duk_debug_write_reply(thr);
38225 if (thr->callstack_top == 0) {
38226 goto callstack_empty;
38227 }
38228 level = -1;
38229 }
38230
38231 curr_act = thr->callstack + thr->callstack_top + level;
38232
38233 /* XXX: several nice-to-have improvements here:
38234 * - Use direct reads avoiding value stack operations
38235 * - Avoid triggering getters, indicate getter values to debug client
38236 * - If side effects are possible, add error catching
38237 */
38238
38239 duk_push_tval(ctx, &curr_act->tv_func);
38241 if (duk_is_object(ctx, -1)) {
38242 duk_enum(ctx, -1, 0 /*enum_flags*/);
38243 while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
38244 varname = duk_get_hstring(ctx, -1);
38245 DUK_ASSERT(varname != NULL);
38246
38247 duk_js_getvar_activation(thr, curr_act, varname, 0 /*throw_flag*/);
38248 /* [ ... func varmap enum key value this ] */
38249 duk_debug_write_hstring(thr, duk_get_hstring(ctx, -3));
38250 duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
38251 duk_pop_3(ctx); /* -> [ ... func varmap enum ] */
38252 }
38253 } else {
38254 DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
38255 }
38256
38257 callstack_empty:
38258 duk_debug_write_eom(thr);
38259}
38260
38261DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
38262 duk_context *ctx = (duk_context *) thr;
38263 duk_small_uint_t call_flags;
38264 duk_int_t call_ret;
38265 duk_small_int_t eval_err;
38266 duk_int32_t level;
38267
38268 DUK_UNREF(heap);
38269
38270 DUK_D(DUK_DPRINT("debug command Eval"));
38271
38272 /* The eval code is executed within the lexical environment of a specified
38273 * activation. For now, use global object eval() function, with the eval
38274 * considered a 'direct call to eval'.
38275 *
38276 * Callstack level for debug commands only affects scope -- the callstack
38277 * as seen by, e.g. Duktape.act() will be the same regardless.
38278 */
38279
38280 /* nargs == 2 so we can pass a callstack level to eval(). */
38282 duk_push_undefined(ctx); /* 'this' binding shouldn't matter here */
38283
38284 (void) duk_debug_read_hstring(thr);
38285 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38286 level = duk_debug_read_int(thr); /* optional callstack level */
38287 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38288 DUK_D(DUK_DPRINT("invalid callstack level for Eval"));
38289 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38290 return;
38291 }
38292 }
38293 else {
38294 level = -1;
38295 }
38296 DUK_ASSERT(level < 0 && -level <= (duk_int32_t) thr->callstack_top);
38297 duk_push_int(ctx, level - 1); /* compensate for eval() call */
38298
38299 /* [ ... eval "eval" eval_input level ] */
38300
38301 call_flags = 0;
38302 if (thr->callstack_top >= (duk_size_t) -level) {
38303 duk_activation *act;
38304 duk_hobject *fun;
38305
38306 act = thr->callstack + thr->callstack_top + level;
38307 fun = DUK_ACT_GET_FUNC(act);
38308 if (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(fun)) {
38309 /* Direct eval requires that there's a current
38310 * activation and it is an Ecmascript function.
38311 * When Eval is executed from e.g. cooperate API
38312 * call we'll need to do an indirect eval instead.
38313 */
38314 call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
38315 }
38316 }
38317
38318 call_ret = duk_handle_call_protected(thr, 2 /*num_stack_args*/, call_flags);
38319
38320 if (call_ret == DUK_EXEC_SUCCESS) {
38321 eval_err = 0;
38322 /* Use result value as is. */
38323 } else {
38324 /* For errors a string coerced result is most informative
38325 * right now, as the debug client doesn't have the capability
38326 * to traverse the error object.
38327 */
38328 eval_err = 1;
38329 duk_safe_to_string(ctx, -1);
38330 }
38331
38332 /* [ ... result ] */
38333
38334 duk_debug_write_reply(thr);
38335 duk_debug_write_int(thr, (duk_int32_t) eval_err);
38336 DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
38337 duk_debug_write_tval(thr, duk_get_tval(ctx, -1));
38338 duk_debug_write_eom(thr);
38339}
38340
38341DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
38342 DUK_UNREF(heap);
38343 DUK_D(DUK_DPRINT("debug command Detach"));
38344
38345 duk_debug_write_reply(thr);
38346 duk_debug_write_eom(thr);
38347
38348 DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
38349 DUK__SET_CONN_BROKEN(thr, 0); /* not an error */
38350}
38351
38352DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
38353 duk_context *ctx = (duk_context *) thr;
38354 duk_idx_t old_top;
38355
38356 DUK_D(DUK_DPRINT("debug command AppRequest"));
38357
38358 old_top = duk_get_top(ctx); /* save stack top */
38359
38360 if (heap->dbg_request_cb != NULL) {
38361 duk_idx_t nrets;
38362 duk_idx_t nvalues = 0;
38363 duk_idx_t top, idx;
38364
38365 /* Read tvals from the message and push them onto the valstack,
38366 * then call the request callback to process the request.
38367 */
38368 while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38369 duk_tval *tv;
38370 if (!duk_check_stack(ctx, 1)) {
38371 DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
38372 goto fail;
38373 }
38374 tv = duk_debug_read_tval(thr); /* push to stack */
38375 if (tv == NULL) {
38376 /* detached */
38377 return;
38378 }
38379 nvalues++;
38380 }
38381 DUK_ASSERT(duk_get_top(ctx) == old_top + nvalues);
38382
38383 /* Request callback should push values for reply to client onto valstack */
38384 DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
38385 (long) nvalues, (long) old_top, (long) duk_get_top(ctx)));
38386 nrets = heap->dbg_request_cb(ctx, heap->dbg_udata, nvalues);
38387 DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
38388 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(ctx)));
38389 if (nrets >= 0) {
38390 DUK_ASSERT(duk_get_top(ctx) >= old_top + nrets);
38391 if (duk_get_top(ctx) < old_top + nrets) {
38392 DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
38393 "top=%ld < old_top=%ld + nrets=%ld; "
38394 "this might mean it's unsafe to continue!",
38395 (long) duk_get_top(ctx), (long) old_top, (long) nrets));
38396 goto fail;
38397 }
38398
38399 /* Reply with tvals pushed by request callback */
38400 duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
38401 top = duk_get_top(ctx);
38402 for (idx = top - nrets; idx < top; idx++) {
38403 duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(ctx, idx));
38404 }
38405 duk_debug_write_eom(thr);
38406 } else {
38407 DUK_ASSERT(duk_get_top(ctx) >= old_top + 1);
38408 if (duk_get_top(ctx) < old_top + 1) {
38409 DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
38410 goto fail;
38411 }
38412 duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(ctx, -1));
38413 }
38414
38415 duk_set_top(ctx, old_top); /* restore stack top */
38416 } else {
38417 DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
38418 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
38419 }
38420
38421 return;
38422
38423 fail:
38424 duk_set_top(ctx, old_top); /* restore stack top */
38425 DUK__SET_CONN_BROKEN(thr, 1);
38426}
38427
38428/*
38429 * DumpHeap command
38430 */
38431
38432#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
38433/* XXX: this has some overlap with object inspection; remove this and make
38434 * DumpHeap return lists of heapptrs instead?
38435 */
38436DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
38437 DUK_UNREF(heap);
38438
38439 duk_debug_write_heapptr(thr, hdr);
38440 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
38441 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
38442#if defined(DUK_USE_REFERENCE_COUNTING)
38443 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
38444#else
38445 duk_debug_write_int(thr, (duk_int32_t) -1);
38446#endif
38447
38448 switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
38449 case DUK_HTYPE_STRING: {
38450 duk_hstring *h = (duk_hstring *) hdr;
38451
38452 duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_BYTELEN(h));
38453 duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_CHARLEN(h));
38454 duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_HASH(h));
38455 duk_debug_write_hstring(thr, h);
38456 break;
38457 }
38458 case DUK_HTYPE_OBJECT: {
38459 duk_hobject *h = (duk_hobject *) hdr;
38460 duk_hstring *k;
38462
38463 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
38464 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
38465 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
38466 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
38467 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
38468 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
38469
38470 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
38471 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
38472 k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
38473 duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
38474 if (k == NULL) {
38475 duk_debug_write_int(thr, 0); /* isAccessor */
38476 duk_debug_write_unused(thr);
38477 continue;
38478 }
38479 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
38480 duk_debug_write_int(thr, 1); /* isAccessor */
38481 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
38482 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
38483 } else {
38484 duk_debug_write_int(thr, 0); /* isAccessor */
38485
38486 duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
38487 }
38488 }
38489
38490 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
38491 /* Note: array dump will include elements beyond
38492 * 'length'.
38493 */
38494 duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
38495 }
38496 break;
38497 }
38498 case DUK_HTYPE_BUFFER: {
38499 duk_hbuffer *h = (duk_hbuffer *) hdr;
38500
38501 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
38502 duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
38503 break;
38504 }
38505 default: {
38506 DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
38507 }
38508 }
38509}
38510
38511DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
38512 duk_heaphdr *hdr;
38513
38514 hdr = heap->heap_allocated;
38515 while (hdr != NULL) {
38516 duk__debug_dump_heaphdr(thr, heap, hdr);
38517 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
38518 }
38519}
38520
38521#if defined(DUK_USE_STRTAB_CHAIN)
38522DUK_LOCAL void duk__debug_dump_strtab_chain(duk_hthread *thr, duk_heap *heap) {
38523 duk_uint_fast32_t i, j;
38525#if defined(DUK_USE_HEAPPTR16)
38526 duk_uint16_t *lst;
38527#else
38528 duk_hstring **lst;
38529#endif
38530 duk_hstring *h;
38531
38532 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
38533 e = heap->strtable + i;
38534 if (e->listlen > 0) {
38535#if defined(DUK_USE_HEAPPTR16)
38536 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
38537#else
38538 lst = e->u.strlist;
38539#endif
38540 DUK_ASSERT(lst != NULL);
38541
38542 for (j = 0; j < e->listlen; j++) {
38543#if defined(DUK_USE_HEAPPTR16)
38544 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
38545#else
38546 h = lst[j];
38547#endif
38548 if (h != NULL) {
38549 duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38550 }
38551 }
38552 } else {
38553#if defined(DUK_USE_HEAPPTR16)
38554 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
38555#else
38556 h = e->u.str;
38557#endif
38558 if (h != NULL) {
38559 duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38560 }
38561 }
38562 }
38563}
38564#endif /* DUK_USE_STRTAB_CHAIN */
38565
38566#if defined(DUK_USE_STRTAB_PROBE)
38567DUK_LOCAL void duk__debug_dump_strtab_probe(duk_hthread *thr, duk_heap *heap) {
38568 duk_uint32_t i;
38569 duk_hstring *h;
38570
38571 for (i = 0; i < heap->st_size; i++) {
38572#if defined(DUK_USE_HEAPPTR16)
38573 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
38574#else
38575 h = heap->strtable[i];
38576#endif
38577 if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
38578 continue;
38579 }
38580
38581 duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38582 }
38583}
38584#endif /* DUK_USE_STRTAB_PROBE */
38585
38586DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
38587 DUK_D(DUK_DPRINT("debug command DumpHeap"));
38588
38589 duk_debug_write_reply(thr);
38590 duk__debug_dump_heap_allocated(thr, heap);
38591#if defined(DUK_USE_STRTAB_CHAIN)
38592 duk__debug_dump_strtab_chain(thr, heap);
38593#endif
38594#if defined(DUK_USE_STRTAB_PROBE)
38595 duk__debug_dump_strtab_probe(thr, heap);
38596#endif
38597 duk_debug_write_eom(thr);
38598}
38599#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
38600
38601DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
38602 duk_activation *act;
38604 duk_size_t i, n;
38605 duk_tval *tv;
38606 duk_hobject **fn;
38607 duk_int32_t level = -1;
38608 duk_uint8_t ibyte;
38609
38610 DUK_UNREF(heap);
38611
38612 DUK_D(DUK_DPRINT("debug command GetBytecode"));
38613
38614 ibyte = duk_debug_peek_byte(thr);
38615 if (ibyte != DUK_DBG_IB_EOM) {
38616 tv = duk_debug_read_tval(thr);
38617 if (tv == NULL) {
38618 /* detached */
38619 return;
38620 }
38621 if (DUK_TVAL_IS_OBJECT(tv)) {
38622 /* tentative, checked later */
38624 DUK_ASSERT(fun != NULL);
38625 } else if (DUK_TVAL_IS_NUMBER(tv)) {
38626 level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
38627 } else {
38628 DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
38629 goto fail_args;
38630 }
38631 }
38632
38633 if (fun == NULL) {
38634 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38635 DUK_D(DUK_DPRINT("invalid callstack level for GetBytecode"));
38636 goto fail_level;
38637 }
38638 act = thr->callstack + thr->callstack_top + level;
38640 }
38641
38642 if (fun == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)) {
38643 DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
38644 goto fail_args;
38645 }
38647
38648 duk_debug_write_reply(thr);
38650 duk_debug_write_int(thr, (duk_int32_t) n);
38652 for (i = 0; i < n; i++) {
38653 duk_debug_write_tval(thr, tv);
38654 tv++;
38655 }
38657 duk_debug_write_int(thr, (duk_int32_t) n);
38659 for (i = 0; i < n; i++) {
38660 duk_debug_write_hobject(thr, *fn);
38661 fn++;
38662 }
38663 duk_debug_write_string(thr,
38664 (const char *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap, fun),
38666 duk_debug_write_eom(thr);
38667 return;
38668
38669 fail_args:
38670 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
38671 return;
38672
38673 fail_level:
38674 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38675 return;
38676}
38677
38678/*
38679 * Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
38680 * GetObjPropDescRange
38681 */
38682
38683#if defined(DUK_USE_DEBUGGER_INSPECT)
38684
38685#if 0 /* pruned */
38686DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
38687 "reachable",
38688 "temproot",
38689 "finalizable",
38690 "finalized",
38691 "readonly"
38692 /* NULL not needed here */
38693};
38694DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
38700 0 /* terminator */
38701};
38702#endif
38703DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
38704#if 0
38705 "arridx",
38706 "internal",
38707 "reserved_word",
38708 "strict_reserved_word",
38709 "eval_or_arguments",
38710#endif
38711 "extdata"
38712 /* NULL not needed here */
38713};
38714DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
38715#if 0
38721#endif
38723 0 /* terminator */
38724};
38725DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
38726 "extensible",
38727 "constructable",
38728 "bound",
38729 "compiledfunction",
38730 "nativefunction",
38731 "bufferobject",
38732 "thread",
38733 "array_part",
38734 "strict",
38735 "notail",
38736 "newenv",
38737 "namebinding",
38738 "createargs",
38739 "envrecclosed",
38740 "exotic_array",
38741 "exotic_stringobj",
38742 "exotic_arguments",
38743 "exotic_dukfunc",
38744 "exotic_proxyobj"
38745 /* NULL not needed here */
38746};
38747DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
38767 0 /* terminator */
38768};
38769DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
38770 "dynamic",
38771 "external"
38772 /* NULL not needed here */
38773};
38774DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
38777 0 /* terminator */
38778};
38779
38780DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
38781 duk_debug_write_uint(thr, 0);
38782 duk_debug_write_cstring(thr, key);
38783}
38784
38785DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
38786 duk_debug_write_uint(thr, 0);
38787 duk_debug_write_cstring(thr, key);
38788 duk_debug_write_uint(thr, val);
38789}
38790
38791DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
38792 duk_debug_write_uint(thr, 0);
38793 duk_debug_write_cstring(thr, key);
38794 duk_debug_write_int(thr, val);
38795}
38796
38797DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
38798 duk_debug_write_uint(thr, 0);
38799 duk_debug_write_cstring(thr, key);
38800 duk_debug_write_boolean(thr, val);
38801}
38802
38803DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
38804 const char *key;
38806
38807 for (;;) {
38808 mask = *masks++;
38809 if (!mask) {
38810 break;
38811 }
38812 key = *keys++;
38813 DUK_ASSERT(key != NULL);
38814
38815 DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
38816 duk__debug_getinfo_prop_bool(thr, key, flags & mask);
38817 }
38818}
38819
38820/* Inspect a property using a virtual index into a conceptual property list
38821 * consisting of (1) all array part items from [0,a_size[ (even when above
38822 * .length) and (2) all entry part items from [0,e_next[. Unused slots are
38823 * indicated using dvalue 'unused'.
38824 */
38825DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
38826 duk_uint_t a_size;
38827 duk_tval *tv;
38828 duk_hstring *h_key;
38829 duk_hobject *h_getset;
38830 duk_uint_t flags;
38831
38832 DUK_UNREF(heap);
38833
38834 a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
38835 if (idx < a_size) {
38836 duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
38837 duk_debug_write_uint(thr, idx);
38838 tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
38839 duk_debug_write_tval(thr, tv);
38840 return 1;
38841 }
38842
38843 idx -= a_size;
38844 if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
38845 return 0;
38846 }
38847
38848 h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
38849 if (h_key == NULL) {
38850 duk_debug_write_uint(thr, 0);
38851 duk_debug_write_null(thr);
38852 duk_debug_write_unused(thr);
38853 return 1;
38854 }
38855
38856 flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
38857 if (DUK_HSTRING_HAS_INTERNAL(h_key)) {
38859 }
38860 duk_debug_write_uint(thr, flags);
38861 duk_debug_write_hstring(thr, h_key);
38862 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
38863 h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
38864 if (h_getset) {
38865 duk_debug_write_hobject(thr, h_getset);
38866 } else {
38867 duk_debug_write_null(thr);
38868 }
38869 h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
38870 if (h_getset) {
38871 duk_debug_write_hobject(thr, h_getset);
38872 } else {
38873 duk_debug_write_null(thr);
38874 }
38875 } else {
38876 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
38877 duk_debug_write_tval(thr, tv);
38878 }
38879 return 1;
38880}
38881
38882DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
38883 duk_heaphdr *h;
38884
38885 DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
38886 DUK_UNREF(heap);
38887
38888 h = duk_debug_read_any_ptr(thr);
38889 if (!h) {
38890 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
38891 return;
38892 }
38893
38894 duk_debug_write_reply(thr);
38895
38896 /* As with all inspection code, we rely on the debug client providing
38897 * a valid, non-stale pointer: there's no portable way to safely
38898 * validate the pointer here.
38899 */
38900
38901 duk__debug_getinfo_flags_key(thr, "heapptr");
38902 duk_debug_write_heapptr(thr, h);
38903
38904 /* XXX: comes out as signed now */
38905 duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
38906 duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
38907#if defined(DUK_USE_REFERENCE_COUNTING)
38908 duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
38909#endif
38910#if 0 /* pruned */
38911 duk__debug_getinfo_bitmask(thr,
38912 duk__debug_getinfo_heaphdr_keys,
38913 duk__debug_getinfo_heaphdr_masks,
38915#endif
38916
38917 switch (DUK_HEAPHDR_GET_TYPE(h)) {
38918 case DUK_HTYPE_STRING: {
38919 duk_hstring *h_str;
38920
38921 h_str = (duk_hstring *) h;
38922 duk__debug_getinfo_bitmask(thr,
38923 duk__debug_getinfo_hstring_keys,
38924 duk__debug_getinfo_hstring_masks,
38926 duk__debug_getinfo_prop_uint(thr, "bytelen", DUK_HSTRING_GET_BYTELEN(h_str));
38927 duk__debug_getinfo_prop_uint(thr, "charlen", DUK_HSTRING_GET_CHARLEN(h_str));
38928 duk__debug_getinfo_prop_uint(thr, "hash", DUK_HSTRING_GET_HASH(h_str));
38929 duk__debug_getinfo_flags_key(thr, "data");
38930 duk_debug_write_hstring(thr, h_str);
38931 break;
38932 }
38933 case DUK_HTYPE_OBJECT: {
38934 duk_hobject *h_obj;
38935 duk_hobject *h_proto;
38936
38937 h_obj = (duk_hobject *) h;
38938 h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
38939
38940 /* duk_hobject specific fields. */
38941 duk__debug_getinfo_bitmask(thr,
38942 duk__debug_getinfo_hobject_keys,
38943 duk__debug_getinfo_hobject_masks,
38945 duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
38946 duk__debug_getinfo_flags_key(thr, "class_name");
38947 duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
38948 duk__debug_getinfo_flags_key(thr, "prototype");
38949 if (h_proto != NULL) {
38950 duk_debug_write_hobject(thr, h_proto);
38951 } else {
38952 duk_debug_write_null(thr);
38953 }
38954 duk__debug_getinfo_flags_key(thr, "props");
38955 duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
38956 duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
38957 duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
38958 duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
38959 duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
38960
38961 /* duk_hnativefunction specific fields. */
38962 if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
38963 duk_hnativefunction *h_fun;
38964 h_fun = (duk_hnativefunction *) h_obj;
38965
38966 duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
38967 duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
38968 duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATIVEFUNCTION_NARGS_VARARGS);
38969 /* Native function pointer may be different from a void pointer,
38970 * and we serialize it from memory directly now (no byte swapping etc).
38971 */
38972 duk__debug_getinfo_flags_key(thr, "funcptr");
38973 duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
38974 }
38975
38977 duk_hcompiledfunction *h_fun;
38978 duk_hbuffer *h_buf;
38979 h_fun = (duk_hcompiledfunction *) h_obj;
38980
38981 duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
38982 duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
38983 duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
38984 duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
38985 h_buf = (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun);
38986 if (h_buf != NULL) {
38987 duk__debug_getinfo_flags_key(thr, "data");
38988 duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
38989 }
38990 }
38991
38992 if (DUK_HOBJECT_IS_THREAD(h_obj)) {
38993 /* XXX: Currently no inspection of threads, e.g. value stack, call
38994 * stack, catch stack, etc.
38995 */
38996 duk_hthread *h_thr;
38997 h_thr = (duk_hthread *) h_obj;
38998 DUK_UNREF(h_thr);
38999 }
39000
39001 if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
39002 duk_hbufferobject *h_bufobj;
39003 h_bufobj = (duk_hbufferobject *) h_obj;
39004
39005 duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
39006 duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
39007 duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
39008 duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
39009 duk__debug_getinfo_prop_bool(thr, "is_view", (duk_uint_t) h_bufobj->is_view);
39010 if (h_bufobj->buf != NULL) {
39011 duk__debug_getinfo_flags_key(thr, "buffer");
39012 duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
39013 }
39014 }
39015 break;
39016 }
39017 case DUK_HTYPE_BUFFER: {
39018 duk_hbuffer *h_buf;
39019
39020 h_buf = (duk_hbuffer *) h;
39021 duk__debug_getinfo_bitmask(thr,
39022 duk__debug_getinfo_hbuffer_keys,
39023 duk__debug_getinfo_hbuffer_masks,
39025 duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
39026 duk__debug_getinfo_flags_key(thr, "dataptr");
39027 duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
39028 duk__debug_getinfo_flags_key(thr, "data");
39029 duk_debug_write_hbuffer(thr, h_buf); /* tolerates NULL h_buf */
39030 break;
39031 }
39032 default: {
39033 /* Since we already started writing the reply, just emit nothing. */
39034 DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
39035 }
39036 }
39037
39038 duk_debug_write_eom(thr);
39039}
39040
39041DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
39042 duk_heaphdr *h;
39043 duk_hobject *h_obj;
39044 duk_hstring *h_key;
39045 duk_propdesc desc;
39046
39047 DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
39048 DUK_UNREF(heap);
39049
39050 h = duk_debug_read_any_ptr(thr);
39051 if (!h) {
39052 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
39053 return;
39054 }
39055 h_key = duk_debug_read_hstring(thr);
39056 if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
39057 goto fail_args;
39058 }
39059 h_obj = (duk_hobject *) h;
39060
39061 if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
39062 duk_int_t virtual_idx;
39063 duk_bool_t rc;
39064
39065 /* To use the shared helper need the virtual index. */
39066 DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
39067 virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
39068 (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
39069
39070 duk_debug_write_reply(thr);
39071 rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
39072 DUK_ASSERT(rc == 1);
39073 DUK_UNREF(rc);
39074 duk_debug_write_eom(thr);
39075 } else {
39076 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
39077 }
39078 return;
39079
39080 fail_args:
39081 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
39082}
39083
39084DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
39085 duk_heaphdr *h;
39086 duk_hobject *h_obj;
39087 duk_uint_t idx, idx_start, idx_end;
39088
39089 DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
39090 DUK_UNREF(heap);
39091
39092 h = duk_debug_read_any_ptr(thr);
39093 idx_start = duk_debug_read_int(thr);
39094 idx_end = duk_debug_read_int(thr);
39095 if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
39096 goto fail_args;
39097 }
39098 h_obj = (duk_hobject *) h;
39099
39100 /* The index range space is conceptually the array part followed by the
39101 * entry part. Unlike normal enumeration all slots are exposed here as
39102 * is and return 'unused' if the slots are not in active use. In particular
39103 * the array part is included for the full a_size regardless of what the
39104 * array .length is.
39105 */
39106
39107 duk_debug_write_reply(thr);
39108 for (idx = idx_start; idx < idx_end; idx++) {
39109 if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
39110 break;
39111 }
39112 }
39113 duk_debug_write_eom(thr);
39114 return;
39115
39116 fail_args:
39117 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
39118}
39119
39120#endif /* DUK_USE_DEBUGGER_INSPECT */
39121
39122/*
39123 * Process incoming debug requests
39124 *
39125 * Individual request handlers can push temporaries on the value stack and
39126 * rely on duk__debug_process_message() to restore the value stack top
39127 * automatically.
39128 */
39129
39130/* Process one debug message. Automatically restore value stack top to its
39131 * entry value, so that individual message handlers don't need exact value
39132 * stack handling which is convenient.
39133 */
39134DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
39135 duk_context *ctx = (duk_context *) thr;
39136 duk_heap *heap;
39137 duk_uint8_t x;
39138 duk_int32_t cmd;
39139 duk_idx_t entry_top;
39140
39141 DUK_ASSERT(thr != NULL);
39142 heap = thr->heap;
39143 DUK_ASSERT(heap != NULL);
39144 DUK_UNREF(ctx);
39145
39146 entry_top = duk_get_top(ctx);
39147
39148 x = duk_debug_read_byte(thr);
39149 switch (x) {
39150 case DUK_DBG_IB_REQUEST: {
39151 cmd = duk_debug_read_int(thr);
39152 switch (cmd) {
39153 case DUK_DBG_CMD_BASICINFO: {
39154 duk__debug_handle_basic_info(thr, heap);
39155 break;
39156 }
39158 duk__debug_handle_trigger_status(thr, heap);
39159 break;
39160 }
39161 case DUK_DBG_CMD_PAUSE: {
39162 duk__debug_handle_pause(thr, heap);
39163 break;
39164 }
39165 case DUK_DBG_CMD_RESUME: {
39166 duk__debug_handle_resume(thr, heap);
39167 break;
39168 }
39171 case DUK_DBG_CMD_STEPOUT: {
39172 duk__debug_handle_step(thr, heap, cmd);
39173 break;
39174 }
39175 case DUK_DBG_CMD_LISTBREAK: {
39176 duk__debug_handle_list_break(thr, heap);
39177 break;
39178 }
39179 case DUK_DBG_CMD_ADDBREAK: {
39180 duk__debug_handle_add_break(thr, heap);
39181 break;
39182 }
39183 case DUK_DBG_CMD_DELBREAK: {
39184 duk__debug_handle_del_break(thr, heap);
39185 break;
39186 }
39187 case DUK_DBG_CMD_GETVAR: {
39188 duk__debug_handle_get_var(thr, heap);
39189 break;
39190 }
39191 case DUK_DBG_CMD_PUTVAR: {
39192 duk__debug_handle_put_var(thr, heap);
39193 break;
39194 }
39196 duk__debug_handle_get_call_stack(thr, heap);
39197 break;
39198 }
39199 case DUK_DBG_CMD_GETLOCALS: {
39200 duk__debug_handle_get_locals(thr, heap);
39201 break;
39202 }
39203 case DUK_DBG_CMD_EVAL: {
39204 duk__debug_handle_eval(thr, heap);
39205 break;
39206 }
39207 case DUK_DBG_CMD_DETACH: {
39208 /* The actual detached_cb call is postponed to message loop so
39209 * we don't need any special precautions here (just skip to EOM
39210 * on the already closed connection).
39211 */
39212 duk__debug_handle_detach(thr, heap);
39213 break;
39214 }
39215#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
39216 case DUK_DBG_CMD_DUMPHEAP: {
39217 duk__debug_handle_dump_heap(thr, heap);
39218 break;
39219 }
39220#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
39222 duk__debug_handle_get_bytecode(thr, heap);
39223 break;
39224 }
39226 duk__debug_handle_apprequest(thr, heap);
39227 break;
39228 }
39229#if defined(DUK_USE_DEBUGGER_INSPECT)
39231 duk__debug_handle_get_heap_obj_info(thr, heap);
39232 break;
39233 }
39235 duk__debug_handle_get_obj_prop_desc(thr, heap);
39236 break;
39237 }
39239 duk__debug_handle_get_obj_prop_desc_range(thr, heap);
39240 break;
39241 }
39242#endif /* DUK_USE_DEBUGGER_INSPECT */
39243 default: {
39244 DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
39245 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
39246 }
39247 } /* switch cmd */
39248 break;
39249 }
39250 case DUK_DBG_IB_REPLY: {
39251 DUK_D(DUK_DPRINT("debug reply, skipping"));
39252 break;
39253 }
39254 case DUK_DBG_IB_ERROR: {
39255 DUK_D(DUK_DPRINT("debug error, skipping"));
39256 break;
39257 }
39258 case DUK_DBG_IB_NOTIFY: {
39259 DUK_D(DUK_DPRINT("debug notify, skipping"));
39260 break;
39261 }
39262 default: {
39263 DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
39264 goto fail;
39265 }
39266 } /* switch initial byte */
39267
39268 DUK_ASSERT(duk_get_top(ctx) >= entry_top);
39269 duk_set_top(ctx, entry_top);
39270 duk__debug_skip_to_eom(thr);
39271 return;
39272
39273 fail:
39274 DUK_ASSERT(duk_get_top(ctx) >= entry_top);
39275 duk_set_top(ctx, entry_top);
39276 DUK__SET_CONN_BROKEN(thr, 1);
39277 return;
39278}
39279
39280DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
39281 if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
39282 duk_debug_send_status(thr);
39283 thr->heap->dbg_state_dirty = 0;
39284 }
39285}
39286
39287DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
39288 duk_context *ctx = (duk_context *) thr;
39289#if defined(DUK_USE_ASSERTIONS)
39290 duk_idx_t entry_top;
39291#endif
39292 duk_bool_t retval = 0;
39293
39294 DUK_ASSERT(thr != NULL);
39295 DUK_UNREF(ctx);
39296 DUK_ASSERT(thr->heap != NULL);
39297#if defined(DUK_USE_ASSERTIONS)
39298 entry_top = duk_get_top(ctx);
39299#endif
39300
39301 DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
39302 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
39303 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
39304 DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(ctx)));
39305
39306 /* thr->heap->dbg_detaching may be != 0 if a debugger write outside
39307 * the message loop caused a transport error and detach1() to run.
39308 */
39309 DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
39310 DUK_ASSERT(thr->heap->dbg_processing == 0);
39311 thr->heap->dbg_processing = 1;
39312
39313 /* Ensure dirty state causes a Status even if never process any
39314 * messages. This is expected by the bytecode executor when in
39315 * the running state.
39316 */
39317 duk__check_resend_status(thr);
39318
39319 for (;;) {
39320 /* Process messages until we're no longer paused or we peek
39321 * and see there's nothing to read right now.
39322 */
39323 DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(ctx)));
39324 DUK_ASSERT(thr->heap->dbg_processing == 1);
39325
39326 while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
39327 /* Detach is pending; can be triggered from outside the
39328 * debugger loop (e.g. Status notify write error) or by
39329 * previous message handling. Call detached callback
39330 * here, in a controlled state, to ensure a possible
39331 * reattach inside the detached_cb is handled correctly.
39332 *
39333 * Recheck for detach in a while loop: an immediate
39334 * reattach involves a call to duk_debugger_attach()
39335 * which writes a debugger handshake line immediately
39336 * inside the API call. If the transport write fails
39337 * for that handshake, we can immediately end up in a
39338 * "transport broken, detaching" case several times here.
39339 * Loop back until we're either cleanly attached or
39340 * fully detached.
39341 *
39342 * NOTE: Reset dbg_processing = 1 forcibly, in case we
39343 * re-attached; duk_debugger_attach() sets dbg_processing
39344 * to 0 at the moment.
39345 */
39346
39347 DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
39348
39349 duk__debug_do_detach2(thr->heap);
39350 thr->heap->dbg_processing = 1; /* may be set to 0 by duk_debugger_attach() inside callback */
39351
39352 DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
39353 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
39354 }
39355 DUK_ASSERT(thr->heap->dbg_detaching == 0); /* true even with reattach */
39356 DUK_ASSERT(thr->heap->dbg_processing == 1); /* even after a detach and possible reattach */
39357
39358 if (thr->heap->dbg_read_cb == NULL) {
39359 DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
39360 break;
39361 }
39362
39363 if (!thr->heap->dbg_paused || no_block) {
39364 if (!duk_debug_read_peek(thr)) {
39365 /* Note: peek cannot currently trigger a detach
39366 * so the dbg_detaching == 0 assert outside the
39367 * loop is correct.
39368 */
39369 DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
39370 break;
39371 }
39372 DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
39373 } else {
39374 DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
39375 }
39376
39377 duk__check_resend_status(thr);
39378 duk__debug_process_message(thr);
39379 duk__check_resend_status(thr);
39380
39381 retval = 1; /* processed one or more messages */
39382 }
39383
39384 DUK_ASSERT(thr->heap->dbg_detaching == 0);
39385 DUK_ASSERT(thr->heap->dbg_processing == 1);
39386 thr->heap->dbg_processing = 0;
39387
39388 /* As an initial implementation, read flush after exiting the message
39389 * loop. If transport is broken, this is a no-op (with debug logs).
39390 */
39391 duk_debug_read_flush(thr); /* this cannot initiate a detach */
39392 DUK_ASSERT(thr->heap->dbg_detaching == 0);
39393
39394 DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(ctx)));
39395
39396#if defined(DUK_USE_ASSERTIONS)
39397 /* Easy to get wrong, so assert for it. */
39398 DUK_ASSERT(entry_top == duk_get_top(ctx));
39399#endif
39400
39401 return retval;
39402}
39403
39404/*
39405 * Halt execution helper
39406 */
39407
39408/* Halt execution and enter a debugger message loop until execution is resumed
39409 * by the client. PC for the current activation may be temporarily decremented
39410 * so that the "current" instruction will be shown by the client. This helper
39411 * is callable from anywhere, also outside bytecode executor.
39412 */
39413
39414DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
39415 duk_activation *act;
39417 duk_instr_t *old_pc = NULL;
39418
39419 DUK_ASSERT(thr != NULL);
39420 DUK_ASSERT(thr->heap != NULL);
39421 DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39422 DUK_ASSERT(thr->heap->dbg_processing == 0);
39423
39424 DUK_HEAP_SET_PAUSED(thr->heap);
39425
39427
39428 /* NOTE: act may be NULL if an error is thrown outside of any activation,
39429 * which may happen in the case of, e.g. syntax errors.
39430 */
39431
39432 /* Decrement PC if that was requested, this requires a PC sync. */
39433 if (act != NULL) {
39435 old_pc = act->curr_pc;
39437
39438 /* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
39439 * guaranteed to be a non-NULL Ecmascript function.
39440 */
39441 DUK_ASSERT(act->curr_pc == NULL ||
39442 (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)));
39443 if (use_prev_pc &&
39444 act->curr_pc != NULL &&
39446 act->curr_pc--;
39447 }
39448 }
39449
39450 /* Process debug messages until we are no longer paused. */
39451
39452 /* NOTE: This is a bit fragile. It's important to ensure that
39453 * duk_debug_process_messages() never throws an error or
39454 * act->curr_pc will never be reset.
39455 */
39456
39457 thr->heap->dbg_state_dirty = 1;
39458 while (thr->heap->dbg_paused) {
39459 DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39460 DUK_ASSERT(thr->heap->dbg_processing);
39461 duk_debug_process_messages(thr, 0 /*no_block*/);
39462 }
39463
39464 /* XXX: Decrementing and restoring act->curr_pc works now, but if the
39465 * debugger message loop gains the ability to adjust the current PC
39466 * (e.g. a forced jump) restoring the PC here will break. Another
39467 * approach would be to use a state flag for the "decrement 1 from
39468 * topmost activation's PC" and take it into account whenever dealing
39469 * with PC values.
39470 */
39471 if (act != NULL) {
39472 act->curr_pc = old_pc; /* restore PC */
39473 }
39474}
39475
39476/*
39477 * Breakpoint management
39478 */
39479
39480DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
39481 duk_heap *heap;
39482 duk_breakpoint *b;
39483
39484 /* Caller must trigger recomputation of active breakpoint list. To
39485 * ensure stale values are not used if that doesn't happen, clear the
39486 * active breakpoint list here.
39487 */
39488
39489 DUK_ASSERT(thr != NULL);
39490 DUK_ASSERT(filename != NULL);
39491 heap = thr->heap;
39492 DUK_ASSERT(heap != NULL);
39493
39494 if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
39495 DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
39496 (duk_heaphdr *) filename, (long) line));
39497 return -1;
39498 }
39499 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
39500 b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
39501 b->filename = filename;
39502 b->line = line;
39503 DUK_HSTRING_INCREF(thr, filename);
39504
39505 return heap->dbg_breakpoint_count - 1; /* index */
39506}
39507
39508DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
39509 duk_heap *heap;
39510 duk_hstring *h;
39511 duk_breakpoint *b;
39512 duk_size_t move_size;
39513
39514 /* Caller must trigger recomputation of active breakpoint list. To
39515 * ensure stale values are not used if that doesn't happen, clear the
39516 * active breakpoint list here.
39517 */
39518
39519 DUK_ASSERT(thr != NULL);
39520 heap = thr->heap;
39521 DUK_ASSERT(heap != NULL);
39522 DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39523 DUK_ASSERT_DISABLE(breakpoint_index >= 0); /* unsigned */
39524
39525 if (breakpoint_index >= heap->dbg_breakpoint_count) {
39526 DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
39527 return 0;
39528 }
39529 b = heap->dbg_breakpoints + breakpoint_index;
39530
39531 h = b->filename;
39532 DUK_ASSERT(h != NULL);
39533
39534 move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
39535 if (move_size > 0) {
39536 DUK_MEMMOVE((void *) b,
39537 (const void *) (b + 1),
39538 (size_t) move_size);
39539 }
39540 heap->dbg_breakpoint_count--;
39541 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
39542
39543 DUK_HSTRING_DECREF(thr, h); /* side effects */
39544 DUK_UNREF(h); /* w/o refcounting */
39545
39546 /* Breakpoint entries above the used area are left as garbage. */
39547
39548 return 1;
39549}
39550
39551#undef DUK__SET_CONN_BROKEN
39552
39553#else /* DUK_USE_DEBUGGER_SUPPORT */
39554
39555/* No debugger support. */
39556
39557#endif /* DUK_USE_DEBUGGER_SUPPORT */
39558/*
39559 * Augmenting errors at their creation site and their throw site.
39560 *
39561 * When errors are created, traceback data is added by built-in code
39562 * and a user error handler (if defined) can process or replace the
39563 * error. Similarly, when errors are thrown, a user error handler
39564 * (if defined) can process or replace the error.
39565 *
39566 * Augmentation and other processing at error creation time is nice
39567 * because an error is only created once, but it may be thrown and
39568 * rethrown multiple times. User error handler registered for processing
39569 * an error at its throw site must be careful to handle rethrowing in
39570 * a useful manner.
39571 *
39572 * Error augmentation may throw an internal error (e.g. alloc error).
39573 *
39574 * Ecmascript allows throwing any values, so all values cannot be
39575 * augmented. Currently, the built-in augmentation at error creation
39576 * only augments error values which are Error instances (= have the
39577 * built-in Error.prototype in their prototype chain) and are also
39578 * extensible. User error handlers have no limitations in this respect.
39579 */
39580
39581/* include removed: duk_internal.h */
39582
39583/*
39584 * Helper for calling a user error handler.
39585 *
39586 * 'thr' must be the currently active thread; the error handler is called
39587 * in its context. The valstack of 'thr' must have the error value on
39588 * top, and will be replaced by another error value based on the return
39589 * value of the error handler.
39590 *
39591 * The helper calls duk_handle_call() recursively in protected mode.
39592 * Before that call happens, no longjmps should happen; as a consequence,
39593 * we must assume that the valstack contains enough temporary space for
39594 * arguments and such.
39595 *
39596 * While the error handler runs, any errors thrown will not trigger a
39597 * recursive error handler call (this is implemented using a heap level
39598 * flag which will "follow" through any coroutines resumed inside the
39599 * error handler). If the error handler is not callable or throws an
39600 * error, the resulting error replaces the original error (for Duktape
39601 * internal errors, duk_error_throw.c further substitutes this error with
39602 * a DoubleError which is not ideal). This would be easy to change and
39603 * even signal to the caller.
39604 *
39605 * The user error handler is stored in 'Duktape.errCreate' or
39606 * 'Duktape.errThrow' depending on whether we're augmenting the error at
39607 * creation or throw time. There are several alternatives to this approach,
39608 * see doc/error-objects.rst for discussion.
39609 *
39610 * Note: since further longjmp()s may occur while calling the error handler
39611 * (for many reasons, e.g. a labeled 'break' inside the handler), the
39612 * caller can make no assumptions on the thr->heap->lj state after the
39613 * call (this affects especially duk_error_throw.c). This is not an issue
39614 * as long as the caller writes to the lj state only after the error handler
39615 * finishes.
39616 */
39617
39618#if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
39620 duk_context *ctx = (duk_context *) thr;
39621 duk_tval *tv_hnd;
39622 duk_small_uint_t call_flags;
39623 duk_int_t rc;
39624
39625 DUK_ASSERT(thr != NULL);
39626 DUK_ASSERT(thr->heap != NULL);
39627 DUK_ASSERT_DISABLE(stridx_cb >= 0); /* unsigned */
39628 DUK_ASSERT(stridx_cb < DUK_HEAP_NUM_STRINGS);
39629
39631 DUK_DD(DUK_DDPRINT("recursive call to error handler, ignore"));
39632 return;
39633 }
39634
39635 /*
39636 * Check whether or not we have an error handler.
39637 *
39638 * We must be careful of not triggering an error when looking up the
39639 * property. For instance, if the property is a getter, we don't want
39640 * to call it, only plain values are allowed. The value, if it exists,
39641 * is not checked. If the value is not a function, a TypeError happens
39642 * when it is called and that error replaces the original one.
39643 */
39644
39645 DUK_ASSERT_VALSTACK_SPACE(thr, 4); /* 3 entries actually needed below */
39646
39647 /* [ ... errval ] */
39648
39649 if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
39650 /* When creating built-ins, some of the built-ins may not be set
39651 * and we want to tolerate that when throwing errors.
39652 */
39653 DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
39654 return;
39655 }
39658 DUK_HTHREAD_GET_STRING(thr, stridx_cb));
39659 if (tv_hnd == NULL) {
39660 DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
39661 (duk_tval *) tv_hnd));
39662 return;
39663 }
39664 DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
39665 (duk_tval *) tv_hnd));
39666 duk_push_tval(ctx, tv_hnd);
39667
39668 /* [ ... errval errhandler ] */
39669
39670 duk_insert(ctx, -2); /* -> [ ... errhandler errval ] */
39671 duk_push_undefined(ctx);
39672 duk_insert(ctx, -2); /* -> [ ... errhandler undefined(= this) errval ] */
39673
39674 /* [ ... errhandler undefined errval ] */
39675
39676 /*
39677 * DUK_CALL_FLAG_IGNORE_RECLIMIT causes duk_handle_call() to ignore C
39678 * recursion depth limit (and won't increase it either). This is
39679 * dangerous, but useful because it allows the error handler to run
39680 * even if the original error is caused by C recursion depth limit.
39681 *
39682 * The heap level DUK_HEAP_FLAG_ERRHANDLER_RUNNING is set for the
39683 * duration of the error handler and cleared afterwards. This flag
39684 * prevents the error handler from running recursively. The flag is
39685 * heap level so that the flag properly controls even coroutines
39686 * launched by an error handler. Since the flag is heap level, it is
39687 * critical to restore it correctly.
39688 *
39689 * We ignore errors now: a success return and an error value both
39690 * replace the original error value. (This would be easy to change.)
39691 */
39692
39693 DUK_ASSERT(!DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap)); /* since no recursive error handler calls */
39695
39696 call_flags = DUK_CALL_FLAG_IGNORE_RECLIMIT; /* ignore reclimit, not constructor */
39697
39699 1, /* num args */
39700 call_flags); /* call_flags */
39701 DUK_UNREF(rc); /* no need to check now: both success and error are OK */
39702
39705
39706 /* [ ... errval ] */
39707}
39708#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
39709
39710/*
39711 * Add ._Tracedata to an error on the stack top.
39712 */
39713
39714#if defined(DUK_USE_TRACEBACKS)
39715DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
39716 duk_context *ctx = (duk_context *) thr;
39718 duk_int_t i, i_min;
39719 duk_uarridx_t arr_idx;
39720 duk_double_t d;
39721
39722 DUK_ASSERT(thr != NULL);
39723 DUK_ASSERT(thr_callstack != NULL);
39724 DUK_ASSERT(ctx != NULL);
39725
39726 /* [ ... error ] */
39727
39728 /*
39729 * The traceback format is pretty arcane in an attempt to keep it compact
39730 * and cheap to create. It may change arbitrarily from version to version.
39731 * It should be decoded/accessed through version specific accessors only.
39732 *
39733 * See doc/error-objects.rst.
39734 */
39735
39736 DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
39737 (duk_tval *) duk_get_tval(ctx, -1)));
39738
39739 duk_push_array(ctx); /* XXX: specify array size, as we know it */
39740 arr_idx = 0;
39741
39742 /* Compiler SyntaxErrors (and other errors) come first, and are
39743 * blamed by default (not flagged "noblame").
39744 */
39745 if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
39747 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39748 arr_idx++;
39749
39750 duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line); /* (flags<<32) + (line), flags = 0 */
39751 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39752 arr_idx++;
39753 }
39754
39755 /* Filename/line from C macros (__FILE__, __LINE__) are added as an
39756 * entry with a special format: (string, number). The number contains
39757 * the line and flags.
39758 */
39759
39760 /* XXX: optimize: allocate an array part to the necessary size (upwards
39761 * estimate) and fill in the values directly into the array part; finally
39762 * update 'length'.
39763 */
39764
39765 /* XXX: using duk_put_prop_index() would cause obscure error cases when Array.prototype
39766 * has write-protected array index named properties. This was seen as DoubleErrors
39767 * in e.g. some test262 test cases. Using duk_xdef_prop_index() is better but heavier.
39768 * The best fix is to fill in the tracedata directly into the array part. There are
39769 * no side effect concerns if the array part is allocated directly and only INCREFs
39770 * happen after that.
39771 */
39772
39773 /* [ ... error arr ] */
39774
39775 if (c_filename) {
39776 duk_push_string(ctx, c_filename);
39777 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39778 arr_idx++;
39779
39780 d = (noblame_fileline ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
39781 (duk_double_t) c_line;
39782 duk_push_number(ctx, d);
39783 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39784 arr_idx++;
39785 }
39786
39787 /* traceback depth doesn't take into account the filename/line
39788 * special handling above (intentional)
39789 */
39791 i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
39792 DUK_ASSERT(i_min >= 0);
39793
39794 /* [ ... error arr ] */
39795
39796 DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
39797 for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
39798 duk_uint32_t pc;
39799
39800 /*
39801 * Note: each API operation potentially resizes the callstack,
39802 * so be careful to re-lookup after every operation. Currently
39803 * these is no issue because we don't store a temporary 'act'
39804 * pointer at all. (This would be a non-issue if we operated
39805 * directly on the array part.)
39806 */
39807
39808 /* [... arr] */
39809
39810 DUK_ASSERT_DISABLE(thr_callstack->callstack[i].pc >= 0); /* unsigned */
39811
39812 /* Add function object. */
39813 duk_push_tval(ctx, &(thr_callstack->callstack + i)->tv_func);
39814 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39815 arr_idx++;
39816
39817 /* Add a number containing: pc, activation flags.
39818 *
39819 * PC points to next instruction, find offending PC. Note that
39820 * PC == 0 for native code.
39821 */
39822 pc = duk_hthread_get_act_prev_pc(thr_callstack, thr_callstack->callstack + i);
39823 DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
39824 DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
39825 d = ((duk_double_t) thr_callstack->callstack[i].flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
39826 duk_push_number(ctx, d); /* -> [... arr num] */
39827 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39828 arr_idx++;
39829 }
39830
39831 /* XXX: set with duk_hobject_set_length() when tracedata is filled directly */
39832 duk_push_uint(ctx, (duk_uint_t) arr_idx);
39834
39835 /* [ ... error arr ] */
39836
39837 duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_TRACEDATA); /* -> [ ... error ] */
39838}
39839#endif /* DUK_USE_TRACEBACKS */
39840
39841/*
39842 * Add .fileName and .lineNumber to an error on the stack top.
39843 */
39844
39845#if !defined(DUK_USE_TRACEBACKS)
39846DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
39847 duk_context *ctx;
39848#if defined(DUK_USE_ASSERTIONS)
39849 duk_int_t entry_top;
39850#endif
39851
39852 ctx = (duk_context *) thr;
39853#if defined(DUK_USE_ASSERTIONS)
39854 entry_top = duk_get_top(ctx);
39855#endif
39856
39857 /*
39858 * If tracebacks are disabled, 'fileName' and 'lineNumber' are added
39859 * as plain own properties. Since Error.prototype has accessors of
39860 * the same name, we need to define own properties directly (cannot
39861 * just use e.g. duk_put_prop_stridx). Existing properties are not
39862 * overwritten in case they already exist.
39863 */
39864
39865 if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
39866 /* Compiler SyntaxError (or other error) gets the primary blame.
39867 * Currently no flag to prevent blaming.
39868 */
39871 } else if (c_filename && !noblame_fileline) {
39872 /* C call site gets blamed next, unless flagged not to do so.
39873 * XXX: file/line is disabled in minimal builds, so disable this
39874 * too when appropriate.
39875 */
39876 duk_push_int(ctx, c_line);
39877 duk_push_string(ctx, c_filename);
39878 } else {
39879 /* Finally, blame the innermost callstack entry which has a
39880 * .fileName property.
39881 */
39883 duk_int_t i, i_min;
39884 duk_uint32_t ecma_line;
39885
39887 i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
39888 DUK_ASSERT(i_min >= 0);
39889
39890 DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
39891 for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
39892 duk_activation *act;
39893 duk_hobject *func;
39894 duk_uint32_t pc;
39895
39896 DUK_UNREF(pc);
39897 act = thr_callstack->callstack + i;
39898 DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
39899
39900 func = DUK_ACT_GET_FUNC(act);
39901 if (func == NULL) {
39902 /* Lightfunc, not blamed now. */
39903 continue;
39904 }
39905
39906 /* PC points to next instruction, find offending PC,
39907 * PC == 0 for native code.
39908 */
39909 pc = duk_hthread_get_act_prev_pc(thr, act); /* thr argument only used for thr->heap, so specific thread doesn't matter */
39910 DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
39911 DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
39912 act = NULL; /* invalidated by pushes, so get out of the way */
39913
39914 duk_push_hobject(ctx, func);
39915
39916 /* [ ... error func ] */
39917
39919 if (!duk_is_string(ctx, -1)) {
39920 duk_pop_2(ctx);
39921 continue;
39922 }
39923
39924 /* [ ... error func fileName ] */
39925
39926 ecma_line = 0;
39927#if defined(DUK_USE_PC2LINE)
39929 ecma_line = duk_hobject_pc2line_query(ctx, -2, (duk_uint_fast32_t) pc);
39930 } else {
39931 /* Native function, no relevant lineNumber. */
39932 }
39933#endif /* DUK_USE_PC2LINE */
39934 duk_push_u32(ctx, ecma_line);
39935
39936 /* [ ... error func fileName lineNumber ] */
39937
39938 duk_replace(ctx, -3);
39939
39940 /* [ ... error lineNumber fileName ] */
39941 goto define_props;
39942 }
39943
39944 /* No activation matches, use undefined for both .fileName and
39945 * .lineNumber (matches what we do with a _Tracedata based
39946 * no-match lookup.
39947 */
39948 duk_push_undefined(ctx);
39950 }
39951
39952 define_props:
39953 /* [ ... error lineNumber fileName ] */
39954#if defined(DUK_USE_ASSERTIONS)
39955 DUK_ASSERT(duk_get_top(ctx) == entry_top + 2);
39956#endif
39959}
39960#endif /* !DUK_USE_TRACEBACKS */
39961
39962/*
39963 * Add line number to a compiler error.
39964 */
39965
39967 duk_context *ctx;
39968
39969 /* Append a "(line NNN)" to the "message" property of any error
39970 * thrown during compilation. Usually compilation errors are
39971 * SyntaxErrors but they can also be out-of-memory errors and
39972 * the like.
39973 */
39974
39975 /* [ ... error ] */
39976
39977 ctx = (duk_context *) thr;
39978 DUK_ASSERT(duk_is_object(ctx, -1));
39979
39980 if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
39981 return;
39982 }
39983
39984 DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
39985 (duk_tval *) duk_get_tval(ctx, -1)));
39986
39988 duk_push_sprintf(ctx, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
39989 duk_concat(ctx, 2);
39991 } else {
39992 duk_pop(ctx);
39993 }
39994
39995 DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
39996 (duk_tval *) duk_get_tval(ctx, -1)));
39997}
39998
39999/*
40000 * Augment an error being created using Duktape specific properties
40001 * like _Tracedata or .fileName/.lineNumber.
40002 */
40003
40004#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
40005DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_int_t noblame_fileline, duk_hobject *obj) {
40006 duk_context *ctx = (duk_context *) thr;
40007#if defined(DUK_USE_ASSERTIONS)
40008 duk_int_t entry_top;
40009#endif
40010
40011#if defined(DUK_USE_ASSERTIONS)
40012 entry_top = duk_get_top(ctx);
40013#endif
40014 DUK_ASSERT(obj != NULL);
40015
40016 DUK_UNREF(obj); /* unreferenced w/o tracebacks */
40017 DUK_UNREF(ctx); /* unreferenced w/o asserts */
40018
40020
40021#if defined(DUK_USE_TRACEBACKS)
40022 /* If tracebacks are enabled, the '_Tracedata' property is the only
40023 * thing we need: 'fileName' and 'lineNumber' are virtual properties
40024 * which use '_Tracedata'.
40025 */
40027 DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
40028 } else {
40029 duk__add_traceback(thr, thr_callstack, c_filename, c_line, noblame_fileline);
40030 }
40031#else
40032 /* Without tracebacks the concrete .fileName and .lineNumber need
40033 * to be added directly.
40034 */
40035 duk__add_fileline(thr, thr_callstack, c_filename, c_line, noblame_fileline);
40036#endif
40037
40038#if defined(DUK_USE_ASSERTIONS)
40039 DUK_ASSERT(duk_get_top(ctx) == entry_top);
40040#endif
40041}
40042#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
40043
40044/*
40045 * Augment an error at creation time with _Tracedata/fileName/lineNumber
40046 * and allow a user error handler (if defined) to process/replace the error.
40047 * The error to be augmented is at the stack top.
40048 *
40049 * thr: thread containing the error value
40050 * thr_callstack: thread which should be used for generating callstack etc.
40051 * c_filename: C __FILE__ related to the error
40052 * c_line: C __LINE__ related to the error
40053 * noblame_fileline: if true, don't fileName/line as error source, otherwise use traceback
40054 * (needed because user code filename/line are reported but internal ones
40055 * are not)
40056 *
40057 * XXX: rename noblame_fileline to flags field; combine it to some existing
40058 * field (there are only a few call sites so this may not be worth it).
40059 */
40060
40061#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
40062DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
40063 duk_context *ctx = (duk_context *) thr;
40064 duk_hobject *obj;
40065
40066 DUK_ASSERT(thr != NULL);
40067 DUK_ASSERT(thr_callstack != NULL);
40068 DUK_ASSERT(ctx != NULL);
40069
40070 /* [ ... error ] */
40071
40072 /*
40073 * Criteria for augmenting:
40074 *
40075 * - augmentation enabled in build (naturally)
40076 * - error value internal prototype chain contains the built-in
40077 * Error prototype object (i.e. 'val instanceof Error')
40078 *
40079 * Additional criteria for built-in augmenting:
40080 *
40081 * - error value is an extensible object
40082 */
40083
40084 obj = duk_get_hobject(ctx, -1);
40085 if (!obj) {
40086 DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
40087 return;
40088 }
40089 if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
40090 /* If the value has a prototype loop, it's critical not to
40091 * throw here. Instead, assume the value is not to be
40092 * augmented.
40093 */
40094 DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
40095 return;
40096 }
40097 if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
40098 DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
40099 duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, noblame_fileline, obj);
40100 } else {
40101 DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
40103
40104 /* [ ... error ] */
40105
40106#if defined(DUK_USE_ERRCREATE)
40108#endif
40109}
40110#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
40111
40112/*
40113 * Augment an error at throw time; allow a user error handler (if defined)
40114 * to process/replace the error. The error to be augmented is at the
40115 * stack top.
40116 */
40117
40118#if defined(DUK_USE_AUGMENT_ERROR_THROW)
40120#if defined(DUK_USE_ERRTHROW)
40122#endif /* DUK_USE_ERRTHROW */
40123}
40124#endif /* DUK_USE_AUGMENT_ERROR_THROW */
40125/*
40126 * Do a longjmp call, calling the fatal error handler if no
40127 * catchpoint exists.
40128 */
40129
40130/* include removed: duk_internal.h */
40131
40133 DUK_ASSERT(thr != NULL);
40134
40135 DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
40136 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
40137 &thr->heap->lj.value1, &thr->heap->lj.value2));
40138
40139#if !defined(DUK_USE_CPP_EXCEPTIONS)
40140 /* If we don't have a jmpbuf_ptr, there is little we can do
40141 * except panic. The caller's expectation is that we never
40142 * return.
40143 *
40144 * With C++ exceptions we now just propagate an uncaught error
40145 * instead of invoking the fatal error handler. Because there's
40146 * a dummy jmpbuf for C++ exceptions now, this could be changed.
40147 */
40148 if (!thr->heap->lj.jmpbuf_ptr) {
40149
40150 DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
40151 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
40152 &thr->heap->lj.value1, &thr->heap->lj.value2));
40153
40154 duk_fatal((duk_context *) thr, DUK_ERR_UNCAUGHT_ERROR, "uncaught error");
40156 }
40157#endif /* DUK_USE_CPP_EXCEPTIONS */
40158
40159#if defined(DUK_USE_CPP_EXCEPTIONS)
40160 {
40161 duk_internal_exception exc; /* dummy */
40162 throw exc;
40163 }
40164#else /* DUK_USE_CPP_EXCEPTIONS */
40166#endif /* DUK_USE_CPP_EXCEPTIONS */
40167
40169}
40170/*
40171 * Error helpers
40172 */
40173
40174/* include removed: duk_internal.h */
40175
40176/*
40177 * Helper to walk the thread chain and see if there is an active error
40178 * catcher. Protected calls or finally blocks aren't considered catching.
40179 */
40180
40181#if defined(DUK_USE_DEBUGGER_SUPPORT) && \
40182 (defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT))
40183DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
40184 /*
40185 * XXX: As noted above, a protected API call won't be counted as a
40186 * catcher. This is usually convenient, e.g. in the case of a top-
40187 * level duk_pcall(), but may not always be desirable. Perhaps add an
40188 * argument to treat them as catchers?
40189 */
40190
40191 duk_size_t i;
40192
40193 DUK_ASSERT(thr != NULL);
40194
40195 while (thr != NULL) {
40196 for (i = 0; i < thr->catchstack_top; i++) {
40197 duk_catcher *cat = thr->catchstack + i;
40198 if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
40199 return 1; /* all we need to know */
40200 }
40201 }
40202 thr = thr->resumer;
40203 }
40204 return 0;
40205}
40206#endif /* DUK_USE_DEBUGGER_SUPPORT && (DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) */
40207
40208/*
40209 * Get prototype object for an integer error code.
40210 */
40211
40213 switch (code) {
40214 case DUK_ERR_EVAL_ERROR:
40222 case DUK_ERR_TYPE_ERROR:
40224 case DUK_ERR_URI_ERROR:
40227 /* XXX: more specific error classes? */
40232 case DUK_ERR_API_ERROR:
40233 case DUK_ERR_ERROR:
40234 default:
40236 }
40237}
40238
40239/*
40240 * Exposed helper for setting up heap longjmp state.
40241 */
40242
40244#if defined(DUK_USE_DEBUGGER_SUPPORT)
40245 /* If something is thrown with the debugger attached and nobody will
40246 * catch it, execution is paused before the longjmp, turning over
40247 * control to the debug client. This allows local state to be examined
40248 * before the stack is unwound. Errors are not intercepted when debug
40249 * message loop is active (e.g. for Eval).
40250 */
40251
40252 /* XXX: Allow customizing the pause and notify behavior at runtime
40253 * using debugger runtime flags. For now the behavior is fixed using
40254 * config options.
40255 */
40256#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
40257 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) &&
40258 !thr->heap->dbg_processing &&
40259 lj_type == DUK_LJ_TYPE_THROW) {
40260 duk_context *ctx = (duk_context *) thr;
40262 duk_hobject *h_obj;
40263
40264 /* Don't intercept a DoubleError, we may have caused the initial double
40265 * fault and attempting to intercept it will cause us to be called
40266 * recursively and exhaust the C stack.
40267 */
40268 h_obj = duk_get_hobject(ctx, -1);
40269 if (h_obj == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
40270 DUK_D(DUK_DPRINT("built-in DoubleError instance thrown, not intercepting"));
40271 goto skip_throw_intercept;
40272 }
40273
40274 DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
40275
40276 fatal = !duk__have_active_catcher(thr);
40277
40278#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
40279 /* Report it to the debug client */
40280 duk_debug_send_throw(thr, fatal);
40281#endif
40282
40283#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
40284 if (fatal) {
40285 DUK_D(DUK_DPRINT("throw will be fatal, halt before longjmp"));
40286 duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
40287 }
40288#endif
40289 }
40290
40291 skip_throw_intercept:
40292#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT */
40293#endif /* DUK_USE_DEBUGGER_SUPPORT */
40294
40295 thr->heap->lj.type = lj_type;
40296
40297 DUK_ASSERT(thr->valstack_top > thr->valstack);
40298 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, thr->valstack_top - 1); /* side effects */
40299
40300 duk_pop((duk_context *) thr);
40301}
40302/*
40303 * Create and throw an Ecmascript error object based on a code and a message.
40304 *
40305 * Used when we throw errors internally. Ecmascript generated error objects
40306 * are created by Ecmascript code, and the throwing is handled by the bytecode
40307 * executor.
40309
40310/* include removed: duk_internal.h */
40311
40312/*
40313 * Create and throw an error (originating from Duktape internally)
40314 *
40315 * Push an error object on top of the stack, possibly throw augmenting
40316 * the error, and finally longjmp.
40317 *
40318 * If an error occurs while we're dealing with the current error, we might
40319 * enter an infinite recursion loop. This is prevented by detecting a
40320 * "double fault" through the heap->handling_error flag; the recursion
40321 * then stops at the second level.
40322 */
40323
40324#ifdef DUK_USE_VERBOSE_ERRORS
40325DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
40326#else
40328#endif
40329 duk_context *ctx = (duk_context *) thr;
40330 duk_bool_t double_error = thr->heap->handling_error;
40331
40332#ifdef DUK_USE_VERBOSE_ERRORS
40333 DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
40334 (long) code, (const char *) msg,
40335 (const char *) filename, (long) line));
40336#else
40337 DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
40338#endif
40339
40340 DUK_ASSERT(thr != NULL);
40341 DUK_ASSERT(ctx != NULL);
40342
40343 thr->heap->handling_error = 1;
40344
40345 if (!double_error) {
40346 /* Allow headroom for calls during error handling (see GH-191).
40347 * We allow space for 10 additional recursions, with one extra
40348 * for, e.g. a print() call at the deepest level.
40349 */
40352 }
40353
40354 DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11); /* just making sure */
40355
40356 /* Sync so that augmentation sees up-to-date activations, NULL
40357 * thr->ptr_curr_pc so that it's not used if side effects occur
40358 * in augmentation or longjmp handling.
40359 */
40361
40362 /*
40363 * Create and push an error object onto the top of stack.
40364 * If a "double error" occurs, use a fixed error instance
40365 * to avoid further trouble.
40366 */
40367
40368 /* XXX: if attempt to push beyond allocated valstack, this double fault
40369 * handling fails miserably. We should really write the double error
40370 * directly to thr->heap->lj.value1 and avoid valstack use entirely.
40371 */
40372
40373 if (double_error) {
40374 if (thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
40375 DUK_D(DUK_DPRINT("double fault detected -> push built-in fixed 'double error' instance"));
40377 } else {
40378 DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
40379 "-> push the error code as a number"));
40380 duk_push_int(ctx, (duk_int_t) code);
40381 }
40382 } else {
40383 /* Error object is augmented at its creation here. */
40384 duk_require_stack(ctx, 1);
40385 /* XXX: unnecessary '%s' formatting here, but cannot use
40386 * 'msg' as a format string directly.
40387 */
40388#ifdef DUK_USE_VERBOSE_ERRORS
40391 filename,
40392 line,
40393 "%s",
40394 (const char *) msg);
40395#else
40398 NULL,
40399 0,
40400 NULL);
40401#endif
40402 }
40403
40404 /*
40405 * Augment error (throw time), unless alloc/double error
40406 */
40407
40408 if (double_error || code == DUK_ERR_ALLOC_ERROR) {
40409 DUK_D(DUK_DPRINT("alloc or double error: skip throw augmenting to avoid further trouble"));
40410 } else {
40411#if defined(DUK_USE_AUGMENT_ERROR_THROW)
40412 DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
40413 (duk_tval *) duk_get_tval(ctx, -1)));
40415#endif
40416 }
40417
40418 /*
40419 * Finally, longjmp
40420 */
40423
40424 thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX; /* reset callstack limit */
40425 thr->heap->handling_error = 0;
40426
40427 DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
40428 (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
40429
40430 duk_err_longjmp(thr);
40432}
40433
40434/*
40435 * Helper for C function call negative return values.
40436 */
40437
40439 duk_context *ctx = (duk_context *) thr;
40440 const char *msg;
40441 duk_errcode_t code;
40442
40443 DUK_ASSERT(thr != NULL);
40444 DUK_ASSERT(rc < 0);
40445
40446 /* XXX: this generates quite large code - perhaps select the error
40447 * class based on the code and then just use the error 'name'?
40448 */
40449 /* XXX: shared strings */
40450
40451 code = -rc;
40452
40453 switch (rc) {
40454 case DUK_RET_UNIMPLEMENTED_ERROR: msg = "unimplemented"; break;
40455 case DUK_RET_UNSUPPORTED_ERROR: msg = "unsupported"; break;
40456 case DUK_RET_INTERNAL_ERROR: msg = "internal"; break;
40457 case DUK_RET_ALLOC_ERROR: msg = "alloc"; break;
40458 case DUK_RET_ASSERTION_ERROR: msg = "assertion"; break;
40459 case DUK_RET_API_ERROR: msg = "api"; break;
40460 case DUK_RET_UNCAUGHT_ERROR: msg = "uncaught"; break;
40461 case DUK_RET_ERROR: msg = "error"; break;
40462 case DUK_RET_EVAL_ERROR: msg = "eval"; break;
40463 case DUK_RET_RANGE_ERROR: msg = "range"; break;
40464 case DUK_RET_REFERENCE_ERROR: msg = "reference"; break;
40465 case DUK_RET_SYNTAX_ERROR: msg = "syntax"; break;
40466 case DUK_RET_TYPE_ERROR: msg = "type"; break;
40467 case DUK_RET_URI_ERROR: msg = "uri"; break;
40468 default: msg = "unknown"; break;
40469 }
40470
40471 DUK_ASSERT(msg != NULL);
40472
40473 /*
40474 * The __FILE__ and __LINE__ information is intentionally not used in the
40475 * creation of the error object, as it isn't useful in the tracedata. The
40476 * tracedata still contains the function which returned the negative return
40477 * code, and having the file/line of this function isn't very useful.
40478 */
40479
40480 duk_error_raw(ctx, code, NULL, 0, "%s error (rc %ld)", (const char *) msg, (long) rc);
40482}
40483/*
40484 * duk_hbuffer allocation and freeing.
40485 */
40486
40487/* include removed: duk_internal.h */
40488
40489/* Allocate a new duk_hbuffer of a certain type and return a pointer to it
40490 * (NULL on error). Write buffer data pointer to 'out_bufdata' (only if
40491 * allocation successful).
40492 */
40493DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
40494 duk_hbuffer *res = NULL;
40495 duk_size_t header_size;
40496 duk_size_t alloc_size;
40497
40498 DUK_ASSERT(heap != NULL);
40499 DUK_ASSERT(out_bufdata != NULL);
40500
40501 DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
40502
40503 /* Size sanity check. Should not be necessary because caller is
40504 * required to check this, but we don't want to cause a segfault
40505 * if the size wraps either in duk_size_t computation or when
40506 * storing the size in a 16-bit field.
40507 */
40508 if (size > DUK_HBUFFER_MAX_BYTELEN) {
40509 DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
40510 return NULL; /* no need to write 'out_bufdata' */
40511 }
40512
40513 if (flags & DUK_BUF_FLAG_EXTERNAL) {
40514 header_size = sizeof(duk_hbuffer_external);
40515 alloc_size = sizeof(duk_hbuffer_external);
40516 } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
40517 header_size = sizeof(duk_hbuffer_dynamic);
40518 alloc_size = sizeof(duk_hbuffer_dynamic);
40519 } else {
40520 header_size = sizeof(duk_hbuffer_fixed);
40521 alloc_size = sizeof(duk_hbuffer_fixed) + size;
40522 DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed)); /* no wrapping */
40523 }
40524
40525 res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
40526 if (!res) {
40527 goto error;
40528 }
40529
40530 /* zero everything unless requested not to do so */
40531#if defined(DUK_USE_ZERO_BUFFER_DATA)
40532 DUK_MEMZERO((void *) res,
40533 (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
40534#else
40535 DUK_MEMZERO((void *) res, header_size);
40536#endif
40537
40538 if (flags & DUK_BUF_FLAG_EXTERNAL) {
40540 h = (duk_hbuffer_external *) res;
40541 DUK_UNREF(h);
40542 *out_bufdata = NULL;
40543#if defined(DUK_USE_EXPLICIT_NULL_INIT)
40544#if defined(DUK_USE_HEAPPTR16)
40545/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
40546#else
40548#endif
40549#endif
40551 } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
40553 void *ptr;
40554
40555 if (size > 0) {
40556 DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL)); /* alloc external with size zero */
40557 DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
40558#ifdef DUK_USE_ZERO_BUFFER_DATA
40559 ptr = DUK_ALLOC_ZEROED(heap, size);
40560#else
40561 ptr = DUK_ALLOC(heap, size);
40562#endif
40563 if (!ptr) {
40564 /* Because size > 0, NULL check is correct */
40565 goto error;
40566 }
40567 *out_bufdata = ptr;
40568
40570 } else {
40571 *out_bufdata = NULL;
40572#if defined(DUK_USE_EXPLICIT_NULL_INIT)
40573#if defined(DUK_USE_HEAPPTR16)
40574/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
40575#else
40577#endif
40578#endif
40580 }
40581 } else {
40582 *out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);
40583 }
40584
40585 DUK_HBUFFER_SET_SIZE(res, size);
40586
40588 if (flags & DUK_BUF_FLAG_DYNAMIC) {
40590 if (flags & DUK_BUF_FLAG_EXTERNAL) {
40592 }
40593 } else {
40595 }
40596 DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
40597
40598 DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
40599 return res;
40600
40601 error:
40602 DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
40603
40604 DUK_FREE(heap, res);
40605 return NULL; /* no need to write 'out_bufdata' */
40606}
40607
40608/* For indirect allocs. */
40609
40610DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
40612 DUK_UNREF(heap);
40613 return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
40614}
40616 * duk_hbuffer operations such as resizing and inserting/appending data to
40617 * a dynamic buffer.
40618 *
40619 * Append operations append to the end of the buffer and they are relatively
40620 * efficient: the buffer is grown with a "spare" part relative to the buffer
40621 * size to minimize reallocations. Insert operations need to move existing
40622 * data forward in the buffer with memmove() and are not very efficient.
40623 * They are used e.g. by the regexp compiler to "backpatch" regexp bytecode.
40624 */
40625
40626/* include removed: duk_internal.h */
40627
40628/*
40629 * Resizing
40630 */
40631
40633 void *res;
40634 duk_size_t prev_size;
40635
40636 DUK_ASSERT(thr != NULL);
40637 DUK_ASSERT(buf != NULL);
40640
40641 /*
40642 * Maximum size check
40643 */
40644
40645 if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
40646 DUK_ERROR_RANGE(thr, "buffer too long");
40647 }
40648
40649 /*
40650 * Note: use indirect realloc variant just in case mark-and-sweep
40651 * (finalizers) might resize this same buffer during garbage
40652 * collection.
40653 */
40654
40655 res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
40656 if (res != NULL || new_size == 0) {
40657 /* 'res' may be NULL if new allocation size is 0. */
40658
40659 DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
40660 (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
40661 (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
40662 (void *) res,
40663 (long) new_size));
40664
40665 /*
40666 * The entire allocated buffer area, regardless of actual used
40667 * size, is kept zeroed in resizes for simplicity. If the buffer
40668 * is grown, zero the new part.
40669 */
40670
40671 prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
40672 if (new_size > prev_size) {
40673 DUK_ASSERT(new_size - prev_size > 0);
40674#ifdef DUK_USE_ZERO_BUFFER_DATA
40675 DUK_MEMZERO((void *) ((char *) res + prev_size),
40676 (duk_size_t) (new_size - prev_size));
40677#endif
40678 }
40679
40680 DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
40681 DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
40682 } else {
40684 }
40685
40686 DUK_ASSERT(res != NULL || new_size == 0);
40687}
40688
40690 DUK_ASSERT(thr != NULL);
40691 DUK_ASSERT(buf != NULL);
40694
40695 duk_hbuffer_resize(thr, buf, 0);
40696}
40697/* include removed: duk_internal.h */
40698
40699#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
40701 duk_uint_t buf_size;
40702 duk_uint_t buf_avail;
40703
40704 DUK_ASSERT(h_bufobj != NULL);
40705 DUK_ASSERT(h_bufobj->buf != NULL);
40706
40707 buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
40708 if (h_bufobj->offset > buf_size) {
40709 /* Slice starting point is beyond current length. */
40710 return 0;
40712 buf_avail = buf_size - h_bufobj->offset;
40713
40714 return buf_avail >= len ? len : buf_avail;
40715}
40716#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
40717/*
40718 * duk_heap allocation and freeing.
40719 */
40720
40721/* include removed: duk_internal.h */
40722
40723/* Constants for built-in string data depacking. */
40724#define DUK__BITPACK_LETTER_LIMIT 26
40725#define DUK__BITPACK_UNDERSCORE 26
40726#define DUK__BITPACK_FF 27
40727#define DUK__BITPACK_SWITCH1 29
40728#define DUK__BITPACK_SWITCH 30
40729#define DUK__BITPACK_SEVENBIT 31
40730
40731#if defined(DUK_USE_ROM_STRINGS)
40732/* Fixed seed value used with ROM strings. */
40733#define DUK__FIXED_HASH_SEED 0xabcd1234
40734#endif
40735
40736/*
40737 * Free a heap object.
40738 *
40739 * Free heap object and its internal (non-heap) pointers. Assumes that
40740 * caller has removed the object from heap allocated list or the string
40741 * intern table, and any weak references (which strings may have) have
40742 * been already dealt with.
40743 */
40744
40746 DUK_ASSERT(heap != NULL);
40747 DUK_ASSERT(h != NULL);
40748
40749 DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
40750
40753 DUK_UNREF(f);
40754 /* Currently nothing to free; 'data' is a heap object */
40755 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
40757 DUK_UNREF(f);
40758 /* Currently nothing to free */
40759 } else if (DUK_HOBJECT_IS_THREAD(h)) {
40760 duk_hthread *t = (duk_hthread *) h;
40761 DUK_FREE(heap, t->valstack);
40762 DUK_FREE(heap, t->callstack);
40763 DUK_FREE(heap, t->catchstack);
40764 /* Don't free h->resumer because it exists in the heap.
40765 * Callstack entries also contain function pointers which
40766 * are not freed for the same reason.
40767 */
40768
40769 /* XXX: with 'caller' property the callstack would need
40770 * to be unwound to update the 'caller' properties of
40771 * functions in the callstack.
40772 */
40773 }
40774}
40775
40777 DUK_ASSERT(heap != NULL);
40778 DUK_ASSERT(h != NULL);
40779
40782 DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
40784 }
40785}
40788 DUK_ASSERT(heap != NULL);
40789 DUK_ASSERT(h != NULL);
40790
40791 DUK_UNREF(heap);
40792 DUK_UNREF(h);
40793
40794#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
40795 if (DUK_HSTRING_HAS_EXTDATA(h)) {
40796 DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
40797 h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
40798 DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
40799 }
40800#endif
40801}
40802
40804 DUK_ASSERT(heap);
40805 DUK_ASSERT(hdr);
40806
40807 DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
40808
40809 switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
40810 case DUK_HTYPE_STRING:
40811 duk_free_hstring_inner(heap, (duk_hstring *) hdr);
40812 break;
40813 case DUK_HTYPE_OBJECT:
40814 duk_free_hobject_inner(heap, (duk_hobject *) hdr);
40815 break;
40816 case DUK_HTYPE_BUFFER:
40817 duk_free_hbuffer_inner(heap, (duk_hbuffer *) hdr);
40818 break;
40819 default:
40821 }
40823 DUK_FREE(heap, hdr);
40824}
40825
40826/*
40827 * Free the heap.
40828 *
40829 * Frees heap-related non-heap-tracked allocations such as the
40830 * string intern table; then frees the heap allocated objects;
40831 * and finally frees the heap structure itself. Reference counts
40832 * and GC markers are ignored (and not updated) in this process,
40833 * and finalizers won't be called.
40834 *
40835 * The heap pointer and heap object pointers must not be used
40836 * after this call.
40837 */
40838
40840 duk_heaphdr *curr;
40842
40843 curr = heap->heap_allocated;
40844 while (curr) {
40845 /* We don't log or warn about freeing zero refcount objects
40846 * because they may happen with finalizer processing.
40847 */
40848
40849 DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
40850 (duk_heaphdr *) curr));
40851 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
40852 duk_heap_free_heaphdr_raw(heap, curr);
40853 curr = next;
40854 }
40855}
40856
40857#if defined(DUK_USE_REFERENCE_COUNTING)
40859 duk_heaphdr *curr;
40861
40862 curr = heap->refzero_list;
40863 while (curr) {
40864 DUK_DDD(DUK_DDDPRINT("FINALFREE (refzero_list): %!iO",
40865 (duk_heaphdr *) curr));
40866 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
40867 duk_heap_free_heaphdr_raw(heap, curr);
40868 curr = next;
40869 }
40870}
40871#endif
40873#if defined(DUK_USE_MARK_AND_SWEEP)
40875 duk_heaphdr *curr;
40878 curr = heap->finalize_list;
40879 while (curr) {
40880 DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
40881 (duk_heaphdr *) curr));
40882 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
40883 duk_heap_free_heaphdr_raw(heap, curr);
40884 curr = next;
40885 }
40886}
40887#endif
40888
40890 /* strings are only tracked by stringtable */
40892}
40893
40895 duk_hthread *thr;
40896 duk_heaphdr *curr;
40897 duk_uint_t round_no;
40898 duk_size_t count_all;
40899 duk_size_t count_finalized;
40900 duk_size_t curr_limit;
40901
40902 DUK_ASSERT(heap != NULL);
40903 DUK_ASSERT(heap->heap_thread != NULL);
40904
40905#if defined(DUK_USE_REFERENCE_COUNTING)
40906 DUK_ASSERT(heap->refzero_list == NULL); /* refzero not running -> must be empty */
40907#endif
40908#if defined(DUK_USE_MARK_AND_SWEEP)
40909 DUK_ASSERT(heap->finalize_list == NULL); /* mark-and-sweep not running -> must be empty */
40910#endif
40911
40912 /* XXX: here again finalizer thread is the heap_thread which needs
40913 * to be coordinated with finalizer thread fixes.
40914 */
40915 thr = heap->heap_thread;
40916 DUK_ASSERT(thr != NULL);
40917
40918 /* Prevent mark-and-sweep for the pending finalizers, also prevents
40919 * refzero handling from moving objects away from the heap_allocated
40920 * list. (The flag meaning is slightly abused here.)
40921 */
40924
40925 curr_limit = 0; /* suppress warning, not used */
40926 for (round_no = 0; ; round_no++) {
40927 curr = heap->heap_allocated;
40928 count_all = 0;
40929 count_finalized = 0;
40930 while (curr) {
40931 count_all++;
40933 /* Only objects in heap_allocated may have finalizers. Check that
40934 * the object itself has a _Finalizer property (own or inherited)
40935 * so that we don't execute finalizers for e.g. Proxy objects.
40936 */
40937 DUK_ASSERT(thr != NULL);
40938 DUK_ASSERT(curr != NULL);
40939
40941 if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
40942 DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)); /* maps to finalizer 2nd argument */
40944 count_finalized++;
40945 }
40946 }
40947 }
40948 curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
40949 }
40950
40951 /* Each round of finalizer execution may spawn new finalizable objects
40952 * which is normal behavior for some applications. Allow multiple
40953 * rounds of finalization, but use a shrinking limit based on the
40954 * first round to detect the case where a runaway finalizer creates
40955 * an unbounded amount of new finalizable objects. Finalizer rescue
40956 * is not supported: the semantics are unclear because most of the
40957 * objects being finalized here are already reachable. The finalizer
40958 * is given a boolean to indicate that rescue is not possible.
40959 *
40960 * See discussion in: https://github.com/svaarala/duktape/pull/473
40961 */
40962
40963 if (round_no == 0) {
40964 /* Cannot wrap: each object is at least 8 bytes so count is
40965 * at most 1/8 of that.
40966 */
40967 curr_limit = count_all * 2;
40968 } else {
40969 curr_limit = (curr_limit * 3) / 4; /* Decrease by 25% every round */
40970 }
40971 DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
40972 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
40973
40974 if (count_finalized == 0) {
40975 DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
40976 break;
40977 }
40978 if (count_finalized >= curr_limit) {
40979 DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
40980 break;
40981 }
40982 }
40983
40986}
40987
40989 DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
40990
40991#if defined(DUK_USE_DEBUG)
40992 duk_heap_dump_strtab(heap);
40993#endif
40994
40995#if defined(DUK_USE_DEBUGGER_SUPPORT)
40996 /* Detach a debugger if attached (can be called multiple times)
40997 * safely.
40998 */
40999 /* XXX: Add a flag to reject an attempt to re-attach? Otherwise
41000 * the detached callback may immediately reattach.
41001 */
41002 duk_debug_do_detach(heap);
41003#endif
41004
41005 /* Execute finalizers before freeing the heap, even for reachable
41006 * objects, and regardless of whether or not mark-and-sweep is
41007 * enabled. This gives finalizers the chance to free any native
41008 * resources like file handles, allocations made outside Duktape,
41009 * etc. This is quite tricky to get right, so that all finalizer
41010 * guarantees are honored.
41011 *
41012 * XXX: this perhaps requires an execution time limit.
41013 */
41014 DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
41015#if defined(DUK_USE_MARK_AND_SWEEP)
41016 /* Run mark-and-sweep a few times just in case (unreachable object
41017 * finalizers run already here). The last round must rescue objects
41018 * from the previous round without running any more finalizers. This
41019 * ensures rescued objects get their FINALIZED flag cleared so that
41020 * their finalizer is called once more in forced finalization to
41021 * satisfy finalizer guarantees. However, we don't want to run any
41022 * more finalizer because that'd required one more loop, and so on.
41023 */
41024 DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
41025 duk_heap_mark_and_sweep(heap, 0);
41026 DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
41027 duk_heap_mark_and_sweep(heap, 0);
41028 DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
41029 duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS); /* skip finalizers; queue finalizable objects to heap_allocated */
41030#endif
41031
41032 DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* rescue no longer supported */
41034
41035 /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
41036 * are on the heap allocated list.
41037 */
41038
41039 DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap));
41040 duk__free_allocated(heap);
41041
41042#if defined(DUK_USE_REFERENCE_COUNTING)
41043 DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap));
41045#endif
41046
41047#if defined(DUK_USE_MARK_AND_SWEEP)
41048 DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap));
41050#endif
41051
41052 DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
41054
41055 DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
41056 heap->free_func(heap->heap_udata, heap);
41057}
41058
41059/*
41060 * Allocate a heap.
41061 *
41062 * String table is initialized with built-in strings from genbuiltins.py,
41063 * either by dynamically creating the strings or by referring to ROM strings.
41064 */
41065
41066#if defined(DUK_USE_ROM_STRINGS)
41068#if defined(DUK_USE_ASSERTIONS)
41070#endif
41071
41072 /* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
41073 * so nothing to initialize for strs[].
41075
41076#if defined(DUK_USE_ASSERTIONS)
41077 for (i = 0; i < sizeof(duk_rom_strings) / sizeof(const duk_hstring *); i++) {
41078 duk_uint32_t hash;
41079 const duk_hstring *h;
41080 h = duk_rom_strings[i];
41081 DUK_ASSERT(h != NULL);
41082 hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
41083 DUK_DD(DUK_DDPRINT("duk_rom_strings[%d] -> hash 0x%08lx, computed 0x%08lx",
41084 (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
41085 DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
41086 }
41087#endif
41088 return 1;
41089}
41090#else /* DUK_USE_ROM_STRINGS */
41092 duk_bitdecoder_ctx bd_ctx;
41093 duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
41094 duk_small_uint_t i, j;
41095
41096 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
41097 bd->data = (const duk_uint8_t *) duk_strings_data;
41099
41100 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
41101 duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
41102 duk_hstring *h;
41103 duk_small_uint_t len;
41104 duk_small_uint_t mode;
41106
41107 len = duk_bd_decode(bd, 5);
41108 mode = 32; /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
41109 for (j = 0; j < len; j++) {
41110 t = duk_bd_decode(bd, 5);
41111 if (t < DUK__BITPACK_LETTER_LIMIT) {
41112 t = t + DUK_ASC_UC_A + mode;
41113 } else if (t == DUK__BITPACK_UNDERSCORE) {
41115 } else if (t == DUK__BITPACK_FF) {
41116 /* Internal keys are prefixed with 0xFF in the stringtable
41117 * (which makes them invalid UTF-8 on purpose).
41118 */
41119 t = 0xff;
41120 } else if (t == DUK__BITPACK_SWITCH1) {
41121 t = duk_bd_decode(bd, 5);
41122 DUK_ASSERT_DISABLE(t >= 0); /* unsigned */
41123 DUK_ASSERT(t <= 25);
41124 t = t + DUK_ASC_UC_A + (mode ^ 32);
41125 } else if (t == DUK__BITPACK_SWITCH) {
41126 mode = mode ^ 32;
41127 t = duk_bd_decode(bd, 5);
41128 DUK_ASSERT_DISABLE(t >= 0);
41129 DUK_ASSERT(t <= 25);
41130 t = t + DUK_ASC_UC_A + mode;
41131 } else if (t == DUK__BITPACK_SEVENBIT) {
41132 t = duk_bd_decode(bd, 7);
41133 }
41134 tmp[j] = (duk_uint8_t) t;
41135 }
41136
41137 /* No need to length check string: it will never exceed even
41138 * the 16-bit length maximum.
41139 */
41140 DUK_ASSERT(len <= 0xffffUL);
41141 DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
41142 h = duk_heap_string_intern(heap, tmp, len);
41143 if (!h) {
41144 goto error;
41145 }
41147
41148 /* Special flags checks. Since these strings are always
41149 * reachable and a string cannot appear twice in the string
41150 * table, there's no need to check/set these flags elsewhere.
41151 * The 'internal' flag is set by string intern code.
41152 */
41153 if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
41155 }
41160 }
41161 }
41162
41163 DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
41164
41165 /* XXX: The incref macro takes a thread pointer but doesn't
41166 * use it right now.
41168 DUK_HSTRING_INCREF(_never_referenced_, h);
41169
41170#if defined(DUK_USE_HEAPPTR16)
41171 heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
41172#else
41173 heap->strs[i] = h;
41174#endif
41175 }
41176
41177 return 1;
41178
41179 error:
41180 return 0;
41181}
41182#endif /* DUK_USE_ROM_STRINGS */
41183
41185 duk_hthread *thr;
41186
41187 DUK_DD(DUK_DDPRINT("heap init: alloc heap thread"));
41188 thr = duk_hthread_alloc(heap,
41192 if (!thr) {
41193 DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
41194 return 0;
41195 }
41197#if defined(DUK_USE_ROM_STRINGS)
41198 /* No strs[] pointer. */
41199#else /* DUK_USE_ROM_STRINGS */
41200#if defined(DUK_USE_HEAPPTR16)
41201 thr->strs16 = heap->strs16;
41202#else
41203 thr->strs = heap->strs;
41204#endif
41205#endif /* DUK_USE_ROM_STRINGS */
41206
41207 heap->heap_thread = thr;
41208 DUK_HTHREAD_INCREF(thr, thr); /* Note: first argument not really used */
41209
41210 /* 'thr' is now reachable */
41211
41212 if (!duk_hthread_init_stacks(heap, thr)) {
41213 return 0;
41214 }
41215
41216 /* XXX: this may now fail, and is not handled correctly */
41218
41219 /* default prototype (Note: 'thr' must be reachable) */
41221
41222 return 1;
41223}
41224
41225#if defined(DUK_USE_DEBUG)
41226#define DUK__DUMPSZ(t) do { \
41227 DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
41228 } while (0)
41229
41230/* These is not 100% because format would need to be non-portable "long long".
41231 * Also print out as doubles to catch cases where the "long" type is not wide
41232 * enough; the limits will then not be printed accurately but the magnitude
41233 * will be correct.
41234 */
41235#define DUK__DUMPLM_SIGNED_RAW(t,a,b) do { \
41236 DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
41237 (long) (a), (long) (b), \
41238 (double) (a), (double) (b))); \
41239 } while (0)
41240#define DUK__DUMPLM_UNSIGNED_RAW(t,a,b) do { \
41241 DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
41242 (unsigned long) (a), (unsigned long) (b), \
41243 (double) (a), (double) (b))); \
41244 } while (0)
41245#define DUK__DUMPLM_SIGNED(t) do { \
41246 DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
41247 } while (0)
41248#define DUK__DUMPLM_UNSIGNED(t) do { \
41249 DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
41250 } while (0)
41251
41252DUK_LOCAL void duk__dump_type_sizes(void) {
41253 DUK_D(DUK_DPRINT("sizeof()"));
41254
41255 /* basic platform types */
41256 DUK__DUMPSZ(char);
41257 DUK__DUMPSZ(short);
41258 DUK__DUMPSZ(int);
41259 DUK__DUMPSZ(long);
41260 DUK__DUMPSZ(double);
41261 DUK__DUMPSZ(void *);
41262 DUK__DUMPSZ(size_t);
41263
41264 /* basic types from duk_features.h */
41265 DUK__DUMPSZ(duk_uint8_t);
41266 DUK__DUMPSZ(duk_int8_t);
41267 DUK__DUMPSZ(duk_uint16_t);
41268 DUK__DUMPSZ(duk_int16_t);
41269 DUK__DUMPSZ(duk_uint32_t);
41270 DUK__DUMPSZ(duk_int32_t);
41271 DUK__DUMPSZ(duk_uint64_t);
41272 DUK__DUMPSZ(duk_int64_t);
41273 DUK__DUMPSZ(duk_uint_least8_t);
41274 DUK__DUMPSZ(duk_int_least8_t);
41275 DUK__DUMPSZ(duk_uint_least16_t);
41276 DUK__DUMPSZ(duk_int_least16_t);
41277 DUK__DUMPSZ(duk_uint_least32_t);
41278 DUK__DUMPSZ(duk_int_least32_t);
41279#if defined(DUK_USE_64BIT_OPS)
41280 DUK__DUMPSZ(duk_uint_least64_t);
41281 DUK__DUMPSZ(duk_int_least64_t);
41282#endif
41283 DUK__DUMPSZ(duk_uint_fast8_t);
41284 DUK__DUMPSZ(duk_int_fast8_t);
41285 DUK__DUMPSZ(duk_uint_fast16_t);
41286 DUK__DUMPSZ(duk_int_fast16_t);
41287 DUK__DUMPSZ(duk_uint_fast32_t);
41288 DUK__DUMPSZ(duk_int_fast32_t);
41289#if defined(DUK_USE_64BIT_OPS)
41290 DUK__DUMPSZ(duk_uint_fast64_t);
41291 DUK__DUMPSZ(duk_int_fast64_t);
41292#endif
41293 DUK__DUMPSZ(duk_uintptr_t);
41294 DUK__DUMPSZ(duk_intptr_t);
41295 DUK__DUMPSZ(duk_uintmax_t);
41296 DUK__DUMPSZ(duk_intmax_t);
41297 DUK__DUMPSZ(duk_double_t);
41298
41299 /* important chosen base types */
41300 DUK__DUMPSZ(duk_int_t);
41301 DUK__DUMPSZ(duk_uint_t);
41302 DUK__DUMPSZ(duk_int_fast_t);
41303 DUK__DUMPSZ(duk_uint_fast_t);
41304 DUK__DUMPSZ(duk_small_int_t);
41305 DUK__DUMPSZ(duk_small_uint_t);
41306 DUK__DUMPSZ(duk_small_int_fast_t);
41307 DUK__DUMPSZ(duk_small_uint_fast_t);
41308
41309 /* some derived types */
41310 DUK__DUMPSZ(duk_codepoint_t);
41311 DUK__DUMPSZ(duk_ucodepoint_t);
41312 DUK__DUMPSZ(duk_idx_t);
41313 DUK__DUMPSZ(duk_errcode_t);
41314 DUK__DUMPSZ(duk_uarridx_t);
41315
41316 /* tval */
41317 DUK__DUMPSZ(duk_double_union);
41318 DUK__DUMPSZ(duk_tval);
41319
41320 /* structs from duk_forwdecl.h */
41321 DUK__DUMPSZ(duk_jmpbuf); /* just one 'int' for C++ exceptions */
41322 DUK__DUMPSZ(duk_heaphdr);
41323 DUK__DUMPSZ(duk_heaphdr_string);
41324 DUK__DUMPSZ(duk_hstring);
41325 DUK__DUMPSZ(duk_hstring_external);
41326 DUK__DUMPSZ(duk_hobject);
41327 DUK__DUMPSZ(duk_hcompiledfunction);
41328 DUK__DUMPSZ(duk_hnativefunction);
41329 DUK__DUMPSZ(duk_hthread);
41330 DUK__DUMPSZ(duk_hbuffer);
41331 DUK__DUMPSZ(duk_hbuffer_fixed);
41332 DUK__DUMPSZ(duk_hbuffer_dynamic);
41333 DUK__DUMPSZ(duk_hbuffer_external);
41334 DUK__DUMPSZ(duk_propaccessor);
41335 DUK__DUMPSZ(duk_propvalue);
41336 DUK__DUMPSZ(duk_propdesc);
41337 DUK__DUMPSZ(duk_heap);
41338#if defined(DUK_USE_STRTAB_CHAIN)
41339 DUK__DUMPSZ(duk_strtab_entry);
41340#endif
41341 DUK__DUMPSZ(duk_activation);
41342 DUK__DUMPSZ(duk_catcher);
41343 DUK__DUMPSZ(duk_strcache);
41344 DUK__DUMPSZ(duk_ljstate);
41345 DUK__DUMPSZ(duk_fixedbuffer);
41346 DUK__DUMPSZ(duk_bitdecoder_ctx);
41347 DUK__DUMPSZ(duk_bitencoder_ctx);
41348 DUK__DUMPSZ(duk_token);
41349 DUK__DUMPSZ(duk_re_token);
41350 DUK__DUMPSZ(duk_lexer_point);
41351 DUK__DUMPSZ(duk_lexer_ctx);
41352 DUK__DUMPSZ(duk_compiler_instr);
41353 DUK__DUMPSZ(duk_compiler_func);
41354 DUK__DUMPSZ(duk_compiler_ctx);
41355 DUK__DUMPSZ(duk_re_matcher_ctx);
41356 DUK__DUMPSZ(duk_re_compiler_ctx);
41357}
41358DUK_LOCAL void duk__dump_type_limits(void) {
41359 DUK_D(DUK_DPRINT("limits"));
41360
41361 /* basic types */
41362 DUK__DUMPLM_SIGNED(INT8);
41363 DUK__DUMPLM_UNSIGNED(UINT8);
41364 DUK__DUMPLM_SIGNED(INT_FAST8);
41365 DUK__DUMPLM_UNSIGNED(UINT_FAST8);
41366 DUK__DUMPLM_SIGNED(INT_LEAST8);
41367 DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
41368 DUK__DUMPLM_SIGNED(INT16);
41369 DUK__DUMPLM_UNSIGNED(UINT16);
41370 DUK__DUMPLM_SIGNED(INT_FAST16);
41371 DUK__DUMPLM_UNSIGNED(UINT_FAST16);
41372 DUK__DUMPLM_SIGNED(INT_LEAST16);
41373 DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
41374 DUK__DUMPLM_SIGNED(INT32);
41375 DUK__DUMPLM_UNSIGNED(UINT32);
41376 DUK__DUMPLM_SIGNED(INT_FAST32);
41377 DUK__DUMPLM_UNSIGNED(UINT_FAST32);
41378 DUK__DUMPLM_SIGNED(INT_LEAST32);
41379 DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
41380#if defined(DUK_USE_64BIT_OPS)
41381 DUK__DUMPLM_SIGNED(INT64);
41382 DUK__DUMPLM_UNSIGNED(UINT64);
41383 DUK__DUMPLM_SIGNED(INT_FAST64);
41384 DUK__DUMPLM_UNSIGNED(UINT_FAST64);
41385 DUK__DUMPLM_SIGNED(INT_LEAST64);
41386 DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
41387#endif
41388 DUK__DUMPLM_SIGNED(INTPTR);
41389 DUK__DUMPLM_UNSIGNED(UINTPTR);
41390 DUK__DUMPLM_SIGNED(INTMAX);
41391 DUK__DUMPLM_UNSIGNED(UINTMAX);
41392
41393 /* derived types */
41394 DUK__DUMPLM_SIGNED(INT);
41395 DUK__DUMPLM_UNSIGNED(UINT);
41396 DUK__DUMPLM_SIGNED(INT_FAST);
41397 DUK__DUMPLM_UNSIGNED(UINT_FAST);
41398 DUK__DUMPLM_SIGNED(SMALL_INT);
41399 DUK__DUMPLM_UNSIGNED(SMALL_UINT);
41400 DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
41401 DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
41402}
41403#undef DUK__DUMPSZ
41404#undef DUK__DUMPLM_SIGNED_RAW
41405#undef DUK__DUMPLM_UNSIGNED_RAW
41406#undef DUK__DUMPLM_SIGNED
41407#undef DUK__DUMPLM_UNSIGNED
41408
41409DUK_LOCAL void duk__dump_misc_options(void) {
41410 DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
41411 DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
41412 DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
41413 DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
41414 DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
41415#if defined(DUK_USE_PACKED_TVAL)
41416 DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
41417#else
41418 DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
41419#endif
41420#if defined(DUK_USE_VARIADIC_MACROS)
41421 DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
41422#else
41423 DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
41424#endif
41425#if defined(DUK_USE_INTEGER_LE)
41426 DUK_D(DUK_DPRINT("integer endianness: little"));
41427#elif defined(DUK_USE_INTEGER_ME)
41428 DUK_D(DUK_DPRINT("integer endianness: mixed"));
41429#elif defined(DUK_USE_INTEGER_BE)
41430 DUK_D(DUK_DPRINT("integer endianness: big"));
41431#else
41432 DUK_D(DUK_DPRINT("integer endianness: ???"));
41433#endif
41434#if defined(DUK_USE_DOUBLE_LE)
41435 DUK_D(DUK_DPRINT("IEEE double endianness: little"));
41436#elif defined(DUK_USE_DOUBLE_ME)
41437 DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
41438#elif defined(DUK_USE_DOUBLE_BE)
41439 DUK_D(DUK_DPRINT("IEEE double endianness: big"));
41440#else
41441 DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
41442#endif
41443}
41444#endif /* DUK_USE_DEBUG */
41445
41448 duk_realloc_function realloc_func,
41449 duk_free_function free_func,
41450 void *heap_udata,
41451 duk_fatal_function fatal_func) {
41452 duk_heap *res = NULL;
41453
41454 /* Silence a few global unused warnings here. */
41456
41457 DUK_D(DUK_DPRINT("allocate heap"));
41458
41459 /*
41460 * Debug dump type sizes
41461 */
41462
41463#if defined(DUK_USE_DEBUG)
41464 duk__dump_misc_options();
41465 duk__dump_type_sizes();
41466 duk__dump_type_limits();
41467#endif
41468
41469 /*
41470 * If selftests enabled, run them as early as possible
41471 */
41472#if defined(DUK_USE_SELF_TESTS)
41473 DUK_D(DUK_DPRINT("running self tests"));
41474 duk_selftest_run_tests();
41475 DUK_D(DUK_DPRINT("self tests passed"));
41476#endif
41477
41478 /*
41479 * Computed values (e.g. INFINITY)
41480 */
41481
41482#if defined(DUK_USE_COMPUTED_NAN)
41483 do {
41484 /* Workaround for some exotic platforms where NAN is missing
41485 * and the expression (0.0 / 0.0) does NOT result in a NaN.
41486 * Such platforms use the global 'duk_computed_nan' which must
41487 * be initialized at runtime. Use 'volatile' to ensure that
41488 * the compiler will actually do the computation and not try
41489 * to do constant folding which might result in the original
41490 * problem.
41491 */
41492 volatile double dbl1 = 0.0;
41493 volatile double dbl2 = 0.0;
41494 duk_computed_nan = dbl1 / dbl2;
41495 } while (0);
41496#endif
41497
41498#if defined(DUK_USE_COMPUTED_INFINITY)
41499 do {
41500 /* Similar workaround for INFINITY. */
41501 volatile double dbl1 = 1.0;
41502 volatile double dbl2 = 0.0;
41503 duk_computed_infinity = dbl1 / dbl2;
41504 } while (0);
41505#endif
41506
41507 /*
41508 * Allocate heap struct
41509 *
41510 * Use a raw call, all macros expect the heap to be initialized
41511 */
41512
41513 res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
41514 if (!res) {
41515 goto error;
41516 }
41517
41518 /*
41519 * Zero the struct, and start initializing roughly in order
41520 */
41521
41522 DUK_MEMZERO(res, sizeof(*res));
41523
41524 /* explicit NULL inits */
41525#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41526 res->heap_udata = NULL;
41527 res->heap_allocated = NULL;
41528#if defined(DUK_USE_REFERENCE_COUNTING)
41529 res->refzero_list = NULL;
41530 res->refzero_list_tail = NULL;
41531#endif
41532#if defined(DUK_USE_MARK_AND_SWEEP)
41533 res->finalize_list = NULL;
41534#endif
41535 res->heap_thread = NULL;
41536 res->curr_thread = NULL;
41537 res->heap_object = NULL;
41538#if defined(DUK_USE_STRTAB_CHAIN)
41539 /* nothing to NULL */
41540#elif defined(DUK_USE_STRTAB_PROBE)
41541#if defined(DUK_USE_HEAPPTR16)
41542 res->strtable16 = (duk_uint16_t *) NULL;
41543#else
41544 res->strtable = (duk_hstring **) NULL;
41545#endif
41546#endif
41547#if defined(DUK_USE_ROM_STRINGS)
41548 /* no res->strs[] */
41549#else /* DUK_USE_ROM_STRINGS */
41550#if defined(DUK_USE_HEAPPTR16)
41551 /* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
41552#else
41553 {
41555 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
41556 res->strs[i] = NULL;
41557 }
41558 }
41559#endif
41560#endif /* DUK_USE_ROM_STRINGS */
41561#if defined(DUK_USE_DEBUGGER_SUPPORT)
41562 res->dbg_read_cb = NULL;
41563 res->dbg_write_cb = NULL;
41564 res->dbg_peek_cb = NULL;
41565 res->dbg_read_flush_cb = NULL;
41566 res->dbg_write_flush_cb = NULL;
41567 res->dbg_request_cb = NULL;
41568 res->dbg_udata = NULL;
41569 res->dbg_step_thread = NULL;
41570#endif
41571#endif /* DUK_USE_EXPLICIT_NULL_INIT */
41572
41573 res->alloc_func = alloc_func;
41574 res->realloc_func = realloc_func;
41575 res->free_func = free_func;
41576 res->heap_udata = heap_udata;
41577 res->fatal_func = fatal_func;
41578
41579#if defined(DUK_USE_HEAPPTR16)
41580 /* XXX: zero assumption */
41581 res->heapptr_null16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) NULL);
41582 res->heapptr_deleted16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) DUK_STRTAB_DELETED_MARKER(res));
41583#endif
41584
41585 /* res->mark_and_sweep_trigger_counter == 0 -> now causes immediate GC; which is OK */
41586
41587 res->call_recursion_depth = 0;
41589
41590 /* XXX: use the pointer as a seed for now: mix in time at least */
41591
41592 /* The casts through duk_intr_pt is to avoid the following GCC warning:
41593 *
41594 * warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
41595 *
41596 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
41597 */
41598#if defined(DUK_USE_ROM_STRINGS)
41599 /* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
41600 DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
41601 res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
41602#else /* DUK_USE_ROM_STRINGS */
41603 res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
41604 res->rnd_state = (duk_uint32_t) (duk_intptr_t) res;
41605#if !defined(DUK_USE_STRHASH_DENSE)
41606 res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
41607#endif
41608#endif /* DUK_USE_ROM_STRINGS */
41609
41610#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41611 res->lj.jmpbuf_ptr = NULL;
41612#endif
41613 DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN); /* zero */
41614
41617
41618#if (DUK_STRTAB_INITIAL_SIZE < DUK_UTIL_MIN_HASH_PRIME)
41619#error initial heap stringtable size is defined incorrectly
41620#endif
41621
41622 /*
41623 * Init stringtable: fixed variant
41624 */
41625
41626#if defined(DUK_USE_STRTAB_CHAIN)
41628#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41629 {
41631 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
41632#if defined(DUK_USE_HEAPPTR16)
41633 res->strtable[i].u.str16 = res->heapptr_null16;
41634#else
41635 res->strtable[i].u.str = NULL;
41636#endif
41637 }
41638 }
41639#endif /* DUK_USE_EXPLICIT_NULL_INIT */
41640#endif /* DUK_USE_STRTAB_CHAIN */
41641
41642 /*
41643 * Init stringtable: probe variant
41644 */
41645
41646#if defined(DUK_USE_STRTAB_PROBE)
41647#if defined(DUK_USE_HEAPPTR16)
41648 res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
41649 if (!res->strtable16) {
41650 goto error;
41651 }
41652#else /* DUK_USE_HEAPPTR16 */
41653 res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
41654 if (!res->strtable) {
41655 goto error;
41656 }
41657#endif /* DUK_USE_HEAPPTR16 */
41659#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41660 {
41663 for (i = 0; i < DUK_STRTAB_INITIAL_SIZE; i++) {
41664#if defined(DUK_USE_HEAPPTR16)
41665 res->strtable16[i] = res->heapptr_null16;
41666#else
41667 res->strtable[i] = NULL;
41668#endif
41669 }
41670 }
41671#else /* DUK_USE_EXPLICIT_NULL_INIT */
41672#if defined(DUK_USE_HEAPPTR16)
41673 DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
41674#else
41676#endif
41677#endif /* DUK_USE_EXPLICIT_NULL_INIT */
41678#endif /* DUK_USE_STRTAB_PROBE */
41679
41680 /*
41681 * Init stringcache
41682 */
41683
41684#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41685 {
41687 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
41688 res->strcache[i].h = NULL;
41689 }
41690 }
41691#endif
41692
41693 /* XXX: error handling is incomplete. It would be cleanest if
41694 * there was a setjmp catchpoint, so that all init code could
41695 * freely throw errors. If that were the case, the return code
41696 * passing here could be removed.
41697 */
41698
41699 /*
41700 * Init built-in strings
41701 */
41702
41703 DUK_DD(DUK_DDPRINT("HEAP: INIT STRINGS"));
41704 if (!duk__init_heap_strings(res)) {
41705 goto error;
41706 }
41707
41708 /*
41709 * Init the heap thread
41710 */
41711
41712 DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP THREAD"));
41713 if (!duk__init_heap_thread(res)) {
41714 goto error;
41715 }
41716
41717 /*
41718 * Init the heap object
41719 */
41720
41721 DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP OBJECT"));
41722 DUK_ASSERT(res->heap_thread != NULL);
41725 if (!res->heap_object) {
41726 goto error;
41727 }
41729
41730 /*
41731 * All done
41732 */
41733
41734 DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
41735 return res;
41736
41737 error:
41738 DUK_D(DUK_DPRINT("heap allocation failed"));
41739
41740 if (res) {
41741 /* assumes that allocated pointers and alloc funcs are valid
41742 * if res exists
41743 */
41744 DUK_ASSERT(res->alloc_func != NULL);
41745 DUK_ASSERT(res->realloc_func != NULL);
41746 DUK_ASSERT(res->free_func != NULL);
41747 duk_heap_free(res);
41748 }
41749 return NULL;
41750}
41751
41752#undef DUK__BITPACK_LETTER_LIMIT
41753#undef DUK__BITPACK_UNDERSCORE
41754#undef DUK__BITPACK_FF
41755#undef DUK__BITPACK_SWITCH1
41756#undef DUK__BITPACK_SWITCH
41757#undef DUK__BITPACK_SEVENBIT
41758#undef DUK__FIXED_HASH_SEED
41759/*
41760 * String hash computation (interning).
41761 *
41762 * String hashing is performance critical because a string hash is computed
41763 * for all new strings which are candidates to be added to the string table.
41764 * However, strings actually added to the string table go through a codepoint
41765 * length calculation which dominates performance because it goes through
41766 * every byte of the input string (but only for strings added).
41767 *
41768 * The string hash algorithm should be fast, but on the other hand provide
41769 * good enough hashes to ensure both string table and object property table
41770 * hash tables work reasonably well (i.e., there aren't too many collisions
41771 * with real world inputs). Unless the hash is cryptographic, it's always
41772 * possible to craft inputs with maximal hash collisions.
41773 *
41774 * NOTE: The hash algorithms must match src/dukutil.py:duk_heap_hashstring()
41775 * for ROM string support!
41776 */
41777
41778/* include removed: duk_internal.h */
41779
41780#if defined(DUK_USE_STRHASH_DENSE)
41781/* Constants for duk_hashstring(). */
41782#define DUK__STRHASH_SHORTSTRING 4096L
41783#define DUK__STRHASH_MEDIUMSTRING (256L * 1024L)
41784#define DUK__STRHASH_BLOCKSIZE 256L
41785
41786DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
41787 duk_uint32_t hash;
41788
41789 /* Use Murmurhash2 directly for short strings, and use "block skipping"
41790 * for long strings: hash an initial part and then sample the rest of
41791 * the string with reasonably sized chunks. An initial offset for the
41792 * sampling is computed based on a hash of the initial part of the string;
41793 * this is done to (usually) avoid the case where all long strings have
41794 * certain offset ranges which are never sampled.
41795 *
41796 * Skip should depend on length and bound the total time to roughly
41797 * logarithmic. With current values:
41798 *
41799 * 1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
41800 * 1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
41801 *
41802 * XXX: It would be better to compute the skip offset more "smoothly"
41803 * instead of having a few boundary values.
41804 */
41805
41806 /* note: mixing len into seed improves hashing when skipping */
41807 duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
41808
41809 if (len <= DUK__STRHASH_SHORTSTRING) {
41810 hash = duk_util_hashbytes(str, len, str_seed);
41811 } else {
41812 duk_size_t off;
41813 duk_size_t skip;
41814
41815 if (len <= DUK__STRHASH_MEDIUMSTRING) {
41816 skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
41817 } else {
41818 skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
41819 }
41820
41821 hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
41822 off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
41823
41824 /* XXX: inefficient loop */
41825 while (off < len) {
41826 duk_size_t left = len - off;
41827 duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
41828 hash ^= duk_util_hashbytes(str + off, now, str_seed);
41829 off += skip;
41830 }
41831 }
41832
41833#if defined(DUK_USE_STRHASH16)
41834 /* Truncate to 16 bits here, so that a computed hash can be compared
41835 * against a hash stored in a 16-bit field.
41836 */
41837 hash &= 0x0000ffffUL;
41838#endif
41839 return hash;
41840}
41841
41842#undef DUK__STRHASH_SHORTSTRING
41843#undef DUK__STRHASH_MEDIUMSTRING
41844#undef DUK__STRHASH_BLOCKSIZE
41845#else /* DUK_USE_STRHASH_DENSE */
41846DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
41847 duk_uint32_t hash;
41848 duk_size_t step;
41849 duk_size_t off;
41850
41851 /* Slightly modified "Bernstein hash" from:
41852 *
41853 * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
41854 *
41855 * Modifications: string skipping and reverse direction similar to
41856 * Lua 5.1.5, and different hash initializer.
41857 *
41858 * The reverse direction ensures last byte it always included in the
41859 * hash which is a good default as changing parts of the string are
41860 * more often in the suffix than in the prefix.
41861 */
41862
41863 hash = heap->hash_seed ^ ((duk_uint32_t) len); /* Bernstein hash init value is normally 5381 */
41864 step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
41865 for (off = len; off >= step; off -= step) {
41866 DUK_ASSERT(off >= 1); /* off >= step, and step >= 1 */
41867 hash = (hash * 33) + str[off - 1];
41868 }
41869
41870#if defined(DUK_USE_STRHASH16)
41871 /* Truncate to 16 bits here, so that a computed hash can be compared
41872 * against a hash stored in a 16-bit field.
41873 */
41874 hash &= 0x0000ffffUL;
41875#endif
41876 return hash;
41877}
41878#endif /* DUK_USE_STRHASH_DENSE */
41879/*
41880 * Mark-and-sweep garbage collection.
41882
41883/* include removed: duk_internal.h */
41884
41885#ifdef DUK_USE_MARK_AND_SWEEP
41886
41889
41890/*
41891 * Misc
41893
41894/* Select a thread for mark-and-sweep use.
41895 *
41896 * XXX: This needs to change later.
41897 */
41899 if (heap->curr_thread) {
41900 return heap->curr_thread;
41901 }
41902 return heap->heap_thread; /* may be NULL, too */
41903}
41904
41905/*
41906 * Marking functions for heap types: mark children recursively
41907 */
41908
41910 DUK_UNREF(heap);
41911 DUK_UNREF(h);
41912
41913 DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
41914 DUK_ASSERT(h);
41915
41916 /* nothing to process */
41917}
41918
41921
41922 DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
41923
41924 DUK_ASSERT(h);
41925
41926 /* XXX: use advancing pointers instead of index macros -> faster and smaller? */
41927
41928 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
41929 duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
41930 if (!key) {
41931 continue;
41932 }
41933 duk__mark_heaphdr(heap, (duk_heaphdr *) key);
41934 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
41935 duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
41936 duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
41937 } else {
41938 duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
41939 }
41940 }
41941
41942 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
41944 }
41945
41946 /* hash part is a 'weak reference' and does not contribute */
41947
41949
41952 duk_tval *tv, *tv_end;
41953 duk_hobject **fn, **fn_end;
41954
41955 /* 'data' is reachable through every compiled function which
41956 * contains a reference.
41957 */
41958
41960
41961 if (DUK_HCOMPILEDFUNCTION_GET_DATA(heap, f) != NULL) {
41963 tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap, f);
41964 while (tv < tv_end) {
41965 duk__mark_tval(heap, tv);
41966 tv++;
41967 }
41968
41970 fn_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, f);
41971 while (fn < fn_end) {
41972 duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
41973 fn++;
41974 }
41975 } else {
41976 /* May happen in some out-of-memory corner cases. */
41977 DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping marking"));
41978 }
41979 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
41981 DUK_UNREF(f);
41982 /* nothing to mark */
41983 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
41985 duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
41986 } else if (DUK_HOBJECT_IS_THREAD(h)) {
41987 duk_hthread *t = (duk_hthread *) h;
41988 duk_tval *tv;
41989
41990 tv = t->valstack;
41991 while (tv < t->valstack_top) {
41992 duk__mark_tval(heap, tv);
41993 tv++;
41994 }
41995
41996 for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
41997 duk_activation *act = t->callstack + i;
41999 duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
42000 duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
42001#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
42002 duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
42003#endif
42004 }
42006#if 0 /* nothing now */
42007 for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
42008 duk_catcher *cat = t->catchstack + i;
42009 }
42010#endif
42011
42013
42014 /* XXX: duk_small_uint_t would be enough for this loop */
42015 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
42016 duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
42017 }
42018 }
42019}
42020
42021/* recursion tracking happens here only */
42023 DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
42024 (void *) h,
42025 (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
42026 if (!h) {
42027 return;
42028 }
42029#if defined(DUK_USE_ROM_OBJECTS)
42030 if (DUK_HEAPHDR_HAS_READONLY(h)) {
42031 DUK_DDD(DUK_DDDPRINT("readonly object %p, skip", (void *) h));
42032 return;
42033 }
42034#endif
42036 DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
42037 return;
42038 }
42040
42042 /* log this with a normal debug level because this should be relatively rare */
42043 DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
42046 return;
42047 }
42048
42050
42051 switch ((int) DUK_HEAPHDR_GET_TYPE(h)) {
42053 duk__mark_hstring(heap, (duk_hstring *) h);
42054 break;
42055 case DUK_HTYPE_OBJECT:
42056 duk__mark_hobject(heap, (duk_hobject *) h);
42057 break;
42058 case DUK_HTYPE_BUFFER:
42059 /* nothing to mark */
42060 break;
42061 default:
42062 DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
42064 }
42065
42067}
42068
42069DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
42070 DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
42071 if (!tv) {
42072 return;
42073 }
42076 }
42077}
42078
42079/*
42080 * Mark the heap.
42081 */
42082
42085
42086 DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
42087
42088 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
42089 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
42090
42091 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
42092 duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
42093 duk__mark_heaphdr(heap, (duk_heaphdr *) h);
42094 }
42095
42096 duk__mark_tval(heap, &heap->lj.value1);
42097 duk__mark_tval(heap, &heap->lj.value2);
42098
42099#if defined(DUK_USE_DEBUGGER_SUPPORT)
42100 for (i = 0; i < heap->dbg_breakpoint_count; i++) {
42101 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
42102 }
42103#endif
42104}
42105
42106/*
42107 * Mark refzero_list objects.
42108 *
42109 * Objects on the refzero_list have no inbound references. They might have
42110 * outbound references to objects that we might free, which would invalidate
42111 * any references held by the refzero objects. A refzero object might also
42112 * be rescued by refcount finalization. Refzero objects are treated as
42113 * reachability roots to ensure they (or anything they point to) are not
42114 * freed in mark-and-sweep.
42115 */
42116
42117#ifdef DUK_USE_REFERENCE_COUNTING
42119 duk_heaphdr *hdr;
42120
42121 DUK_DD(DUK_DDPRINT("duk__mark_refzero_list: %p", (void *) heap));
42122
42123 hdr = heap->refzero_list;
42124 while (hdr) {
42125 duk__mark_heaphdr(heap, hdr);
42126 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42127 }
42128}
42129#endif
42130
42131/*
42132 * Mark unreachable, finalizable objects.
42133 *
42134 * Such objects will be moved aside and their finalizers run later. They have
42135 * to be treated as reachability roots for their properties etc to remain
42136 * allocated. This marking is only done for unreachable values which would
42137 * be swept later (refzero_list is thus excluded).
42138 *
42139 * Objects are first marked FINALIZABLE and only then marked as reachability
42140 * roots; otherwise circular references might be handled inconsistently.
42141 */
42142
42144 duk_hthread *thr;
42145 duk_heaphdr *hdr;
42146 duk_size_t count_finalizable = 0;
42147
42148 DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
42149
42150 thr = duk__get_temp_hthread(heap);
42151 DUK_ASSERT(thr != NULL);
42152
42153 hdr = heap->heap_allocated;
42154 while (hdr) {
42155 /* A finalizer is looked up from the object and up its prototype chain
42156 * (which allows inherited finalizers). A prototype loop must not cause
42157 * an error to be thrown here; duk_hobject_hasprop_raw() will ignore a
42158 * prototype loop silently and indicate that the property doesn't exist.
42159 */
42160
42161 if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
42165
42166 /* heaphdr:
42167 * - is not reachable
42168 * - is an object
42169 * - is not a finalized object
42170 * - has a finalizer
42171 */
42172
42173 DUK_DD(DUK_DDPRINT("unreachable heap object will be "
42174 "finalized -> mark as finalizable "
42175 "and treat as a reachability root: %p",
42176 (void *) hdr));
42179 count_finalizable ++;
42180 }
42181
42182 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42183 }
42184
42185 if (count_finalizable == 0) {
42186 return;
42187 }
42188
42189 DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
42190 (long) count_finalizable));
42191
42192 hdr = heap->heap_allocated;
42193 while (hdr) {
42194 if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
42195 duk__mark_heaphdr(heap, hdr);
42196 }
42197
42198 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42199 }
42200
42201 /* Caller will finish the marking process if we hit a recursion limit. */
42202}
42203
42204/*
42205 * Mark objects on finalize_list.
42206 *
42207 */
42208
42210 duk_heaphdr *hdr;
42211#ifdef DUK_USE_DEBUG
42212 duk_size_t count_finalize_list = 0;
42213#endif
42214
42215 DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
42216
42217 hdr = heap->finalize_list;
42218 while (hdr) {
42219 duk__mark_heaphdr(heap, hdr);
42220 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42221#ifdef DUK_USE_DEBUG
42222 count_finalize_list++;
42223#endif
42224 }
42225
42226#ifdef DUK_USE_DEBUG
42227 if (count_finalize_list > 0) {
42228 DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
42229 (long) count_finalize_list));
42230 }
42231#endif
42232}
42233
42235 * Fallback marking handler if recursion limit is reached.
42236 *
42237 * Iterates 'temproots' until recursion limit is no longer hit. Note
42238 * that temproots may reside either in heap allocated list or the
42239 * refzero work list. This is a slow scan, but guarantees that we
42240 * finish with a bounded C stack.
42241 *
42242 * Note that nodes may have been marked as temproots before this
42243 * scan begun, OR they may have been marked during the scan (as
42244 * we process nodes recursively also during the scan). This is
42245 * intended behavior.
42246 */
42247
42248#ifdef DUK_USE_DEBUG
42250#else
42252#endif
42253 if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
42254 DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
42255 return;
42256 }
42257
42258 DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
42260 DUK_HEAPHDR_CLEAR_REACHABLE(hdr); /* done so that duk__mark_heaphdr() works correctly */
42261 duk__mark_heaphdr(heap, hdr);
42262
42263#ifdef DUK_USE_DEBUG
42264 (*count)++;
42265#endif
42266}
42267
42269 duk_heaphdr *hdr;
42270#ifdef DUK_USE_DEBUG
42271 duk_size_t count;
42272#endif
42273
42274 DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
42275
42277 DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
42278
42279#ifdef DUK_USE_DEBUG
42280 count = 0;
42281#endif
42283
42284 hdr = heap->heap_allocated;
42285 while (hdr) {
42286#ifdef DUK_USE_DEBUG
42287 duk__handle_temproot(heap, hdr, &count);
42288#else
42289 duk__handle_temproot(heap, hdr);
42290#endif
42291 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42292 }
42293
42294 /* must also check refzero_list */
42295#ifdef DUK_USE_REFERENCE_COUNTING
42296 hdr = heap->refzero_list;
42297 while (hdr) {
42298#ifdef DUK_USE_DEBUG
42299 duk__handle_temproot(heap, hdr, &count);
42300#else
42301 duk__handle_temproot(heap, hdr);
42302#endif
42303 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42304 }
42305#endif /* DUK_USE_REFERENCE_COUNTING */
42307#ifdef DUK_USE_DEBUG
42308 DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
42309#endif
42310 }
42311}
42312
42313/*
42314 * Finalize refcounts for heap elements just about to be freed.
42315 * This must be done for all objects before freeing to avoid any
42316 * stale pointer dereferences.
42317 *
42318 * Note that this must deduce the set of objects to be freed
42319 * identically to duk__sweep_heap().
42320 */
42321
42322#ifdef DUK_USE_REFERENCE_COUNTING
42324 duk_hthread *thr;
42325 duk_heaphdr *hdr;
42326
42327 thr = duk__get_temp_hthread(heap);
42328 DUK_ASSERT(thr != NULL);
42329
42330 DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p, hthread=%p",
42331 (void *) heap, (void *) thr));
42332
42333 hdr = heap->heap_allocated;
42334 while (hdr) {
42335 if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
42336 /*
42337 * Unreachable object about to be swept. Finalize target refcounts
42338 * (objects which the unreachable object points to) without doing
42339 * refzero processing. Recursive decrefs are also prevented when
42340 * refzero processing is disabled.
42341 *
42342 * Value cannot be a finalizable object, as they have been made
42343 * temporarily reachable for this round.
42344 */
42345
42346 DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
42348 }
42349
42350 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42351 }
42352}
42353#endif /* DUK_USE_REFERENCE_COUNTING */
42354
42355/*
42356 * Clear (reachable) flags of refzero work list.
42357 */
42358
42359#ifdef DUK_USE_REFERENCE_COUNTING
42361 duk_heaphdr *hdr;
42362
42363 DUK_DD(DUK_DDPRINT("duk__clear_refzero_list_flags: %p", (void *) heap));
42364
42365 hdr = heap->refzero_list;
42366 while (hdr) {
42371 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42372 }
42373}
42374#endif /* DUK_USE_REFERENCE_COUNTING */
42375
42376/*
42377 * Clear (reachable) flags of finalize_list
42378 *
42379 * We could mostly do in the sweep phase when we move objects from the
42380 * heap into the finalize_list. However, if a finalizer run is skipped
42381 * during a mark-and-sweep, the objects on the finalize_list will be marked
42382 * reachable during the next mark-and-sweep. Since they're already on the
42383 * finalize_list, no-one will be clearing their REACHABLE flag so we do it
42384 * here. (This now overlaps with the sweep handling in a harmless way.)
42385 */
42386
42388 duk_heaphdr *hdr;
42389
42390 DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
42391
42392 hdr = heap->finalize_list;
42393 while (hdr) {
42398 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42399 }
42400}
42401
42402/*
42403 * Sweep stringtable
42404 */
42405
42406#if defined(DUK_USE_STRTAB_CHAIN)
42407
42408/* XXX: skip count_free w/o debug? */
42409#if defined(DUK_USE_HEAPPTR16)
42410DUK_LOCAL void duk__sweep_string_chain16(duk_heap *heap, duk_uint16_t *slot, duk_size_t *count_keep, duk_size_t *count_free) {
42411 duk_uint16_t h16 = *slot;
42412 duk_hstring *h;
42413 duk_uint16_t null16 = heap->heapptr_null16;
42414
42415 if (h16 == null16) {
42416 /* nop */
42417 return;
42418 }
42419 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, h16);
42420 DUK_ASSERT(h != NULL);
42421
42424 (*count_keep)++;
42425 } else {
42426#if defined(DUK_USE_REFERENCE_COUNTING)
42428#endif
42429 /* deal with weak references first */
42431 *slot = null16;
42432
42433 /* free inner references (these exist e.g. when external
42434 * strings are enabled)
42435 */
42436 duk_free_hstring_inner(heap, h);
42437 DUK_FREE(heap, h);
42438 (*count_free)++;
42439 }
42440}
42441#else /* DUK_USE_HEAPPTR16 */
42442DUK_LOCAL void duk__sweep_string_chain(duk_heap *heap, duk_hstring **slot, duk_size_t *count_keep, duk_size_t *count_free) {
42443 duk_hstring *h = *slot;
42444
42445 if (h == NULL) {
42446 /* nop */
42447 return;
42448 }
42449
42452 (*count_keep)++;
42453 } else {
42454#if defined(DUK_USE_REFERENCE_COUNTING)
42456#endif
42457 /* deal with weak references first */
42459 *slot = NULL;
42460
42461 /* free inner references (these exist e.g. when external
42462 * strings are enabled)
42463 */
42464 duk_free_hstring_inner(heap, h);
42465 DUK_FREE(heap, h);
42466 (*count_free)++;
42467 }
42468}
42469#endif /* DUK_USE_HEAPPTR16 */
42470
42471DUK_LOCAL void duk__sweep_stringtable_chain(duk_heap *heap, duk_size_t *out_count_keep) {
42474 duk_size_t count_free = 0;
42475 duk_size_t count_keep = 0;
42476 duk_size_t j, n;
42477#if defined(DUK_USE_HEAPPTR16)
42478 duk_uint16_t *lst;
42479#else
42480 duk_hstring **lst;
42481#endif
42482
42483 DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
42484
42485 /* Non-zero refcounts should not happen for unreachable strings,
42486 * because we refcount finalize all unreachable objects which
42487 * should have decreased unreachable string refcounts to zero
42488 * (even for cycles).
42489 */
42490
42491 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
42492 e = heap->strtable + i;
42493 if (e->listlen == 0) {
42494#if defined(DUK_USE_HEAPPTR16)
42495 duk__sweep_string_chain16(heap, &e->u.str16, &count_keep, &count_free);
42496#else
42497 duk__sweep_string_chain(heap, &e->u.str, &count_keep, &count_free);
42498#endif
42499 } else {
42500#if defined(DUK_USE_HEAPPTR16)
42501 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
42502#else
42503 lst = e->u.strlist;
42504#endif
42505 for (j = 0, n = e->listlen; j < n; j++) {
42506#if defined(DUK_USE_HEAPPTR16)
42507 duk__sweep_string_chain16(heap, lst + j, &count_keep, &count_free);
42508#else
42509 duk__sweep_string_chain(heap, lst + j, &count_keep, &count_free);
42510#endif
42511 }
42512 }
42513 }
42514
42515 DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
42516 (long) count_free, (long) count_keep));
42517 *out_count_keep = count_keep;
42518}
42519#endif /* DUK_USE_STRTAB_CHAIN */
42520
42521#if defined(DUK_USE_STRTAB_PROBE)
42522DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep) {
42523 duk_hstring *h;
42525#ifdef DUK_USE_DEBUG
42526 duk_size_t count_free = 0;
42527#endif
42528 duk_size_t count_keep = 0;
42529
42530 DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
42531
42532 for (i = 0; i < heap->st_size; i++) {
42533#if defined(DUK_USE_HEAPPTR16)
42534 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
42535#else
42536 h = heap->strtable[i];
42537#endif
42538 if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
42539 continue;
42540 } else if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
42542 count_keep++;
42543 continue;
42544 }
42545
42546#ifdef DUK_USE_DEBUG
42547 count_free++;
42548#endif
42549
42550#if defined(DUK_USE_REFERENCE_COUNTING)
42551 /* Non-zero refcounts should not happen for unreachable strings,
42552 * because we refcount finalize all unreachable objects which
42553 * should have decreased unreachable string refcounts to zero
42554 * (even for cycles).
42555 */
42557#endif
42558
42559 DUK_DDD(DUK_DDDPRINT("sweep string, not reachable: %p", (void *) h));
42560
42561 /* deal with weak references first */
42563
42564 /* remove the string (mark DELETED), could also call
42565 * duk_heap_string_remove() but that would be slow and
42566 * pointless because we already know the slot.
42567 */
42568#if defined(DUK_USE_HEAPPTR16)
42569 heap->strtable16[i] = heap->heapptr_deleted16;
42570#else
42571 heap->strtable[i] = DUK_STRTAB_DELETED_MARKER(heap);
42572#endif
42573
42574 /* free inner references (these exist e.g. when external
42575 * strings are enabled)
42576 */
42579 /* finally free the struct itself */
42580 DUK_FREE(heap, h);
42581 }
42582
42583#ifdef DUK_USE_DEBUG
42584 DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
42585 (long) count_free, (long) count_keep));
42586#endif
42587 *out_count_keep = count_keep;
42588}
42589#endif /* DUK_USE_STRTAB_PROBE */
42590
42591/*
42592 * Sweep heap
42593 */
42594
42595DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep) {
42596 duk_heaphdr *prev; /* last element that was left in the heap */
42597 duk_heaphdr *curr;
42599#ifdef DUK_USE_DEBUG
42600 duk_size_t count_free = 0;
42601 duk_size_t count_finalize = 0;
42602 duk_size_t count_rescue = 0;
42603#endif
42604 duk_size_t count_keep = 0;
42605
42606 DUK_UNREF(flags);
42607 DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
42608
42609 prev = NULL;
42610 curr = heap->heap_allocated;
42611 heap->heap_allocated = NULL;
42612 while (curr) {
42613 /* Strings and ROM objects are never placed on the heap allocated list. */
42616
42617 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
42618
42619 if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
42620 /*
42621 * Reachable object, keep
42622 */
42623
42624 DUK_DDD(DUK_DDDPRINT("sweep, reachable: %p", (void *) curr));
42625
42626 if (DUK_HEAPHDR_HAS_FINALIZABLE(curr)) {
42627 /*
42628 * If object has been marked finalizable, move it to the
42629 * "to be finalized" work list. It will be collected on
42630 * the next mark-and-sweep if it is still unreachable
42631 * after running the finalizer.
42632 */
42633
42636 DUK_DDD(DUK_DDDPRINT("object has finalizer, move to finalization work list: %p", (void *) curr));
42637
42638#ifdef DUK_USE_DOUBLE_LINKED_HEAP
42639 if (heap->finalize_list) {
42640 DUK_HEAPHDR_SET_PREV(heap, heap->finalize_list, curr);
42641 }
42642 DUK_HEAPHDR_SET_PREV(heap, curr, NULL);
42643#endif
42644 DUK_HEAPHDR_SET_NEXT(heap, curr, heap->finalize_list);
42645 DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
42646 heap->finalize_list = curr;
42647#ifdef DUK_USE_DEBUG
42648 count_finalize++;
42649#endif
42650 } else {
42651 /*
42652 * Object will be kept; queue object back to heap_allocated (to tail)
42653 */
42654
42655 if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
42656 /*
42657 * Object's finalizer was executed on last round, and
42658 * object has been happily rescued.
42659 */
42660
42663 DUK_DD(DUK_DDPRINT("object rescued during mark-and-sweep finalization: %p", (void *) curr));
42664#ifdef DUK_USE_DEBUG
42665 count_rescue++;
42666#endif
42667 } else {
42668 /*
42669 * Plain, boring reachable object.
42670 */
42671 DUK_DD(DUK_DDPRINT("keep object: %!iO", curr));
42672 count_keep++;
42673 }
42674
42675 if (!heap->heap_allocated) {
42676 heap->heap_allocated = curr;
42677 }
42678 if (prev) {
42679 DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
42680 }
42681#ifdef DUK_USE_DOUBLE_LINKED_HEAP
42682 DUK_HEAPHDR_SET_PREV(heap, curr, prev);
42683#endif
42684 DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
42685 DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
42686 prev = curr;
42687 }
42688
42692
42696
42697 curr = next;
42698 } else {
42699 /*
42700 * Unreachable object, free
42701 */
42702
42703 DUK_DDD(DUK_DDDPRINT("sweep, not reachable: %p", (void *) curr));
42704
42705#if defined(DUK_USE_REFERENCE_COUNTING)
42706 /* Non-zero refcounts should not happen because we refcount
42707 * finalize all unreachable objects which should cancel out
42708 * refcounts (even for cycles).
42709 */
42711#endif
42713
42714 if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
42715 DUK_DDD(DUK_DDDPRINT("finalized object not rescued: %p", (void *) curr));
42716 }
42717
42718 /* Note: object cannot be a finalizable unreachable object, as
42719 * they have been marked temporarily reachable for this round,
42720 * and are handled above.
42721 */
42722
42723#ifdef DUK_USE_DEBUG
42724 count_free++;
42725#endif
42726
42727 /* weak refs should be handled here, but no weak refs for
42728 * any non-string objects exist right now.
42729 */
42730
42731 /* free object and all auxiliary (non-heap) allocs */
42732 duk_heap_free_heaphdr_raw(heap, curr);
42733
42734 curr = next;
42735 }
42737 if (prev) {
42738 DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
42739 }
42740 DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
42741
42742#ifdef DUK_USE_DEBUG
42743 DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
42744 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
42745#endif
42746 *out_count_keep = count_keep;
42747}
42748
42749/*
42750 * Run (object) finalizers in the "to be finalized" work list.
42751 */
42752
42754 duk_heaphdr *curr;
42756#ifdef DUK_USE_DEBUG
42757 duk_size_t count = 0;
42758#endif
42759 duk_hthread *thr;
42760
42761 DUK_DD(DUK_DDPRINT("duk__run_object_finalizers: %p", (void *) heap));
42762
42763 thr = duk__get_temp_hthread(heap);
42764 DUK_ASSERT(thr != NULL);
42765
42766 curr = heap->finalize_list;
42767 while (curr) {
42768 DUK_DDD(DUK_DDDPRINT("mark-and-sweep finalize: %p", (void *) curr));
42769
42770 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* only objects have finalizers */
42771 DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr)); /* flags have been already cleared */
42775 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr)); /* No finalizers for ROM objects */
42776
42777 if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
42778 /* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
42779 * Next mark-and-sweep will collect the object unless it has
42780 * become reachable (i.e. rescued). FINALIZED prevents the
42781 * finalizer from being executed again before that.
42782 */
42783 duk_hobject_run_finalizer(thr, (duk_hobject *) curr); /* must never longjmp */
42785 } else {
42786 /* Used during heap destruction: don't actually run finalizers
42787 * because we're heading into forced finalization. Instead,
42788 * queue finalizable objects back to the heap_allocated list.
42789 */
42790 DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
42792 }
42793
42794 /* queue back to heap_allocated */
42795 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
42797
42798 curr = next;
42799#ifdef DUK_USE_DEBUG
42800 count++;
42801#endif
42802 }
42803
42804 /* finalize_list will always be processed completely */
42805 heap->finalize_list = NULL;
42806
42807#ifdef DUK_USE_DEBUG
42808 DUK_D(DUK_DPRINT("mark-and-sweep finalize objects: %ld finalizers called", (long) count));
42809#endif
42810}
42811
42812/*
42813 * Object compaction.
42814 *
42815 * Compaction is assumed to never throw an error.
42816 */
42817
42819 /* XXX: for threads, compact value stack, call stack, catch stack? */
42820
42821 duk_hobject *obj = duk_get_hobject(ctx, -1);
42822 DUK_ASSERT(obj != NULL);
42824 return 0;
42825}
42826
42827#ifdef DUK_USE_DEBUG
42828DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) {
42829#else
42831#endif
42832 duk_heaphdr *curr;
42833#ifdef DUK_USE_DEBUG
42834 duk_size_t old_size, new_size;
42835#endif
42836 duk_hobject *obj;
42837
42838 DUK_UNREF(heap);
42839
42840 curr = start;
42841 while (curr) {
42842 DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
42843
42845 goto next;
42846 }
42847 obj = (duk_hobject *) curr;
42848
42849#ifdef DUK_USE_DEBUG
42853#endif
42854
42855 DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
42856 duk_push_hobject((duk_context *) thr, obj);
42857 /* XXX: disable error handlers for duration of compaction? */
42859
42860#ifdef DUK_USE_DEBUG
42864#endif
42865
42866#ifdef DUK_USE_DEBUG
42867 (*p_count_compact)++;
42868 (*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
42869#endif
42870
42871 next:
42872 curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
42873#ifdef DUK_USE_DEBUG
42874 (*p_count_check)++;
42875#endif
42876 }
42877}
42878
42880 /* XXX: which lists should participate? to be finalized? */
42881#ifdef DUK_USE_DEBUG
42882 duk_size_t count_check = 0;
42883 duk_size_t count_compact = 0;
42884 duk_size_t count_bytes_saved = 0;
42885#endif
42886 duk_hthread *thr;
42887
42888 DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
42889
42890 thr = duk__get_temp_hthread(heap);
42891 DUK_ASSERT(thr != NULL);
42892
42893#ifdef DUK_USE_DEBUG
42894 duk__compact_object_list(heap, thr, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
42895 duk__compact_object_list(heap, thr, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
42896#ifdef DUK_USE_REFERENCE_COUNTING
42897 duk__compact_object_list(heap, thr, heap->refzero_list, &count_check, &count_compact, &count_bytes_saved);
42898#endif
42899#else
42900 duk__compact_object_list(heap, thr, heap->heap_allocated);
42901 duk__compact_object_list(heap, thr, heap->finalize_list);
42902#ifdef DUK_USE_REFERENCE_COUNTING
42903 duk__compact_object_list(heap, thr, heap->refzero_list);
42904#endif
42905#endif
42906
42907#ifdef DUK_USE_DEBUG
42908 DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
42909 (long) count_check, (long) count_compact, (long) count_bytes_saved));
42910#endif
42911}
42912
42913/*
42914 * Assertion helpers.
42915 */
42916
42917#ifdef DUK_USE_ASSERTIONS
42918DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
42919 duk_heaphdr *hdr;
42920
42921 hdr = heap->heap_allocated;
42922 while (hdr) {
42926 /* may have FINALIZED */
42927 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42928 }
42929
42930#ifdef DUK_USE_REFERENCE_COUNTING
42931 hdr = heap->refzero_list;
42932 while (hdr) {
42937 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42938 }
42939#endif /* DUK_USE_REFERENCE_COUNTING */
42940}
42941
42942#ifdef DUK_USE_REFERENCE_COUNTING
42943DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
42944 duk_heaphdr *hdr = heap->heap_allocated;
42945 while (hdr) {
42946 if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
42948 /* An object may be in heap_allocated list with a zero
42949 * refcount if it has just been finalized and is waiting
42950 * to be collected by the next cycle.
42951 */
42952 } else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
42953 /* An object may be in heap_allocated list with a zero
42954 * refcount also if it is a temporary object created by
42955 * a finalizer; because finalization now runs inside
42956 * mark-and-sweep, such objects will not be queued to
42957 * refzero_list and will thus appear here with refcount
42958 * zero.
42959 */
42960#if 0 /* this case can no longer occur because refcount is unsigned */
42961 } else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) < 0) {
42962 DUK_D(DUK_DPRINT("invalid refcount: %ld, %p -> %!O",
42963 (hdr != NULL ? (long) DUK_HEAPHDR_GET_REFCOUNT(hdr) : (long) 0),
42964 (void *) hdr, (duk_heaphdr *) hdr));
42966#endif
42967 }
42968 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42969 }
42970}
42971#endif /* DUK_USE_REFERENCE_COUNTING */
42972#endif /* DUK_USE_ASSERTIONS */
42973
42974/*
42975 * Finalizer torture. Do one fake finalizer call which causes side effects
42976 * similar to one or more finalizers on actual objects.
42977 */
42978
42979#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
42980DUK_LOCAL duk_ret_t duk__markandsweep_fake_finalizer(duk_context *ctx) {
42981 DUK_D(DUK_DPRINT("fake mark-and-sweep torture finalizer executed"));
42982
42983 /* Require a lot of stack to force a value stack grow/shrink.
42984 * Recursive mark-and-sweep is prevented by allocation macros
42985 * so this won't trigger another mark-and-sweep.
42986 */
42987 duk_require_stack(ctx, 100000);
42988
42989 /* XXX: do something to force a callstack grow/shrink, perhaps
42990 * just a manual forced resize or a forced relocating realloc?
42991 */
42992
42993 return 0;
42994}
42995
42996DUK_LOCAL void duk__markandsweep_torture_finalizer(duk_hthread *thr) {
42997 duk_context *ctx;
42998 duk_int_t rc;
42999
43000 DUK_ASSERT(thr != NULL);
43001 ctx = (duk_context *) thr;
43002
43003 /* Avoid fake finalization when callstack limit has been reached.
43004 * Otherwise a callstack limit error will be created, then refzero'ed.
43005 */
43007 thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
43008 DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake mark-and-sweep torture finalizer"));
43009 return;
43010 }
43011
43012 /* Run fake finalizer. Avoid creating unnecessary garbage. */
43013 duk_push_c_function(ctx, duk__markandsweep_fake_finalizer, 0 /*nargs*/);
43014 rc = duk_pcall(ctx, 0 /*nargs*/);
43015 DUK_UNREF(rc); /* ignored */
43016 duk_pop(ctx);
43017}
43018#endif /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
43019
43020/*
43021 * Main mark-and-sweep function.
43022 *
43023 * 'flags' represents the features requested by the caller. The current
43024 * heap->mark_and_sweep_base_flags is ORed automatically into the flags;
43025 * the base flags mask typically prevents certain mark-and-sweep operations
43026 * to avoid trouble.
43027 */
43028
43030 duk_hthread *thr;
43031 duk_size_t count_keep_obj;
43032 duk_size_t count_keep_str;
43033#ifdef DUK_USE_VOLUNTARY_GC
43034 duk_size_t tmp;
43035#endif
43036
43037 /* XXX: thread selection for mark-and-sweep is currently a hack.
43038 * If we don't have a thread, the entire mark-and-sweep is now
43039 * skipped (although we could just skip finalizations).
43040 */
43041
43042 /* If thr != NULL, the thr may still be in the middle of
43043 * initialization.
43044 * XXX: Improve the thread viability test.
43045 */
43046 thr = duk__get_temp_hthread(heap);
43047 if (thr == NULL) {
43048 DUK_D(DUK_DPRINT("gc skipped because we don't have a temp thread"));
43049
43050 /* reset voluntary gc trigger count */
43051#ifdef DUK_USE_VOLUNTARY_GC
43053#endif
43054 return 0; /* OK */
43055 }
43056
43057 /* If debugger is paused, garbage collection is disabled by default. */
43058 /* XXX: will need a force flag if garbage collection is triggered
43059 * explicitly during paused state.
43060 */
43061#if defined(DUK_USE_DEBUGGER_SUPPORT)
43062 if (DUK_HEAP_IS_PAUSED(heap)) {
43063 /* Checking this here rather that in memory alloc primitives
43064 * reduces checking code there but means a failed allocation
43065 * will go through a few retries before giving up. That's
43066 * fine because this only happens during debugging.
43067 */
43068 DUK_D(DUK_DPRINT("gc skipped because debugger is paused"));
43069 return 0;
43070 }
43071#endif
43072
43073 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
43074 (unsigned long) flags, (unsigned long) (flags | heap->mark_and_sweep_base_flags)));
43075
43076 flags |= heap->mark_and_sweep_base_flags;
43077
43078 /*
43079 * Assertions before
43080 */
43081
43082#ifdef DUK_USE_ASSERTIONS
43086 duk__assert_heaphdr_flags(heap);
43087#ifdef DUK_USE_REFERENCE_COUNTING
43088 /* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
43089 * finalizer may trigger a mark-and-sweep.
43090 */
43091 duk__assert_valid_refcounts(heap);
43092#endif /* DUK_USE_REFERENCE_COUNTING */
43093#endif /* DUK_USE_ASSERTIONS */
43094
43095 /*
43096 * Begin
43097 */
43098
43100
43101 /*
43102 * Mark roots, hoping that recursion limit is not normally hit.
43103 * If recursion limit is hit, run additional reachability rounds
43104 * starting from "temproots" until marking is complete.
43105 *
43106 * Marking happens in two phases: first we mark actual reachability
43107 * roots (and run "temproots" to complete the process). Then we
43108 * check which objects are unreachable and are finalizable; such
43109 * objects are marked as FINALIZABLE and marked as reachability
43110 * (and "temproots" is run again to complete the process).
43111 *
43112 * The heap finalize_list must also be marked as a reachability root.
43113 * There may be objects on the list from a previous round if the
43114 * previous run had finalizer skip flag.
43115 */
43116
43117 duk__mark_roots_heap(heap); /* main reachability roots */
43118#ifdef DUK_USE_REFERENCE_COUNTING
43119 duk__mark_refzero_list(heap); /* refzero_list treated as reachability roots */
43120#endif
43121 duk__mark_temproots_by_heap_scan(heap); /* temproots */
43122
43123 duk__mark_finalizable(heap); /* mark finalizable as reachability roots */
43124 duk__mark_finalize_list(heap); /* mark finalizer work list as reachability roots */
43125 duk__mark_temproots_by_heap_scan(heap); /* temproots */
43126
43127 /*
43128 * Sweep garbage and remove marking flags, and move objects with
43129 * finalizers to the finalizer work list.
43130 *
43131 * Objects to be swept need to get their refcounts finalized before
43132 * they are swept. In other words, their target object refcounts
43133 * need to be decreased. This has to be done before freeing any
43134 * objects to avoid decref'ing dangling pointers (which may happen
43135 * even without bugs, e.g. with reference loops)
43136 *
43137 * Because strings don't point to other heap objects, similar
43138 * finalization is not necessary for strings.
43139 */
43140
43141 /* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
43142
43143#ifdef DUK_USE_REFERENCE_COUNTING
43145#endif
43146 duk__sweep_heap(heap, flags, &count_keep_obj);
43147#if defined(DUK_USE_STRTAB_CHAIN)
43148 duk__sweep_stringtable_chain(heap, &count_keep_str);
43149#elif defined(DUK_USE_STRTAB_PROBE)
43150 duk__sweep_stringtable_probe(heap, &count_keep_str);
43151#else
43152#error internal error, invalid strtab options
43153#endif
43154#ifdef DUK_USE_REFERENCE_COUNTING
43156#endif
43158
43159 /*
43160 * Object compaction (emergency only).
43161 *
43162 * Object compaction is a separate step after sweeping, as there is
43163 * more free memory for it to work with. Also, currently compaction
43164 * may insert new objects into the heap allocated list and the string
43165 * table which we don't want to do during a sweep (the reachability
43166 * flags of such objects would be incorrect). The objects inserted
43167 * are currently:
43168 *
43169 * - a temporary duk_hbuffer for a new properties allocation
43170 * - if array part is abandoned, string keys are interned
43171 *
43172 * The object insertions go to the front of the list, so they do not
43173 * cause an infinite loop (they are not compacted).
43174 */
43175
43176 if ((flags & DUK_MS_FLAG_EMERGENCY) &&
43179 }
43180
43181 /*
43182 * String table resize check.
43183 *
43184 * Note: this may silently (and safely) fail if GC is caused by an
43185 * allocation call in stringtable resize_hash(). Resize_hash()
43186 * will prevent a recursive call to itself by setting the
43187 * DUK_MS_FLAG_NO_STRINGTABLE_RESIZE in heap->mark_and_sweep_base_flags.
43188 */
43189
43190 /* XXX: stringtable emergency compaction? */
43191
43192 /* XXX: remove this feature entirely? it would only matter for
43193 * emergency GC. Disable for lowest memory builds.
43194 */
43195#if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
43196 if (!(flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE)) {
43197 DUK_DD(DUK_DDPRINT("resize stringtable: %p", (void *) heap));
43199 } else {
43200 DUK_D(DUK_DPRINT("stringtable resize skipped because DUK_MS_FLAG_NO_STRINGTABLE_RESIZE is set"));
43201 }
43202#endif
43203
43204 /*
43205 * Finalize objects in the finalization work list. Finalized
43206 * objects are queued back to heap_allocated with FINALIZED set.
43207 *
43208 * Since finalizers may cause arbitrary side effects, they are
43209 * prevented during string table and object property allocation
43210 * resizing using the DUK_MS_FLAG_NO_FINALIZERS flag in
43211 * heap->mark_and_sweep_base_flags. In this case the objects
43212 * remain in the finalization work list after mark-and-sweep
43213 * exits and they may be finalized on the next pass.
43214 *
43215 * Finalization currently happens inside "MARKANDSWEEP_RUNNING"
43216 * protection (no mark-and-sweep may be triggered by the
43217 * finalizers). As a side effect:
43218 *
43219 * 1) an out-of-memory error inside a finalizer will not
43220 * cause a mark-and-sweep and may cause the finalizer
43221 * to fail unnecessarily
43222 *
43223 * 2) any temporary objects whose refcount decreases to zero
43224 * during finalization will not be put into refzero_list;
43225 * they can only be collected by another mark-and-sweep
43226 *
43227 * This is not optimal, but since the sweep for this phase has
43228 * already happened, this is probably good enough for now.
43229 */
43230
43231#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
43232 /* Cannot simulate individual finalizers because finalize_list only
43233 * contains objects with actual finalizers. But simulate side effects
43234 * from finalization by doing a bogus function call and resizing the
43235 * stacks.
43236 */
43237 if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
43238 DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, DUK_MS_FLAG_NO_FINALIZERS is set"));
43239 } else if (!(thr->valstack != NULL && thr->callstack != NULL && thr->catchstack != NULL)) {
43240 DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, thread not yet viable"));
43241 } else {
43242 DUK_D(DUK_DPRINT("run mark-and-sweep torture finalizer"));
43243 duk__markandsweep_torture_finalizer(thr);
43244 }
43245#endif /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
43246
43247 if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
43248 DUK_D(DUK_DPRINT("finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set"));
43249 } else {
43250 duk__run_object_finalizers(heap, flags);
43251 }
43252
43253 /*
43254 * Finish
43255 */
43256
43258
43259 /*
43260 * Assertions after
43261 */
43262
43263#ifdef DUK_USE_ASSERTIONS
43267 duk__assert_heaphdr_flags(heap);
43268#ifdef DUK_USE_REFERENCE_COUNTING
43269 /* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
43270 * finalizer may trigger a mark-and-sweep.
43271 */
43272 duk__assert_valid_refcounts(heap);
43273#endif /* DUK_USE_REFERENCE_COUNTING */
43274#endif /* DUK_USE_ASSERTIONS */
43275
43276 /*
43277 * Reset trigger counter
43278 */
43279
43280#ifdef DUK_USE_VOLUNTARY_GC
43281 tmp = (count_keep_obj + count_keep_str) / 256;
43285 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
43286 (long) count_keep_obj, (long) count_keep_str, (long) heap->mark_and_sweep_trigger_counter));
43287#else
43288 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
43289 (long) count_keep_obj, (long) count_keep_str));
43290#endif
43291
43292 return 0; /* OK */
43293}
43294
43295#else /* DUK_USE_MARK_AND_SWEEP */
43296
43297/* no mark-and-sweep gc */
43299#endif /* DUK_USE_MARK_AND_SWEEP */
43300/*
43301 * Memory allocation handling.
43302 */
43303
43304/* include removed: duk_internal.h */
43306/*
43307 * Helpers
43308 *
43309 * The fast path checks are done within a macro to ensure "inlining"
43310 * while the slow path actions use a helper (which won't typically be
43311 * inlined in size optimized builds).
43312 */
43313
43314#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
43315#define DUK__VOLUNTARY_PERIODIC_GC(heap) do { \
43316 (heap)->mark_and_sweep_trigger_counter--; \
43317 if ((heap)->mark_and_sweep_trigger_counter <= 0) { \
43318 duk__run_voluntary_gc(heap); \
43319 } \
43320 } while (0)
43321
43324 DUK_DD(DUK_DDPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
43325 } else {
43326 duk_small_uint_t flags;
43328
43329 DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
43330 flags = 0;
43331 rc = duk_heap_mark_and_sweep(heap, flags);
43332 DUK_UNREF(rc);
43333 }
43334}
43335#else
43336#define DUK__VOLUNTARY_PERIODIC_GC(heap) /* no voluntary gc */
43337#endif /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
43338
43339/*
43340 * Allocate memory with garbage collection
43341 */
43342
43343#ifdef DUK_USE_MARK_AND_SWEEP
43345 void *res;
43346 duk_bool_t rc;
43348
43349 DUK_ASSERT(heap != NULL);
43350 DUK_ASSERT_DISABLE(size >= 0);
43351
43352 /*
43353 * Voluntary periodic GC (if enabled)
43354 */
43355
43357
43358 /*
43359 * First attempt
43360 */
43361
43362#ifdef DUK_USE_GC_TORTURE
43363 /* simulate alloc failure on every alloc (except when mark-and-sweep is running) */
43365 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
43366 res = NULL;
43367 DUK_UNREF(res);
43368 goto skip_attempt;
43369 }
43370#endif
43371 res = heap->alloc_func(heap->heap_udata, size);
43372 if (res || size == 0) {
43373 /* for zero size allocations NULL is allowed */
43374 return res;
43375 }
43376#ifdef DUK_USE_GC_TORTURE
43377 skip_attempt:
43378#endif
43379
43380 DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
43381
43382 /*
43383 * Avoid a GC if GC is already running. This can happen at a late
43384 * stage in a GC when we try to e.g. resize the stringtable
43385 * or compact objects.
43386 */
43387
43389 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
43390 return NULL;
43391 }
43392
43393 /*
43394 * Retry with several GC attempts. Initial attempts are made without
43395 * emergency mode; later attempts use emergency mode which minimizes
43396 * memory allocations forcibly.
43397 */
43398
43399 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43400 duk_small_uint_t flags;
43401
43402 flags = 0;
43404 flags |= DUK_MS_FLAG_EMERGENCY;
43405 }
43406
43407 rc = duk_heap_mark_and_sweep(heap, flags);
43408 DUK_UNREF(rc);
43409
43410 res = heap->alloc_func(heap->heap_udata, size);
43411 if (res) {
43412 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
43413 (long) (i + 1), (long) size));
43414 return res;
43415 }
43416 }
43418 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
43419 return NULL;
43420}
43421#else /* DUK_USE_MARK_AND_SWEEP */
43422/*
43423 * Compared to a direct macro expansion this wrapper saves a few
43424 * instructions because no heap dereferencing is required.
43425 */
43427 DUK_ASSERT(heap != NULL);
43428 DUK_ASSERT_DISABLE(size >= 0);
43429
43430 return heap->alloc_func(heap->heap_udata, size);
43431}
43432#endif /* DUK_USE_MARK_AND_SWEEP */
43433
43435 void *res;
43437 DUK_ASSERT(heap != NULL);
43438 DUK_ASSERT_DISABLE(size >= 0);
43439
43440 res = DUK_ALLOC(heap, size);
43441 if (res) {
43442 /* assume memset with zero size is OK */
43443 DUK_MEMZERO(res, size);
43444 }
43445 return res;
43446}
43447
43448/*
43449 * Reallocate memory with garbage collection
43450 */
43451
43452#ifdef DUK_USE_MARK_AND_SWEEP
43453DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
43454 void *res;
43455 duk_bool_t rc;
43457
43458 DUK_ASSERT(heap != NULL);
43459 /* ptr may be NULL */
43460 DUK_ASSERT_DISABLE(newsize >= 0);
43461
43462 /*
43463 * Voluntary periodic GC (if enabled)
43464 */
43465
43467
43468 /*
43469 * First attempt
43470 */
43471
43472#ifdef DUK_USE_GC_TORTURE
43473 /* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
43475 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
43476 res = NULL;
43477 DUK_UNREF(res);
43478 goto skip_attempt;
43479 }
43480#endif
43481 res = heap->realloc_func(heap->heap_udata, ptr, newsize);
43482 if (res || newsize == 0) {
43483 /* for zero size allocations NULL is allowed */
43484 return res;
43485 }
43486#ifdef DUK_USE_GC_TORTURE
43487 skip_attempt:
43488#endif
43489
43490 DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
43491
43492 /*
43493 * Avoid a GC if GC is already running. See duk_heap_mem_alloc().
43494 */
43495
43497 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
43498 return NULL;
43499 }
43500
43501 /*
43502 * Retry with several GC attempts. Initial attempts are made without
43503 * emergency mode; later attempts use emergency mode which minimizes
43504 * memory allocations forcibly.
43505 */
43506
43507 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43508 duk_small_uint_t flags;
43509
43510 flags = 0;
43512 flags |= DUK_MS_FLAG_EMERGENCY;
43513 }
43514
43515 rc = duk_heap_mark_and_sweep(heap, flags);
43516 DUK_UNREF(rc);
43517
43518 res = heap->realloc_func(heap->heap_udata, ptr, newsize);
43519 if (res || newsize == 0) {
43520 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
43521 (long) (i + 1), (long) newsize));
43522 return res;
43523 }
43524 }
43525
43526 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
43527 return NULL;
43528}
43529#else /* DUK_USE_MARK_AND_SWEEP */
43530/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43531DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
43532 DUK_ASSERT(heap != NULL);
43533 /* ptr may be NULL */
43534 DUK_ASSERT_DISABLE(newsize >= 0);
43535
43536 return heap->realloc_func(heap->heap_udata, ptr, newsize);
43537}
43538#endif /* DUK_USE_MARK_AND_SWEEP */
43539
43540/*
43541 * Reallocate memory with garbage collection, using a callback to provide
43542 * the current allocated pointer. This variant is used when a mark-and-sweep
43543 * (e.g. finalizers) might change the original pointer.
43544 */
43545
43546#ifdef DUK_USE_MARK_AND_SWEEP
43548 void *res;
43549 duk_bool_t rc;
43551
43552 DUK_ASSERT(heap != NULL);
43553 DUK_ASSERT_DISABLE(newsize >= 0);
43554
43555 /*
43556 * Voluntary periodic GC (if enabled)
43557 */
43558
43560
43561 /*
43562 * First attempt
43563 */
43564
43565#ifdef DUK_USE_GC_TORTURE
43566 /* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
43568 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
43569 res = NULL;
43570 DUK_UNREF(res);
43571 goto skip_attempt;
43572 }
43573#endif
43574 res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43575 if (res || newsize == 0) {
43576 /* for zero size allocations NULL is allowed */
43577 return res;
43578 }
43579#ifdef DUK_USE_GC_TORTURE
43580 skip_attempt:
43581#endif
43582
43583 DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
43584
43585 /*
43586 * Avoid a GC if GC is already running. See duk_heap_mem_alloc().
43587 */
43588
43590 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
43591 return NULL;
43592 }
43593
43594 /*
43595 * Retry with several GC attempts. Initial attempts are made without
43596 * emergency mode; later attempts use emergency mode which minimizes
43597 * memory allocations forcibly.
43598 */
43599
43600 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43601 duk_small_uint_t flags;
43602
43603#ifdef DUK_USE_ASSERTIONS
43604 void *ptr_pre; /* ptr before mark-and-sweep */
43605 void *ptr_post;
43606#endif
43607
43608#ifdef DUK_USE_ASSERTIONS
43609 ptr_pre = cb(heap, ud);
43610#endif
43611 flags = 0;
43613 flags |= DUK_MS_FLAG_EMERGENCY;
43614 }
43615
43616 rc = duk_heap_mark_and_sweep(heap, flags);
43617 DUK_UNREF(rc);
43618#ifdef DUK_USE_ASSERTIONS
43619 ptr_post = cb(heap, ud);
43620 if (ptr_pre != ptr_post) {
43621 /* useful for debugging */
43622 DUK_DD(DUK_DDPRINT("note: base pointer changed by mark-and-sweep: %p -> %p",
43623 (void *) ptr_pre, (void *) ptr_post));
43624 }
43625#endif
43626
43627 /* Note: key issue here is to re-lookup the base pointer on every attempt.
43628 * The pointer being reallocated may change after every mark-and-sweep.
43629 */
43630
43631 res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43632 if (res || newsize == 0) {
43633 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
43634 (long) (i + 1), (long) newsize));
43635 return res;
43636 }
43638
43639 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
43640 return NULL;
43641}
43642#else /* DUK_USE_MARK_AND_SWEEP */
43643/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43645 return heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43646}
43647#endif /* DUK_USE_MARK_AND_SWEEP */
43648
43649/*
43650 * Free memory
43651 */
43652
43653#ifdef DUK_USE_MARK_AND_SWEEP
43654DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
43655 DUK_ASSERT(heap != NULL);
43656 /* ptr may be NULL */
43657
43658 /* Must behave like a no-op with NULL and any pointer returned from
43659 * malloc/realloc with zero size.
43660 */
43661 heap->free_func(heap->heap_udata, ptr);
43662
43663 /* Count free operations toward triggering a GC but never actually trigger
43664 * a GC from a free. Otherwise code which frees internal structures would
43665 * need to put in NULLs at every turn to ensure the object is always in
43666 * consistent state for a mark-and-sweep.
43667 */
43668#ifdef DUK_USE_VOLUNTARY_GC
43670#endif
43671}
43672#else
43673/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43674DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
43675 DUK_ASSERT(heap != NULL);
43676 /* ptr may be NULL */
43678 /* Note: must behave like a no-op with NULL and any pointer
43679 * returned from malloc/realloc with zero size.
43680 */
43681 heap->free_func(heap->heap_udata, ptr);
43682}
43683#endif
43684/*
43685 * Support functions for duk_heap.
43686 */
43687
43688/* include removed: duk_internal.h */
43689
43690#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
43691/* arbitrary remove only works with double linked heap, and is only required by
43692 * reference counting so far.
43693 */
43696
43697 if (DUK_HEAPHDR_GET_PREV(heap, hdr)) {
43699 } else {
43700 heap->heap_allocated = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43701 }
43702 if (DUK_HEAPHDR_GET_NEXT(heap, hdr)) {
43704 } else {
43705 ;
43706 }
43707
43708 /* The prev/next pointers of the removed duk_heaphdr are left as garbage.
43709 * It's up to the caller to ensure they're written before inserting the
43710 * object back.
43711 */
43712}
43713#endif
43714
43717
43718#ifdef DUK_USE_DOUBLE_LINKED_HEAP
43719 if (heap->heap_allocated) {
43721 DUK_HEAPHDR_SET_PREV(heap, heap->heap_allocated, hdr);
43722 }
43723 DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
43724#endif
43725 DUK_HEAPHDR_SET_NEXT(heap, hdr, heap->heap_allocated);
43726 heap->heap_allocated = hdr;
43727}
43728
43729#ifdef DUK_USE_INTERRUPT_COUNTER
43730DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
43731 duk_hthread *curr_thr;
43732
43733 DUK_ASSERT(heap != NULL);
43734
43735 if (new_thr != NULL) {
43736 curr_thr = heap->curr_thread;
43737 if (curr_thr == NULL) {
43738 /* For initial entry use default value; zero forces an
43739 * interrupt before executing the first insturction.
43740 */
43741 DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
43742 new_thr->interrupt_counter = 0;
43743 new_thr->interrupt_init = 0;
43744 } else {
43745 /* Copy interrupt counter/init value state to new thread (if any).
43746 * It's OK for new_thr to be the same as curr_thr.
43747 */
43748#if defined(DUK_USE_DEBUG)
43749 if (new_thr != curr_thr) {
43750 DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
43751 }
43752#endif
43753 new_thr->interrupt_counter = curr_thr->interrupt_counter;
43754 new_thr->interrupt_init = curr_thr->interrupt_init;
43755 }
43756 } else {
43757 DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
43758 }
43759
43760 heap->curr_thread = new_thr; /* may be NULL */
43761}
43762#endif /* DUK_USE_INTERRUPT_COUNTER */
43763/*
43764 * Reference counting implementation.
43765 */
43766
43767/* include removed: duk_internal.h */
43768
43769#ifdef DUK_USE_REFERENCE_COUNTING
43770
43771#ifndef DUK_USE_DOUBLE_LINKED_HEAP
43772#error internal error, reference counting requires a double linked heap
43773#endif
43774
43775/*
43776 * Misc
43777 */
43778
43780 /* tail insert: don't disturb head in case refzero is running */
43781
43782 if (heap->refzero_list != NULL) {
43783 duk_heaphdr *hdr_prev;
43784
43785 hdr_prev = heap->refzero_list_tail;
43786 DUK_ASSERT(hdr_prev != NULL);
43787 DUK_ASSERT(DUK_HEAPHDR_GET_NEXT(heap, hdr_prev) == NULL);
43788
43789 DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
43790 DUK_HEAPHDR_SET_PREV(heap, hdr, hdr_prev);
43791 DUK_HEAPHDR_SET_NEXT(heap, hdr_prev, hdr);
43792 DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
43793 DUK_ASSERT_HEAPHDR_LINKS(heap, hdr_prev);
43794 heap->refzero_list_tail = hdr;
43795 } else {
43797 DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
43798 DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
43799 DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
43800 heap->refzero_list = hdr;
43801 heap->refzero_list_tail = hdr;
43803}
43804
43805/*
43806 * Heap object refcount finalization.
43807 *
43808 * When an object is about to be freed, all other objects it refers to must
43809 * be decref'd. Refcount finalization does NOT free the object or its inner
43810 * allocations (mark-and-sweep shares these helpers), it just manipulates
43811 * the refcounts.
43812 *
43813 * Note that any of the decref's may cause a refcount to drop to zero, BUT
43814 * it will not be processed inline; instead, because refzero is already
43815 * running, the objects will just be queued to refzero list and processed
43816 * later. This eliminates C recursion.
43817 */
43818
43821
43822 DUK_ASSERT(h);
43824
43825 /* XXX: better to get base and walk forwards? */
43826
43827 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
43828 duk_hstring *key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
43829 if (!key) {
43830 continue;
43831 }
43832 duk_heaphdr_decref(thr, (duk_heaphdr *) key);
43833 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)) {
43836 } else {
43838 }
43839 }
43840
43841 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
43843 }
43844
43845 /* hash part is a 'weak reference' and does not contribute */
43846
43848
43851 duk_tval *tv, *tv_end;
43852 duk_hobject **funcs, **funcs_end;
43853
43854 if (DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f) != NULL) {
43857 while (tv < tv_end) {
43858 duk_tval_decref(thr, tv);
43859 tv++;
43860 }
43861
43863 funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
43864 while (funcs < funcs_end) {
43866 funcs++;
43867 }
43868 } else {
43869 /* May happen in some out-of-memory corner cases. */
43870 DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping decref"));
43871 }
43872
43874 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
43876 DUK_UNREF(f);
43877 /* nothing to finalize */
43878 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
43880 if (b->buf) {
43881 duk_heaphdr_decref(thr, (duk_heaphdr *) b->buf);
43882 }
43883 } else if (DUK_HOBJECT_IS_THREAD(h)) {
43884 duk_hthread *t = (duk_hthread *) h;
43885 duk_tval *tv;
43886
43887 tv = t->valstack;
43888 while (tv < t->valstack_top) {
43889 duk_tval_decref(thr, tv);
43890 tv++;
43891 }
43892
43893 for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
43894 duk_activation *act = t->callstack + i;
43898#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
43899 duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->prev_caller);
43900#endif
43901 }
43902
43903#if 0 /* nothing now */
43904 for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
43905 duk_catcher *cat = t->catchstack + i;
43906 }
43907#endif
43908
43909 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
43911 }
43912
43914 }
43915}
43916
43918 DUK_ASSERT(hdr);
43919
43920 switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
43921 case DUK_HTYPE_OBJECT:
43923 break;
43924 case DUK_HTYPE_BUFFER:
43925 /* nothing to finalize */
43926 break;
43927 case DUK_HTYPE_STRING:
43928 /* cannot happen: strings are not put into refzero list (they don't even have the next/prev pointers) */
43929 default:
43931 }
43932}
43933
43934#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
43935DUK_LOCAL duk_ret_t duk__refcount_fake_finalizer(duk_context *ctx) {
43936 DUK_UNREF(ctx);
43937 DUK_D(DUK_DPRINT("fake refcount torture finalizer executed"));
43938#if 0
43939 DUK_DD(DUK_DDPRINT("fake torture finalizer for: %!T", duk_get_tval(ctx, 0)));
43940#endif
43941 /* Require a lot of stack to force a value stack grow/shrink. */
43942 duk_require_stack(ctx, 100000);
43943
43944 /* XXX: do something to force a callstack grow/shrink, perhaps
43945 * just a manual forced resize?
43946 */
43947 return 0;
43948}
43949
43950DUK_LOCAL void duk__refcount_run_torture_finalizer(duk_hthread *thr, duk_hobject *obj) {
43951 duk_context *ctx;
43952 duk_int_t rc;
43953
43954 DUK_ASSERT(thr != NULL);
43955 DUK_ASSERT(obj != NULL);
43956 ctx = (duk_context *) thr;
43957
43958 /* Avoid fake finalization for the duk__refcount_fake_finalizer function
43959 * itself, otherwise we're in infinite recursion.
43960 */
43962 if (((duk_hnativefunction *) obj)->func == duk__refcount_fake_finalizer) {
43963 DUK_DD(DUK_DDPRINT("avoid fake torture finalizer for duk__refcount_fake_finalizer itself"));
43964 return;
43965 }
43966 }
43967 /* Avoid fake finalization when callstack limit has been reached.
43968 * Otherwise a callstack limit error will be created, then refzero'ed,
43969 * and we're in an infinite loop.
43970 */
43972 thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
43973 DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake torture finalizer"));
43974 return;
43975 }
43976
43977 /* Run fake finalizer. Avoid creating new refzero queue entries
43978 * so that we are not forced into a forever loop.
43979 */
43980 duk_push_c_function(ctx, duk__refcount_fake_finalizer, 1 /*nargs*/);
43981 duk_push_hobject(ctx, obj);
43982 rc = duk_pcall(ctx, 1);
43983 DUK_UNREF(rc); /* ignored */
43984 duk_pop(ctx);
43985}
43986#endif /* DUK_USE_REFZERO_FINALIZER_TORTURE */
43987
43988/*
43989 * Refcount memory freeing loop.
43990 *
43991 * Frees objects in the refzero_pending list until the list becomes
43992 * empty. When an object is freed, its references get decref'd and
43993 * may cause further objects to be queued for freeing.
43994 *
43995 * This could be expanded to allow incremental freeing: just bail out
43996 * early and resume at a future alloc/decref/refzero.
43997 */
43998
44000 duk_heaphdr *h1, *h2;
44001 duk_heap *heap;
44002 duk_int_t count = 0;
44003
44004 DUK_ASSERT(thr != NULL);
44005 DUK_ASSERT(thr->heap != NULL);
44006 heap = thr->heap;
44007 DUK_ASSERT(heap != NULL);
44008
44009 /*
44010 * Detect recursive invocation
44011 */
44012
44014 DUK_DDD(DUK_DDDPRINT("refzero free running, skip run"));
44015 return;
44016 }
44017
44018 /*
44019 * Churn refzero_list until empty
44020 */
44021
44023 while (heap->refzero_list) {
44024 duk_hobject *obj;
44025 duk_bool_t rescued = 0;
44026
44027 /*
44028 * Pick an object from the head (don't remove yet).
44029 */
44030
44031 h1 = heap->refzero_list;
44032 obj = (duk_hobject *) h1;
44033 DUK_DD(DUK_DDPRINT("refzero processing %p: %!O", (void *) h1, (duk_heaphdr *) h1));
44034 DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, h1) == NULL);
44035 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h1) == DUK_HTYPE_OBJECT); /* currently, always the case */
44036
44037#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
44038 /* Torture option to shake out finalizer side effect issues:
44039 * make a bogus function call for every finalizable object,
44040 * essentially simulating the case where everything has a
44041 * finalizer.
44042 */
44043 DUK_DD(DUK_DDPRINT("refzero torture enabled, fake finalizer"));
44045 DUK_HEAPHDR_PREINC_REFCOUNT(h1); /* bump refcount to prevent refzero during finalizer processing */
44046 duk__refcount_run_torture_finalizer(thr, obj); /* must never longjmp */
44047 DUK_HEAPHDR_PREDEC_REFCOUNT(h1); /* remove artificial bump */
44048 DUK_ASSERT_DISABLE(h1->h_refcount >= 0); /* refcount is unsigned, so always true */
44049#endif
44050
44051 /*
44052 * Finalizer check.
44053 *
44054 * Note: running a finalizer may have arbitrary side effects, e.g.
44055 * queue more objects on refzero_list (tail), or even trigger a
44056 * mark-and-sweep.
44057 *
44058 * Note: quick reject check should match vast majority of
44059 * objects and must be safe (not throw any errors, ever).
44060 */
44061
44062 /* An object may have FINALIZED here if it was finalized by mark-and-sweep
44063 * on a previous run and refcount then decreased to zero. We won't run the
44064 * finalizer again here.
44065 */
44066
44067 /* A finalizer is looked up from the object and up its prototype chain
44068 * (which allows inherited finalizers).
44069 */
44071 DUK_DDD(DUK_DDDPRINT("object has a finalizer, run it"));
44072
44074 DUK_HEAPHDR_PREINC_REFCOUNT(h1); /* bump refcount to prevent refzero during finalizer processing */
44075
44076 duk_hobject_run_finalizer(thr, obj); /* must never longjmp */
44077 DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1)); /* duk_hobject_run_finalizer() sets */
44078
44079 DUK_HEAPHDR_PREDEC_REFCOUNT(h1); /* remove artificial bump */
44080 DUK_ASSERT_DISABLE(h1->h_refcount >= 0); /* refcount is unsigned, so always true */
44081
44082 if (DUK_HEAPHDR_GET_REFCOUNT(h1) != 0) {
44083 DUK_DDD(DUK_DDDPRINT("-> object refcount after finalization non-zero, object will be rescued"));
44084 rescued = 1;
44085 } else {
44086 DUK_DDD(DUK_DDDPRINT("-> object refcount still zero after finalization, object will be freed"));
44087 }
44088 }
44089
44090 /* Refzero head is still the same. This is the case even if finalizer
44091 * inserted more refzero objects; they are inserted to the tail.
44092 */
44093 DUK_ASSERT(h1 == heap->refzero_list);
44094
44095 /*
44096 * Remove the object from the refzero list. This cannot be done
44097 * before a possible finalizer has been executed; the finalizer
44098 * may trigger a mark-and-sweep, and mark-and-sweep must be able
44099 * to traverse a complete refzero_list.
44100 */
44101
44102 h2 = DUK_HEAPHDR_GET_NEXT(heap, h1);
44103 if (h2) {
44104 DUK_HEAPHDR_SET_PREV(heap, h2, NULL); /* not strictly necessary */
44105 heap->refzero_list = h2;
44106 } else {
44107 heap->refzero_list = NULL;
44108 heap->refzero_list_tail = NULL;
44109 }
44110
44111 /*
44112 * Rescue or free.
44113 */
44114
44115 if (rescued) {
44116 /* yes -> move back to heap allocated */
44117 DUK_DD(DUK_DDPRINT("object rescued during refcount finalization: %p", (void *) h1));
44121 h2 = heap->heap_allocated;
44122 DUK_HEAPHDR_SET_PREV(heap, h1, NULL);
44123 if (h2) {
44124 DUK_HEAPHDR_SET_PREV(heap, h2, h1);
44125 }
44126 DUK_HEAPHDR_SET_NEXT(heap, h1, h2);
44127 DUK_ASSERT_HEAPHDR_LINKS(heap, h1);
44128 DUK_ASSERT_HEAPHDR_LINKS(heap, h2);
44129 heap->heap_allocated = h1;
44130 } else {
44131 /* no -> decref members, then free */
44133 duk_heap_free_heaphdr_raw(heap, h1);
44134 }
44135
44136 count++;
44137 }
44139
44140 DUK_DDD(DUK_DDDPRINT("refzero processed %ld objects", (long) count));
44141
44142 /*
44143 * Once the whole refzero cascade has been freed, check for
44144 * a voluntary mark-and-sweep.
44145 */
44146
44147#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
44148 /* 'count' is more or less comparable to normal trigger counter update
44149 * which happens in memory block (re)allocation.
44150 */
44151 heap->mark_and_sweep_trigger_counter -= count;
44152 if (heap->mark_and_sweep_trigger_counter <= 0) {
44153 duk_bool_t rc;
44154 duk_small_uint_t flags = 0; /* not emergency */
44155 DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
44156 rc = duk_heap_mark_and_sweep(heap, flags);
44157 DUK_UNREF(rc);
44158 DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
44159 }
44160#endif /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
44161}
44162
44163/*
44164 * Incref and decref functions.
44165 *
44166 * Decref may trigger immediate refzero handling, which may free and finalize
44167 * an arbitrary number of objects.
44168 *
44169 */
44170
44172 duk_heap *heap;
44173
44174 DUK_ASSERT(thr != NULL);
44175 DUK_ASSERT(h != NULL);
44176
44177 heap = thr->heap;
44178 DUK_DDD(DUK_DDDPRINT("refzero %p: %!O", (void *) h, (duk_heaphdr *) h));
44179
44180 /*
44181 * Refzero handling is skipped entirely if (1) mark-and-sweep is
44182 * running or (2) execution is paused in the debugger. The objects
44183 * are left in the heap, and will be freed by mark-and-sweep or
44184 * eventual heap destruction.
44185 *
44186 * This is necessary during mark-and-sweep because refcounts are also
44187 * updated during the sweep phase (otherwise objects referenced by a
44188 * swept object would have incorrect refcounts) which then calls here.
44189 * This could be avoided by using separate decref macros in
44190 * mark-and-sweep; however, mark-and-sweep also calls finalizers which
44191 * would use the ordinary decref macros anyway and still call this
44192 * function.
44193 *
44194 * This check must be enabled also when mark-and-sweep support has been
44195 * disabled: the flag is also used in heap destruction when running
44196 * finalizers for remaining objects, and the flag prevents objects from
44197 * being moved around in heap linked lists.
44198 */
44199
44200 /* XXX: ideally this would be just one flag (maybe a derived one) so
44201 * that a single bit test is sufficient to check the condition.
44202 */
44203#if defined(DUK_USE_DEBUGGER_SUPPORT)
44204 if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) || DUK_HEAP_IS_PAUSED(heap))) {
44205#else
44207#endif
44208 DUK_DDD(DUK_DDDPRINT("refzero handling suppressed when mark-and-sweep running, object: %p", (void *) h));
44209 return;
44210 }
44211
44213 case DUK_HTYPE_STRING:
44214 /*
44215 * Strings have no internal references but do have "weak"
44216 * references in the string cache. Also note that strings
44217 * are not on the heap_allocated list like other heap
44218 * elements.
44219 */
44220
44224 break;
44225
44226 case DUK_HTYPE_OBJECT:
44227 /*
44228 * Objects have internal references. Must finalize through
44229 * the "refzero" work list.
44230 */
44231
44233 duk__queue_refzero(heap, h);
44235 break;
44236
44237 case DUK_HTYPE_BUFFER:
44238 /*
44239 * Buffers have no internal references. However, a dynamic
44240 * buffer has a separate allocation for the buffer. This is
44241 * freed by duk_heap_free_heaphdr_raw().
44242 */
44243
44246 break;
44247
44248 default:
44249 DUK_D(DUK_DPRINT("invalid heap type in decref: %ld", (long) DUK_HEAPHDR_GET_TYPE(h)));
44251 }
44252}
44253
44254#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
44255DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
44256 DUK_ASSERT(tv != NULL);
44257
44260 DUK_ASSERT(h != NULL);
44264 }
44265}
44266#endif
44267
44268#if 0 /* unused */
44269DUK_INTERNAL void duk_tval_incref_allownull(duk_tval *tv) {
44270 if (tv == NULL) {
44271 return;
44272 }
44275 DUK_ASSERT(h != NULL);
44279 }
44280}
44281#endif
44282
44284 DUK_ASSERT(thr != NULL);
44285 DUK_ASSERT(tv != NULL);
44286
44289 DUK_ASSERT(h != NULL);
44291 duk_heaphdr_decref(thr, h);
44292 }
44293}
44294
44295#if 0 /* unused */
44296DUK_INTERNAL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv) {
44297 DUK_ASSERT(thr != NULL);
44298
44299 if (tv == NULL) {
44300 return;
44301 }
44304 DUK_ASSERT(h != NULL);
44306 duk_heaphdr_decref(thr, h);
44307 }
44308}
44309#endif
44310
44311#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
44312DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
44313 DUK_ASSERT(h != NULL);
44318}
44319#endif
44320
44321#if 0 /* unused */
44322DUK_INTERNAL void duk_heaphdr_incref_allownull(duk_heaphdr *h) {
44323 if (h == NULL) {
44324 return;
44325 }
44328
44330}
44331#endif
44332
44335 DUK_ASSERT(thr->heap != NULL);
44336 DUK_ASSERT(h != NULL);
44339
44340#if defined(DUK_USE_ROM_OBJECTS)
44341 if (DUK_HEAPHDR_HAS_READONLY(h)) {
44342 return;
44343 }
44344#endif
44345 if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
44346 return;
44347 }
44348 duk_heaphdr_refzero(thr, h);
44349}
44350
44352 DUK_ASSERT(thr != NULL);
44353 DUK_ASSERT(thr->heap != NULL);
44354
44355 if (h == NULL) {
44356 return;
44357 }
44359
44360#if defined(DUK_USE_ROM_OBJECTS)
44361 if (DUK_HEAPHDR_HAS_READONLY(h)) {
44362 return;
44363 }
44364#endif
44366 if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
44367 return;
44368 }
44369 duk_heaphdr_refzero(thr, h);
44370}
44371
44372#else
44373
44374/* no refcounting */
44375
44376#endif /* DUK_USE_REFERENCE_COUNTING */
44377/*
44378 * String cache.
44380 * Provides a cache to optimize indexed string lookups. The cache keeps
44381 * track of (byte offset, char offset) states for a fixed number of strings.
44382 * Otherwise we'd need to scan from either end of the string, as we store
44383 * strings in (extended) UTF-8.
44384 */
44385
44386/* include removed: duk_internal.h */
44387
44388/*
44389 * Delete references to given hstring from the heap string cache.
44390 *
44391 * String cache references are 'weak': they are not counted towards
44392 * reference counts, nor serve as roots for mark-and-sweep. When an
44393 * object is about to be freed, such references need to be removed.
44394 */
44395
44398 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44399 duk_strcache *c = heap->strcache + i;
44400 if (c->h == h) {
44401 DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
44402 (void *) h, (void *) heap));
44403 c->h = NULL;
44405 /* XXX: the string shouldn't appear twice, but we now loop to the
44406 * end anyway; if fixed, add a looping assertion to ensure there
44407 * is no duplicate.
44408 */
44409 }
44410 }
44411}
44412
44413/*
44414 * String scanning helpers
44415 *
44416 * All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
44417 * considered to contribute a character. This must match how string
44418 * character length is computed.
44419 */
44421DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
44422 while (n > 0) {
44423 for (;;) {
44424 p++;
44425 if (p >= q) {
44426 return NULL;
44427 }
44428 if ((*p & 0xc0) != 0x80) {
44429 break;
44430 }
44431 }
44432 n--;
44433 }
44434 return p;
44435}
44436
44437DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
44438 while (n > 0) {
44439 for (;;) {
44440 p--;
44441 if (p < q) {
44442 return NULL;
44443 }
44444 if ((*p & 0xc0) != 0x80) {
44445 break;
44446 }
44447 }
44448 n--;
44449 }
44450 return p;
44451}
44452
44453/*
44454 * Convert char offset to byte offset
44455 *
44456 * Avoid using the string cache if possible: for ASCII strings byte and
44457 * char offsets are equal and for short strings direct scanning may be
44458 * better than using the string cache (which may evict a more important
44459 * entry).
44460 *
44461 * Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
44462 * Better typing might be to use duk_size_t.
44463 */
44464
44466 duk_heap *heap;
44467 duk_strcache *sce;
44468 duk_uint_fast32_t byte_offset;
44470 duk_bool_t use_cache;
44471 duk_uint_fast32_t dist_start, dist_end, dist_sce;
44472 const duk_uint8_t *p_start;
44473 const duk_uint8_t *p_end;
44474 const duk_uint8_t *p_found;
44475
44476 if (char_offset > DUK_HSTRING_GET_CHARLEN(h)) {
44477 goto error;
44478 }
44479
44480 /*
44481 * For ASCII strings, the answer is simple.
44482 */
44483
44484 if (DUK_HSTRING_IS_ASCII(h)) {
44485 /* clen == blen -> pure ascii */
44486 return char_offset;
44487 }
44488
44489 /*
44490 * For non-ASCII strings, we need to scan forwards or backwards
44491 * from some starting point. The starting point may be the start
44492 * or end of the string, or some cached midpoint in the string
44493 * cache.
44494 *
44495 * For "short" strings we simply scan without checking or updating
44496 * the cache. For longer strings we check and update the cache as
44497 * necessary, inserting a new cache entry if none exists.
44498 */
44499
44500 DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
44501 (void *) h, (long) char_offset,
44502 (long) DUK_HSTRING_GET_CHARLEN(h),
44503 (long) DUK_HSTRING_GET_BYTELEN(h)));
44504
44505 heap = thr->heap;
44506 sce = NULL;
44508
44509 if (use_cache) {
44510#ifdef DUK_USE_DDDPRINT
44511 DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
44512 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44513 duk_strcache *c = heap->strcache + i;
44514 DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
44515 (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
44516 }
44517#endif
44518
44519 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44520 duk_strcache *c = heap->strcache + i;
44521
44522 if (c->h == h) {
44523 sce = c;
44524 break;
44525 }
44526 }
44527 }
44528
44529 /*
44530 * Scan from shortest distance:
44531 * - start of string
44532 * - end of string
44533 * - cache entry (if exists)
44534 */
44535
44536 DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
44537 dist_start = char_offset;
44538 dist_end = DUK_HSTRING_GET_CHARLEN(h) - char_offset;
44539 dist_sce = 0; DUK_UNREF(dist_sce); /* initialize for debug prints, needed if sce==NULL */
44540
44541 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
44542 p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
44543 p_found = NULL;
44544
44545 if (sce) {
44546 if (char_offset >= sce->cidx) {
44547 dist_sce = char_offset - sce->cidx;
44548 if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
44549 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44550 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44551 "scan forwards from sce",
44552 (long) use_cache, (void *) (sce ? sce->h : NULL),
44553 (sce ? (long) sce->cidx : (long) -1),
44554 (sce ? (long) sce->bidx : (long) -1),
44555 (long) dist_start, (long) dist_end, (long) dist_sce));
44556
44557 p_found = duk__scan_forwards(p_start + sce->bidx,
44558 p_end,
44559 dist_sce);
44560 goto scan_done;
44561 }
44562 } else {
44563 dist_sce = sce->cidx - char_offset;
44564 if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
44565 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44566 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44567 "scan backwards from sce",
44568 (long) use_cache, (void *) (sce ? sce->h : NULL),
44569 (sce ? (long) sce->cidx : (long) -1),
44570 (sce ? (long) sce->bidx : (long) -1),
44571 (long) dist_start, (long) dist_end, (long) dist_sce));
44572
44573 p_found = duk__scan_backwards(p_start + sce->bidx,
44574 p_start,
44575 dist_sce);
44576 goto scan_done;
44577 }
44578 }
44579 }
44580
44581 /* no sce, or sce scan not best */
44582
44583 if (dist_start <= dist_end) {
44584 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44585 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44586 "scan forwards from string start",
44587 (long) use_cache, (void *) (sce ? sce->h : NULL),
44588 (sce ? (long) sce->cidx : (long) -1),
44589 (sce ? (long) sce->bidx : (long) -1),
44590 (long) dist_start, (long) dist_end, (long) dist_sce));
44591
44592 p_found = duk__scan_forwards(p_start,
44593 p_end,
44594 dist_start);
44595 } else {
44596 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44597 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44598 "scan backwards from string end",
44599 (long) use_cache, (void *) (sce ? sce->h : NULL),
44600 (sce ? (long) sce->cidx : (long) -1),
44601 (sce ? (long) sce->bidx : (long) -1),
44602 (long) dist_start, (long) dist_end, (long) dist_sce));
44603
44604 p_found = duk__scan_backwards(p_end,
44605 p_start,
44606 dist_end);
44607 }
44608
44609 scan_done:
44610
44611 if (!p_found) {
44612 /* Scan error: this shouldn't normally happen; it could happen if
44613 * string is not valid UTF-8 data, and clen/blen are not consistent
44614 * with the scanning algorithm.
44615 */
44616 goto error;
44617 }
44618
44619 DUK_ASSERT(p_found >= p_start);
44620 DUK_ASSERT(p_found <= p_end); /* may be equal */
44621 byte_offset = (duk_uint32_t) (p_found - p_start);
44622
44623 DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
44624 (void *) h, (long) char_offset, (long) byte_offset));
44625
44626 /*
44627 * Update cache entry (allocating if necessary), and move the
44628 * cache entry to the first place (in an "LRU" policy).
44629 */
44630
44631 if (use_cache) {
44632 /* update entry, allocating if necessary */
44633 if (!sce) {
44634 sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1; /* take last entry */
44635 sce->h = h;
44636 }
44637 DUK_ASSERT(sce != NULL);
44638 sce->bidx = (duk_uint32_t) (p_found - p_start);
44639 sce->cidx = (duk_uint32_t) char_offset;
44640
44641 /* LRU: move our entry to first */
44642 if (sce > &heap->strcache[0]) {
44643 /*
44644 * A C
44645 * B A
44646 * C <- sce ==> B
44647 * D D
44648 */
44649 duk_strcache tmp;
44650
44651 tmp = *sce;
44652 DUK_MEMMOVE((void *) (&heap->strcache[1]),
44653 (const void *) (&heap->strcache[0]),
44654 (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
44655 heap->strcache[0] = tmp;
44656
44657 /* 'sce' points to the wrong entry here, but is no longer used */
44658 }
44659#ifdef DUK_USE_DDDPRINT
44660 DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
44661 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44662 duk_strcache *c = heap->strcache + i;
44663 DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
44664 (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
44666#endif
44668
44669 return byte_offset;
44670
44673 return 0;
44674}
44675/*
44676 * Heap stringtable handling, string interning.
44677 */
44678
44679/* include removed: duk_internal.h */
44680
44681#if defined(DUK_USE_STRTAB_PROBE)
44682#define DUK__HASH_INITIAL(hash,h_size) DUK_STRTAB_HASH_INITIAL((hash),(h_size))
44683#define DUK__HASH_PROBE_STEP(hash) DUK_STRTAB_HASH_PROBE_STEP((hash))
44684#define DUK__DELETED_MARKER(heap) DUK_STRTAB_DELETED_MARKER((heap))
44685#endif
44686
44687#if defined(DUK_USE_MARK_AND_SWEEP)
44688#define DUK__PREVENT_MS_SIDE_EFFECTS(heap) do { \
44689 (heap)->mark_and_sweep_base_flags |= \
44690 DUK_MS_FLAG_NO_STRINGTABLE_RESIZE | /* avoid recursive string table call */ \
44691 DUK_MS_FLAG_NO_FINALIZERS | /* avoid pressure to add/remove strings, invalidation of call data argument, etc. */ \
44692 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid array abandoning which interns strings */ \
44693 } while (0)
44694#endif
44695
44696/*
44697 * Create a hstring and insert into the heap. The created object
44698 * is directly garbage collectable with reference count zero.
44699 *
44700 * The caller must place the interned string into the stringtable
44701 * immediately (without chance of a longjmp); otherwise the string
44702 * is lost.
44703 */
44704
44707 const duk_uint8_t *str,
44708 duk_uint32_t blen,
44709 duk_uint32_t strhash,
44710 const duk_uint8_t *extdata) {
44711 duk_hstring *res = NULL;
44712 duk_uint8_t *data;
44713 duk_size_t alloc_size;
44715 duk_uint32_t clen;
44716
44717#if defined(DUK_USE_STRLEN16)
44718 /* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
44719 if (blen > 0xffffUL) {
44720 DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
44721 return NULL;
44722 }
44723#endif
44724
44725 if (extdata) {
44726 alloc_size = (duk_size_t) sizeof(duk_hstring_external);
44727 res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
44728 if (!res) {
44729 goto alloc_error;
44730 }
44731 DUK_MEMZERO(res, sizeof(duk_hstring_external));
44732#if defined(DUK_USE_EXPLICIT_NULL_INIT)
44734#endif
44736
44737 ((duk_hstring_external *) res)->extdata = extdata;
44738 } else {
44739 /* NUL terminate for convenient C access */
44740 alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
44741 res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
44742 if (!res) {
44743 goto alloc_error;
44744 }
44745 DUK_MEMZERO(res, sizeof(duk_hstring));
44746#if defined(DUK_USE_EXPLICIT_NULL_INIT)
44748#endif
44750
44751 data = (duk_uint8_t *) (res + 1);
44752 DUK_MEMCPY(data, str, blen);
44753 data[blen] = (duk_uint8_t) 0;
44754 }
44755
44757 if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) {
44759 }
44760
44761 /* All strings beginning with 0xff are treated as "internal",
44762 * even strings interned by the user. This allows user code to
44763 * create internal properties too, and makes behavior consistent
44764 * in case user code happens to use a string also used by Duktape
44765 * (such as string has already been interned and has the 'internal'
44766 * flag set).
44767 */
44769 if (blen > 0 && str[0] == (duk_uint8_t) 0xff) {
44771 }
44772
44773 DUK_HSTRING_SET_HASH(res, strhash);
44774 DUK_HSTRING_SET_BYTELEN(res, blen);
44775
44776 clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen);
44777 DUK_ASSERT(clen <= blen);
44778#if defined(DUK_USE_HSTRING_CLEN)
44779 DUK_HSTRING_SET_CHARLEN(res, clen);
44780#endif
44781
44782 /* Using an explicit 'ASCII' flag has larger footprint (one call site
44783 * only) but is quite useful for the case when there's no explicit
44784 * 'clen' in duk_hstring.
44785 */
44787 if (clen == blen) {
44789 }
44790
44791 DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld",
44792 (unsigned long) DUK_HSTRING_GET_HASH(res),
44793 (long) DUK_HSTRING_GET_BYTELEN(res),
44794 (long) DUK_HSTRING_GET_CHARLEN(res),
44795 (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
44796 (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
44797
44798 return res;
44799
44800 alloc_error:
44801 DUK_FREE(heap, res);
44802 return NULL;
44803}
44804
44805/*
44806 * String table algorithm: fixed size string table with array chaining
44807 *
44808 * The top level string table has a fixed size, with each slot holding
44809 * either NULL, string pointer, or pointer to a separately allocated
44810 * string pointer list.
44811 *
44812 * This is good for low memory environments using a pool allocator: the
44813 * top level allocation has a fixed size and the pointer lists have quite
44814 * small allocation size, which further matches the typical pool sizes
44815 * needed by objects, strings, property tables, etc.
44816 */
44817
44818#if defined(DUK_USE_STRTAB_CHAIN)
44819
44820#if defined(DUK_USE_HEAPPTR16)
44821DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
44822 duk_small_uint_t slotidx;
44824 duk_uint16_t *lst;
44825 duk_uint16_t *new_lst;
44826 duk_size_t i, n;
44827 duk_uint16_t null16 = heap->heapptr_null16;
44828 duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
44829
44830 DUK_ASSERT(heap != NULL);
44831 DUK_ASSERT(h != NULL);
44832
44835
44836 e = heap->strtable + slotidx;
44837 if (e->listlen == 0) {
44838 if (e->u.str16 == null16) {
44839 e->u.str16 = h16;
44840 } else {
44841 /* Now two entries in the same slot, alloc list */
44842 lst = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * 2);
44843 if (lst == NULL) {
44844 return 1; /* fail */
44845 }
44846 lst[0] = e->u.str16;
44847 lst[1] = h16;
44848 e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) lst);
44849 e->listlen = 2;
44850 }
44851 } else {
44852 DUK_ASSERT(e->u.strlist16 != null16);
44853 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
44854 DUK_ASSERT(lst != NULL);
44855 for (i = 0, n = e->listlen; i < n; i++) {
44856 if (lst[i] == null16) {
44857 lst[i] = h16;
44858 return 0;
44859 }
44860 }
44861
44862 if (e->listlen + 1 == 0) {
44863 /* Overflow, relevant mainly when listlen is 16 bits. */
44864 return 1; /* fail */
44865 }
44866
44867 new_lst = (duk_uint16_t *) DUK_REALLOC(heap, lst, sizeof(duk_uint16_t) * (e->listlen + 1));
44868 if (new_lst == NULL) {
44869 return 1; /* fail */
44870 }
44871 new_lst[e->listlen++] = h16;
44872 e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) new_lst);
44873 }
44874 return 0;
44875}
44876#else /* DUK_USE_HEAPPTR16 */
44877DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
44878 duk_small_uint_t slotidx;
44880 duk_hstring **lst;
44881 duk_hstring **new_lst;
44882 duk_size_t i, n;
44883
44884 DUK_ASSERT(heap != NULL);
44885 DUK_ASSERT(h != NULL);
44886
44889
44890 e = heap->strtable + slotidx;
44891 if (e->listlen == 0) {
44892 if (e->u.str == NULL) {
44893 e->u.str = h;
44894 } else {
44895 /* Now two entries in the same slot, alloc list */
44896 lst = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * 2);
44897 if (lst == NULL) {
44898 return 1; /* fail */
44899 }
44900 lst[0] = e->u.str;
44901 lst[1] = h;
44902 e->u.strlist = lst;
44903 e->listlen = 2;
44904 }
44905 } else {
44906 DUK_ASSERT(e->u.strlist != NULL);
44907 lst = e->u.strlist;
44908 for (i = 0, n = e->listlen; i < n; i++) {
44909 if (lst[i] == NULL) {
44910 lst[i] = h;
44911 return 0;
44912 }
44913 }
44914
44915 if (e->listlen + 1 == 0) {
44916 /* Overflow, relevant mainly when listlen is 16 bits. */
44917 return 1; /* fail */
44918 }
44919
44920 new_lst = (duk_hstring **) DUK_REALLOC(heap, e->u.strlist, sizeof(duk_hstring *) * (e->listlen + 1));
44921 if (new_lst == NULL) {
44922 return 1; /* fail */
44923 }
44924 new_lst[e->listlen++] = h;
44925 e->u.strlist = new_lst;
44926 }
44927 return 0;
44928}
44929#endif /* DUK_USE_HEAPPTR16 */
44930
44931#if defined(DUK_USE_HEAPPTR16)
44932DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
44933 duk_small_uint_t slotidx;
44935 duk_uint16_t *lst;
44936 duk_size_t i, n;
44937 duk_uint16_t null16 = heap->heapptr_null16;
44938
44939 DUK_ASSERT(heap != NULL);
44940
44941 slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
44943
44944 e = heap->strtable + slotidx;
44945 if (e->listlen == 0) {
44946 if (e->u.str16 != null16) {
44947 duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
44948 DUK_ASSERT(h != NULL);
44949 if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
44950 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
44951 return h;
44952 }
44953 }
44954 } else {
44955 DUK_ASSERT(e->u.strlist16 != null16);
44956 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
44957 DUK_ASSERT(lst != NULL);
44958 for (i = 0, n = e->listlen; i < n; i++) {
44959 if (lst[i] != null16) {
44960 duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[i]);
44961 DUK_ASSERT(h != NULL);
44962 if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
44963 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
44964 return h;
44965 }
44966 }
44967 }
44968 }
44969
44970 return NULL;
44971}
44972#else /* DUK_USE_HEAPPTR16 */
44973DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
44974 duk_small_uint_t slotidx;
44976 duk_hstring **lst;
44977 duk_size_t i, n;
44978
44979 DUK_ASSERT(heap != NULL);
44980
44981 slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
44983
44984 e = heap->strtable + slotidx;
44985 if (e->listlen == 0) {
44986 if (e->u.str != NULL &&
44987 DUK_HSTRING_GET_BYTELEN(e->u.str) == blen &&
44988 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e->u.str), (size_t) blen) == 0) {
44989 return e->u.str;
44990 }
44991 } else {
44992 DUK_ASSERT(e->u.strlist != NULL);
44993 lst = e->u.strlist;
44994 for (i = 0, n = e->listlen; i < n; i++) {
44995 if (lst[i] != NULL &&
44996 DUK_HSTRING_GET_BYTELEN(lst[i]) == blen &&
44997 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(lst[i]), (size_t) blen) == 0) {
44998 return lst[i];
44999 }
45000 }
45001 }
45002
45003 return NULL;
45004}
45005#endif /* DUK_USE_HEAPPTR16 */
45006
45007#if defined(DUK_USE_HEAPPTR16)
45008DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
45009 duk_small_uint_t slotidx;
45011 duk_uint16_t *lst;
45012 duk_size_t i, n;
45013 duk_uint16_t h16;
45014 duk_uint16_t null16 = heap->heapptr_null16;
45015
45016 DUK_ASSERT(heap != NULL);
45017 DUK_ASSERT(h != NULL);
45018
45021
45022 DUK_ASSERT(h != NULL);
45023 h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45024
45025 e = heap->strtable + slotidx;
45026 if (e->listlen == 0) {
45027 if (e->u.str16 == h16) {
45028 e->u.str16 = null16;
45029 return;
45030 }
45031 } else {
45032 DUK_ASSERT(e->u.strlist16 != null16);
45033 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45034 DUK_ASSERT(lst != NULL);
45035 for (i = 0, n = e->listlen; i < n; i++) {
45036 if (lst[i] == h16) {
45037 lst[i] = null16;
45038 return;
45039 }
45040 }
45041 }
45042
45043 DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
45045 return;
45046}
45047#else /* DUK_USE_HEAPPTR16 */
45048DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
45049 duk_small_uint_t slotidx;
45051 duk_hstring **lst;
45052 duk_size_t i, n;
45053
45054 DUK_ASSERT(heap != NULL);
45055 DUK_ASSERT(h != NULL);
45056
45059
45060 e = heap->strtable + slotidx;
45061 if (e->listlen == 0) {
45062 DUK_ASSERT(h != NULL);
45063 if (e->u.str == h) {
45064 e->u.str = NULL;
45065 return;
45066 }
45067 } else {
45068 DUK_ASSERT(e->u.strlist != NULL);
45069 lst = e->u.strlist;
45070 for (i = 0, n = e->listlen; i < n; i++) {
45071 DUK_ASSERT(h != NULL);
45072 if (lst[i] == h) {
45073 lst[i] = NULL;
45074 return;
45075 }
45076 }
45077 }
45078
45079 DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
45081 return;
45082}
45083#endif /* DUK_USE_HEAPPTR16 */
45084
45085#if defined(DUK_USE_DEBUG)
45086DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
45089 duk_size_t j, n, used;
45090#if defined(DUK_USE_HEAPPTR16)
45091 duk_uint16_t *lst;
45092 duk_uint16_t null16 = heap->heapptr_null16;
45093#else
45094 duk_hstring **lst;
45095#endif
45096
45097 DUK_ASSERT(heap != NULL);
45098
45099 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
45100 e = heap->strtable + i;
45101
45102 if (e->listlen == 0) {
45103#if defined(DUK_USE_HEAPPTR16)
45104 DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str16 != null16 ? 1 : 0)));
45105#else
45106 DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str ? 1 : 0)));
45107#endif
45108 } else {
45109 used = 0;
45110#if defined(DUK_USE_HEAPPTR16)
45111 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45112#else
45113 lst = e->u.strlist;
45114#endif
45115 DUK_ASSERT(lst != NULL);
45116 for (j = 0, n = e->listlen; j < n; j++) {
45117#if defined(DUK_USE_HEAPPTR16)
45118 if (lst[j] != null16) {
45119#else
45120 if (lst[j] != NULL) {
45121#endif
45122 used++;
45123 }
45124 }
45125 DUK_DD(DUK_DDPRINT("[%03d] -> array %d/%d", (int) i, (int) used, (int) e->listlen));
45127 }
45128}
45129#endif /* DUK_USE_DEBUG */
45130
45131#endif /* DUK_USE_STRTAB_CHAIN */
45132
45133/*
45134 * String table algorithm: closed hashing with a probe sequence
45135 *
45136 * This is the default algorithm and works fine for environments with
45137 * minimal memory constraints.
45138 */
45139
45140#if defined(DUK_USE_STRTAB_PROBE)
45141
45142/* Count actually used (non-NULL, non-DELETED) entries. */
45144 duk_int_t res = 0;
45145 duk_uint_fast32_t i, n;
45146#if defined(DUK_USE_HEAPPTR16)
45147 duk_uint16_t null16 = heap->heapptr_null16;
45148 duk_uint16_t deleted16 = heap->heapptr_deleted16;
45149#endif
45151 n = (duk_uint_fast32_t) heap->st_size;
45152 for (i = 0; i < n; i++) {
45153#if defined(DUK_USE_HEAPPTR16)
45154 if (heap->strtable16[i] != null16 && heap->strtable16[i] != deleted16) {
45155#else
45156 if (heap->strtable[i] != NULL && heap->strtable[i] != DUK__DELETED_MARKER(heap)) {
45157#endif
45158 res++;
45159 }
45160 }
45161 return res;
45162}
45163
45164#if defined(DUK_USE_HEAPPTR16)
45165DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
45166#else
45167DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
45168#endif
45169 duk_uint32_t i;
45170 duk_uint32_t step;
45171#if defined(DUK_USE_HEAPPTR16)
45172 duk_uint16_t null16 = heap->heapptr_null16;
45173 duk_uint16_t deleted16 = heap->heapptr_deleted16;
45174#endif
45175
45176 DUK_ASSERT(size > 0);
45177
45180 for (;;) {
45181#if defined(DUK_USE_HEAPPTR16)
45182 duk_uint16_t e16 = entries16[i];
45183#else
45184 duk_hstring *e = entries[i];
45185#endif
45186
45187#if defined(DUK_USE_HEAPPTR16)
45188 /* XXX: could check for e16 == 0 because NULL is guaranteed to
45189 * encode to zero.
45190 */
45191 if (e16 == null16) {
45192#else
45193 if (e == NULL) {
45194#endif
45195 DUK_DDD(DUK_DDDPRINT("insert hit (null): %ld", (long) i));
45196#if defined(DUK_USE_HEAPPTR16)
45197 entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45198#else
45199 entries[i] = h;
45200#endif
45201 (*p_used)++;
45202 break;
45203#if defined(DUK_USE_HEAPPTR16)
45204 } else if (e16 == deleted16) {
45205#else
45206 } else if (e == DUK__DELETED_MARKER(heap)) {
45207#endif
45208 /* st_used remains the same, DELETED is counted as used */
45209 DUK_DDD(DUK_DDDPRINT("insert hit (deleted): %ld", (long) i));
45210#if defined(DUK_USE_HEAPPTR16)
45211 entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45212#else
45213 entries[i] = h;
45214#endif
45215 break;
45216 }
45217 DUK_DDD(DUK_DDDPRINT("insert miss: %ld", (long) i));
45218 i = (i + step) % size;
45219
45220 /* looping should never happen */
45222 }
45223}
45224
45225#if defined(DUK_USE_HEAPPTR16)
45226DUK_LOCAL duk_hstring *duk__find_matching_string_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45227#else
45228DUK_LOCAL duk_hstring *duk__find_matching_string_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45229#endif
45230 duk_uint32_t i;
45231 duk_uint32_t step;
45232
45233 DUK_ASSERT(size > 0);
45234
45235 i = DUK__HASH_INITIAL(strhash, size);
45236 step = DUK__HASH_PROBE_STEP(strhash);
45237 for (;;) {
45238 duk_hstring *e;
45239#if defined(DUK_USE_HEAPPTR16)
45240 e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, entries16[i]);
45241#else
45242 e = entries[i];
45243#endif
45244
45245 if (!e) {
45246 return NULL;
45247 }
45248 if (e != DUK__DELETED_MARKER(heap) && DUK_HSTRING_GET_BYTELEN(e) == blen) {
45249 if (DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e), (size_t) blen) == 0) {
45250 DUK_DDD(DUK_DDDPRINT("find matching hit: %ld (step %ld, size %ld)",
45251 (long) i, (long) step, (long) size));
45252 return e;
45253 }
45254 }
45255 DUK_DDD(DUK_DDDPRINT("find matching miss: %ld (step %ld, size %ld)",
45256 (long) i, (long) step, (long) size));
45257 i = (i + step) % size;
45258
45259 /* looping should never happen */
45260 DUK_ASSERT(i != DUK__HASH_INITIAL(strhash, size));
45261 }
45263}
45264
45265#if defined(DUK_USE_HEAPPTR16)
45266DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_hstring *h) {
45267#else
45268DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h) {
45269#endif
45270 duk_uint32_t i;
45271 duk_uint32_t step;
45272 duk_uint32_t hash;
45273#if defined(DUK_USE_HEAPPTR16)
45274 duk_uint16_t null16 = heap->heapptr_null16;
45275 duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45276#endif
45277
45278 DUK_ASSERT(size > 0);
45279
45280 hash = DUK_HSTRING_GET_HASH(h);
45281 i = DUK__HASH_INITIAL(hash, size);
45282 step = DUK__HASH_PROBE_STEP(hash);
45283 for (;;) {
45284#if defined(DUK_USE_HEAPPTR16)
45285 duk_uint16_t e16 = entries16[i];
45286#else
45287 duk_hstring *e = entries[i];
45288#endif
45289
45290#if defined(DUK_USE_HEAPPTR16)
45291 if (e16 == null16) {
45292#else
45293 if (!e) {
45294#endif
45296 break;
45297 }
45298#if defined(DUK_USE_HEAPPTR16)
45299 if (e16 == h16) {
45300#else
45301 if (e == h) {
45302#endif
45303 /* st_used remains the same, DELETED is counted as used */
45304 DUK_DDD(DUK_DDDPRINT("free matching hit: %ld", (long) i));
45305#if defined(DUK_USE_HEAPPTR16)
45306 entries16[i] = heap->heapptr_deleted16;
45307#else
45308 entries[i] = DUK__DELETED_MARKER(heap);
45309#endif
45310 break;
45311 }
45312
45313 DUK_DDD(DUK_DDDPRINT("free matching miss: %ld", (long) i));
45314 i = (i + step) % size;
45315
45316 /* looping should never happen */
45317 DUK_ASSERT(i != DUK__HASH_INITIAL(hash, size));
45318 }
45319}
45320
45321DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size) {
45322#if defined(DUK_USE_DEBUG)
45323 duk_uint32_t old_used = heap->st_used;
45324#endif
45325 duk_uint32_t old_size = heap->st_size;
45326#if defined(DUK_USE_HEAPPTR16)
45327 duk_uint16_t *old_entries = heap->strtable16;
45328 duk_uint16_t *new_entries = NULL;
45329#else
45330 duk_hstring **old_entries = heap->strtable;
45331 duk_hstring **new_entries = NULL;
45332#endif
45333 duk_uint32_t new_used = 0;
45334 duk_uint32_t i;
45335
45336#if defined(DUK_USE_DEBUG)
45337 DUK_UNREF(old_used); /* unused with some debug level combinations */
45338#endif
45339
45340#ifdef DUK_USE_DDDPRINT
45341 DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
45342 (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
45343 (long) (((double) old_used) / ((double) old_size) * 100.0),
45344 (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) duk__count_used_probe(heap),
45345 (long) (((double) duk__count_used_probe(heap)) / ((double) new_size) * 100.0)));
45346#endif
45347
45348 DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used_probe(heap)); /* required for rehash to succeed, equality not that useful */
45349 DUK_ASSERT(old_entries);
45350
45351 /*
45352 * The attempt to allocate may cause a GC. Such a GC must not attempt to resize
45353 * the stringtable (though it can be swept); finalizer execution and object
45354 * compaction must also be postponed to avoid the pressure to add strings to the
45355 * string table. Call site must prevent these.
45356 */
45357
45358#if defined(DUK_USE_MARK_AND_SWEEP)
45362#endif
45363
45364#if defined(DUK_USE_HEAPPTR16)
45365 new_entries = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * new_size);
45366#else
45367 new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size);
45368#endif
45369
45370 if (!new_entries) {
45371 goto resize_error;
45372 }
45373
45374#if defined(DUK_USE_EXPLICIT_NULL_INIT)
45375 for (i = 0; i < new_size; i++) {
45376#if defined(DUK_USE_HEAPPTR16)
45377 new_entries[i] = heap->heapptr_null16;
45378#else
45379 new_entries[i] = NULL;
45380#endif
45381 }
45382#else
45383#if defined(DUK_USE_HEAPPTR16)
45384 /* Relies on NULL encoding to zero. */
45385 DUK_MEMZERO(new_entries, sizeof(duk_uint16_t) * new_size);
45386#else
45387 DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size);
45388#endif
45389#endif
45390
45391 /* Because new_size > duk__count_used_probe(heap), guaranteed to work */
45392 for (i = 0; i < old_size; i++) {
45393 duk_hstring *e;
45394
45395#if defined(DUK_USE_HEAPPTR16)
45396 e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, old_entries[i]);
45397#else
45398 e = old_entries[i];
45399#endif
45400 if (e == NULL || e == DUK__DELETED_MARKER(heap)) {
45401 continue;
45402 }
45403 /* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */
45404 duk__insert_hstring_probe(heap, new_entries, new_size, &new_used, e);
45405 }
45406
45407#ifdef DUK_USE_DDPRINT
45408 DUK_DD(DUK_DDPRINT("resized stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
45409 (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
45410 (long) (((double) old_used) / ((double) old_size) * 100.0),
45411 (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) new_used,
45412 (long) (((double) new_used) / ((double) new_size) * 100.0)));
45413#endif
45414
45415#if defined(DUK_USE_HEAPPTR16)
45416 DUK_FREE(heap, heap->strtable16);
45417 heap->strtable16 = new_entries;
45418#else
45419 DUK_FREE(heap, heap->strtable);
45420 heap->strtable = new_entries;
45421#endif
45422 heap->st_size = new_size;
45423 heap->st_used = new_used; /* may be less, since DELETED entries are NULLed by rehash */
45424
45425 return 0; /* OK */
45426
45427 resize_error:
45428 DUK_FREE(heap, new_entries);
45429 return 1; /* FAIL */
45430}
45431
45433 duk_uint32_t new_size;
45434 duk_bool_t ret;
45435
45436 new_size = (duk_uint32_t) duk__count_used_probe(heap);
45437 if (new_size >= 0x80000000UL) {
45439 } else {
45441 new_size = duk_util_get_hash_prime(new_size);
45442 }
45443 DUK_ASSERT(new_size > 0);
45444
45445 /* rehash even if old and new sizes are the same to get rid of
45446 * DELETED entries.
45447 */
45448
45449 ret = duk__resize_strtab_raw_probe(heap, new_size);
45450
45451 return ret;
45452}
45453
45454DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe(duk_heap *heap, duk_uint32_t new_used) {
45455 duk_uint32_t new_free;
45456 duk_uint32_t tmp1;
45457 duk_uint32_t tmp2;
45458
45459 DUK_ASSERT(new_used <= heap->st_size); /* grow by at most one */
45460 new_free = heap->st_size - new_used; /* unsigned intentionally */
45461
45462 /* new_free / size <= 1 / DIV <=> new_free <= size / DIV */
45463 /* new_used / size <= 1 / DIV <=> new_used <= size / DIV */
45464
45465 tmp1 = heap->st_size / DUK_STRTAB_MIN_FREE_DIVISOR;
45466 tmp2 = heap->st_size / DUK_STRTAB_MIN_USED_DIVISOR;
45467
45468 if (new_free <= tmp1 || new_used <= tmp2) {
45469 /* load factor too low or high, count actually used entries and resize */
45470 return duk__resize_strtab_probe(heap);
45471 } else {
45472 return 0; /* OK */
45473 }
45474}
45475
45476#if defined(DUK_USE_DEBUG)
45477DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
45478 duk_uint32_t i;
45479 duk_hstring *h;
45480
45481 DUK_ASSERT(heap != NULL);
45482#if defined(DUK_USE_HEAPPTR16)
45483 DUK_ASSERT(heap->strtable16 != NULL);
45484#else
45485 DUK_ASSERT(heap->strtable != NULL);
45486#endif
45487 DUK_UNREF(h);
45488
45489 for (i = 0; i < heap->st_size; i++) {
45490#if defined(DUK_USE_HEAPPTR16)
45491 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->strtable16[i]);
45492#else
45493 h = heap->strtable[i];
45494#endif
45495
45496 DUK_DD(DUK_DDPRINT("[%03d] -> %p", (int) i, (void *) h));
45497 }
45498}
45499#endif /* DUK_USE_DEBUG */
45500
45501#endif /* DUK_USE_STRTAB_PROBE */
45502
45503/*
45504 * Raw intern and lookup
45505 */
45506
45507DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45508 duk_hstring *res;
45509 const duk_uint8_t *extdata;
45510#if defined(DUK_USE_MARK_AND_SWEEP)
45511 duk_small_uint_t prev_mark_and_sweep_base_flags;
45512#endif
45513
45514 /* Prevent any side effects on the string table and the caller provided
45515 * str/blen arguments while interning is in progress. For example, if
45516 * the caller provided str/blen from a dynamic buffer, a finalizer might
45517 * resize that dynamic buffer, invalidating the call arguments.
45518 */
45519#if defined(DUK_USE_MARK_AND_SWEEP)
45521 prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
45523#endif
45524
45525#if defined(DUK_USE_STRTAB_PROBE)
45526 if (duk__recheck_strtab_size_probe(heap, heap->st_used + 1)) {
45527 goto failed;
45528 }
45529#endif
45530
45531 /* For manual testing only. */
45532#if 0
45533 {
45534 duk_size_t i;
45535 DUK_PRINTF("INTERN: \"");
45536 for (i = 0; i < blen; i++) {
45537 duk_uint8_t x = str[i];
45538 if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') {
45539 DUK_PRINTF("%c", (int) x); /* char: use int cast */
45540 } else {
45541 DUK_PRINTF("\\x%02lx", (long) x);
45542 }
45543 }
45544 DUK_PRINTF("\"\n");
45545 }
45546#endif
45547
45548#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
45549 extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
45550#else
45551 extdata = (const duk_uint8_t *) NULL;
45552#endif
45553 res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata);
45554 if (!res) {
45555 goto failed;
45556 }
45557
45558#if defined(DUK_USE_STRTAB_CHAIN)
45559 if (duk__insert_hstring_chain(heap, res)) {
45560 /* failed */
45561 DUK_FREE(heap, res);
45562 goto failed;
45563 }
45564#elif defined(DUK_USE_STRTAB_PROBE)
45565 /* guaranteed to succeed */
45567#if defined(DUK_USE_HEAPPTR16)
45568 heap->strtable16,
45569#else
45570 heap->strtable,
45571#endif
45572 heap->st_size,
45573 &heap->st_used,
45574 res);
45575#else
45576#error internal error, invalid strtab options
45577#endif
45579 /* Note: hstring is in heap but has refcount zero and is not strongly reachable.
45580 * Caller should increase refcount and make the hstring reachable before any
45581 * operations which require allocation (and possible gc).
45582 */
45583
45584 done:
45585#if defined(DUK_USE_MARK_AND_SWEEP)
45586 heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
45587#endif
45588 return res;
45589
45590 failed:
45591 res = NULL;
45592 goto done;
45593}
45594
45595DUK_LOCAL duk_hstring *duk__do_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash) {
45596 duk_hstring *res;
45597
45598 DUK_ASSERT(out_strhash);
45599
45600 *out_strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
45601
45602#if defined(DUK_USE_ROM_STRINGS)
45603 {
45605 /* XXX: This is VERY inefficient now, and should be e.g. a
45606 * binary search or perfect hash, to be fixed.
45607 */
45608 for (i = 0; i < (duk_small_uint_t) (sizeof(duk_rom_strings) / sizeof(duk_hstring *)); i++) {
45609 duk_hstring *romstr;
45610 romstr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings[i]);
45611 if (blen == DUK_HSTRING_GET_BYTELEN(romstr) &&
45612 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(romstr), blen) == 0) {
45613 DUK_DD(DUK_DDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
45614 romstr, (unsigned long) *out_strhash, (unsigned long) DUK_HSTRING_GET_HASH(romstr)));
45615 DUK_ASSERT(*out_strhash == DUK_HSTRING_GET_HASH(romstr));
45616 *out_strhash = DUK_HSTRING_GET_HASH(romstr);
45617 return romstr;
45618 }
45619 }
45620 }
45621#endif /* DUK_USE_ROM_STRINGS */
45622
45623#if defined(DUK_USE_STRTAB_CHAIN)
45624 res = duk__find_matching_string_chain(heap, str, blen, *out_strhash);
45625#elif defined(DUK_USE_STRTAB_PROBE)
45627#if defined(DUK_USE_HEAPPTR16)
45628 heap->strtable16,
45629#else
45630 heap->strtable,
45631#endif
45632 heap->st_size,
45633 str,
45634 blen,
45635 *out_strhash);
45636#else
45637#error internal error, invalid strtab options
45638#endif
45639
45640 return res;
45641}
45642
45643/*
45644 * Exposed calls
45645 */
45646
45647#if 0 /*unused*/
45648DUK_INTERNAL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
45649 duk_uint32_t strhash; /* dummy */
45650 return duk__do_lookup(heap, str, blen, &strhash);
45651}
45652#endif
45654DUK_INTERNAL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
45655 duk_hstring *res;
45656 duk_uint32_t strhash;
45657
45658 /* caller is responsible for ensuring this */
45660
45661 res = duk__do_lookup(heap, str, blen, &strhash);
45662 if (res) {
45663 return res;
45664 }
45665
45666 res = duk__do_intern(heap, str, blen, strhash);
45667 return res; /* may be NULL */
45668}
45669
45670DUK_INTERNAL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
45671 duk_hstring *res = duk_heap_string_intern(thr->heap, str, blen);
45672 if (!res) {
45674 }
45675 return res;
45676}
45677
45678#if 0 /*unused*/
45679DUK_INTERNAL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val) {
45680 char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
45681 DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
45682 buf[sizeof(buf) - 1] = (char) 0;
45683 DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX); /* formatted result limited */
45684 return duk_heap_string_lookup(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
45685}
45686#endif
45687
45690 DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
45691 buf[sizeof(buf) - 1] = (char) 0;
45692 DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX); /* formatted result limited */
45693 return duk_heap_string_intern(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
45694}
45695
45698 if (!res) {
45700 }
45701 return res;
45702}
45703
45704/* find and remove string from stringtable; caller must free the string itself */
45705#if defined(DUK_USE_REFERENCE_COUNTING)
45707 DUK_DDD(DUK_DDDPRINT("remove string from stringtable: %!O", (duk_heaphdr *) h));
45708
45709#if defined(DUK_USE_STRTAB_CHAIN)
45710 duk__remove_matching_hstring_chain(heap, h);
45711#elif defined(DUK_USE_STRTAB_PROBE)
45713#if defined(DUK_USE_HEAPPTR16)
45714 heap->strtable16,
45715#else
45716 heap->strtable,
45717#endif
45718 heap->st_size,
45719 h);
45720#else
45721#error internal error, invalid strtab options
45722#endif
45723}
45724#endif
45725
45726#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
45728 duk_small_uint_t prev_mark_and_sweep_base_flags;
45729 /* Force a resize so that DELETED entries are eliminated.
45730 * Another option would be duk__recheck_strtab_size_probe();
45731 * but since that happens on every intern anyway, this whole
45732 * check can now be disabled.
45733 */
45734
45736 prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
45738
45739#if defined(DUK_USE_STRTAB_CHAIN)
45740 DUK_UNREF(heap);
45741#elif defined(DUK_USE_STRTAB_PROBE)
45742 (void) duk__resize_strtab_probe(heap);
45743#endif
45744
45745 heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
45746}
45747#endif
45748
45749#if defined(DUK_USE_STRTAB_CHAIN)
45751 /* Free strings in the stringtable and any allocations needed
45752 * by the stringtable itself.
45753 */
45754 duk_uint_fast32_t i, j;
45756#if defined(DUK_USE_HEAPPTR16)
45757 duk_uint16_t *lst;
45758 duk_uint16_t null16 = heap->heapptr_null16;
45759#else
45760 duk_hstring **lst;
45761#endif
45762 duk_hstring *h;
45763
45764 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
45765 e = heap->strtable + i;
45766 if (e->listlen > 0) {
45767#if defined(DUK_USE_HEAPPTR16)
45768 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45769#else
45770 lst = e->u.strlist;
45771#endif
45772 DUK_ASSERT(lst != NULL);
45773
45774 for (j = 0; j < e->listlen; j++) {
45775#if defined(DUK_USE_HEAPPTR16)
45776 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
45777 lst[j] = null16;
45778#else
45779 h = lst[j];
45780 lst[j] = NULL;
45781#endif
45782 /* strings may have inner refs (extdata) in some cases */
45783 if (h != NULL) {
45784 duk_free_hstring_inner(heap, h);
45785 DUK_FREE(heap, h);
45786 }
45787 }
45788#if defined(DUK_USE_HEAPPTR16)
45789 e->u.strlist16 = null16;
45790#else
45791 e->u.strlist = NULL;
45792#endif
45793 DUK_FREE(heap, lst);
45794 } else {
45795#if defined(DUK_USE_HEAPPTR16)
45796 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
45797 e->u.str16 = null16;
45798#else
45799 h = e->u.str;
45800 e->u.str = NULL;
45801#endif
45802 if (h != NULL) {
45803 duk_free_hstring_inner(heap, h);
45804 DUK_FREE(heap, h);
45805 }
45806 }
45807 e->listlen = 0;
45808 }
45809}
45810#endif /* DUK_USE_STRTAB_CHAIN */
45811
45812#if defined(DUK_USE_STRTAB_PROBE)
45815 duk_hstring *h;
45816
45817#if defined(DUK_USE_HEAPPTR16)
45818 if (heap->strtable16) {
45819#else
45820 if (heap->strtable) {
45821#endif
45822 for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
45823#if defined(DUK_USE_HEAPPTR16)
45824 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
45825#else
45826 h = heap->strtable[i];
45827#endif
45828 if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
45829 continue;
45830 }
45831 DUK_ASSERT(h != NULL);
45832
45833 /* strings may have inner refs (extdata) in some cases */
45834 duk_free_hstring_inner(heap, h);
45835 DUK_FREE(heap, h);
45836#if 0 /* not strictly necessary */
45837 heap->strtable[i] = NULL;
45838#endif
45839 }
45840#if defined(DUK_USE_HEAPPTR16)
45841 DUK_FREE(heap, heap->strtable16);
45842#else
45843 DUK_FREE(heap, heap->strtable);
45844#endif
45845#if 0 /* not strictly necessary */
45846 heap->strtable = NULL;
45847#endif
45848 }
45850#endif /* DUK_USE_STRTAB_PROBE */
45851
45852/* Undefine local defines */
45853#undef DUK__HASH_INITIAL
45854#undef DUK__HASH_PROBE_STEP
45855#undef DUK__DELETED_MARKER
45856/*
45857 * Hobject allocation.
45858 *
45859 * Provides primitive allocation functions for all object types (plain object,
45860 * compiled function, native function, thread). The object return is not yet
45861 * in "heap allocated" list and has a refcount of zero, so caller must careful.
45862 */
45863
45864/* include removed: duk_internal.h */
45865
45866DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags) {
45867#ifdef DUK_USE_EXPLICIT_NULL_INIT
45868 DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
45869#endif
45870
45871 /* XXX: macro? sets both heaphdr and object flags */
45872 obj->hdr.h_flags = hobject_flags;
45873 DUK_HEAPHDR_SET_TYPE(&obj->hdr, DUK_HTYPE_OBJECT); /* also goes into flags */
45874
45875#if defined(DUK_USE_HEAPPTR16)
45876 /* Zero encoded pointer is required to match NULL */
45877 DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
45878#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
45879 DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
45880#endif
45881#endif
45882 DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);
45884
45885 /*
45886 * obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
45887 * with this properly. This is intentional: empty objects consume a minimum
45888 * amount of memory. Further, an initial allocation might fail and cause
45889 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
45890 */
45891}
45892
45893/*
45894 * Allocate an duk_hobject.
45895 *
45896 * The allocated object has no allocation for properties; the caller may
45897 * want to force a resize if a desired size is known.
45898 *
45899 * The allocated object has zero reference count and is not reachable.
45900 * The caller MUST make the object reachable and increase its reference
45901 * count before invoking any operation that might require memory allocation.
45902 */
45903
45905 duk_hobject *res;
45906
45907 DUK_ASSERT(heap != NULL);
45909 /* different memory layout, alloc size, and init */
45910 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPILEDFUNCTION) == 0);
45911 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATIVEFUNCTION) == 0);
45912 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_THREAD) == 0);
45913
45914 res = (duk_hobject *) DUK_ALLOC(heap, sizeof(duk_hobject));
45915 if (!res) {
45916 return NULL;
45917 }
45918 DUK_MEMZERO(res, sizeof(duk_hobject));
45919
45920 duk__init_object_parts(heap, res, hobject_flags);
45921
45922 return res;
45923}
45924
45927
45928 res = (duk_hcompiledfunction *) DUK_ALLOC(heap, sizeof(duk_hcompiledfunction));
45929 if (!res) {
45930 return NULL;
45931 }
45933
45934 duk__init_object_parts(heap, &res->obj, hobject_flags);
45935
45936#ifdef DUK_USE_EXPLICIT_NULL_INIT
45937#ifdef DUK_USE_HEAPPTR16
45938 /* NULL pointer is required to encode to zero, so memset is enough. */
45939#else
45940 res->data = NULL;
45941 res->funcs = NULL;
45942 res->bytecode = NULL;
45943#endif
45944#endif
45945
45946 return res;
45947}
45948
45951
45952 res = (duk_hnativefunction *) DUK_ALLOC(heap, sizeof(duk_hnativefunction));
45953 if (!res) {
45954 return NULL;
45955 }
45956 DUK_MEMZERO(res, sizeof(duk_hnativefunction));
45957
45958 duk__init_object_parts(heap, &res->obj, hobject_flags);
45959
45960#ifdef DUK_USE_EXPLICIT_NULL_INIT
45961 res->func = NULL;
45962#endif
45963
45964 return res;
45965}
45966
45968 duk_hbufferobject *res;
45969
45970 res = (duk_hbufferobject *) DUK_ALLOC(heap, sizeof(duk_hbufferobject));
45971 if (!res) {
45972 return NULL;
45973 }
45974 DUK_MEMZERO(res, sizeof(duk_hbufferobject));
45975
45976 duk__init_object_parts(heap, &res->obj, hobject_flags);
45978#ifdef DUK_USE_EXPLICIT_NULL_INIT
45979 res->buf = NULL;
45980#endif
45981
45983 return res;
45984}
45985
45986/*
45987 * Allocate a new thread.
45988 *
45989 * Leaves the built-ins array uninitialized. The caller must either
45990 * initialize a new global context or share existing built-ins from
45991 * another thread.
45992 */
45993
45995 duk_hthread *res;
45996
45997 res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
45998 if (!res) {
45999 return NULL;
46000 }
46001 DUK_MEMZERO(res, sizeof(duk_hthread));
46002
46003 duk__init_object_parts(heap, &res->obj, hobject_flags);
46004
46005#ifdef DUK_USE_EXPLICIT_NULL_INIT
46006 res->ptr_curr_pc = NULL;
46007 res->heap = NULL;
46008 res->valstack = NULL;
46009 res->valstack_end = NULL;
46010 res->valstack_bottom = NULL;
46011 res->valstack_top = NULL;
46012 res->callstack = NULL;
46013 res->catchstack = NULL;
46014 res->resumer = NULL;
46015 res->compile_ctx = NULL,
46016#ifdef DUK_USE_HEAPPTR16
46017 res->strs16 = NULL;
46018#else
46019 res->strs = NULL;
46020#endif
46021 {
46022 int i;
46023 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
46024 res->builtins[i] = NULL;
46025 }
46026 }
46027#endif
46028 /* when nothing is running, API calls are in non-strict mode */
46029 DUK_ASSERT(res->strict == 0);
46030
46031 res->heap = heap;
46035
46036 return res;
46037}
46038
46039#if 0 /* unused now */
46040DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) {
46041 duk_hobject *res = duk_hobject_alloc(thr->heap, hobject_flags);
46042 if (!res) {
46044 }
46045 return res;
46046}
46047#endif
46048/*
46049 * Hobject enumeration support.
46050 *
46051 * Creates an internal enumeration state object to be used e.g. with for-in
46052 * enumeration. The state object contains a snapshot of target object keys
46053 * and internal control state for enumeration. Enumerator flags allow caller
46054 * to e.g. request internal/non-enumerable properties, and to enumerate only
46055 * "own" properties.
46056 *
46057 * Also creates the result value for e.g. Object.keys() based on the same
46058 * internal structure.
46059 *
46060 * This snapshot-based enumeration approach is used to simplify enumeration:
46061 * non-snapshot-based approaches are difficult to reconcile with mutating
46062 * the enumeration target, running multiple long-lived enumerators at the
46063 * same time, garbage collection details, etc. The downside is that the
46064 * enumerator object is memory inefficient especially for iterating arrays.
46065 */
46066
46067/* include removed: duk_internal.h */
46068
46069/* XXX: identify enumeration target with an object index (not top of stack) */
46070
46071/* must match exactly the number of internal properties inserted to enumerator */
46072#define DUK__ENUM_START_INDEX 2
46073
46074DUK_LOCAL const duk_uint16_t duk__bufferobject_virtual_props[] = {
46079};
46080
46081/*
46082 * Helper to sort array index keys. The keys are in the enumeration object
46083 * entry part, starting from DUK__ENUM_START_INDEX, and the entry part is dense.
46084 *
46085 * We use insertion sort because it is simple (leading to compact code,)
46086 * works nicely in-place, and minimizes operations if data is already sorted
46087 * or nearly sorted (which is a very common case here). It also minimizes
46088 * the use of element comparisons in general. This is nice because element
46089 * comparisons here involve re-parsing the string keys into numbers each
46090 * time, which is naturally very expensive.
46091 *
46092 * Note that the entry part values are all "true", e.g.
46093 *
46094 * "1" -> true, "3" -> true, "2" -> true
46095 *
46096 * so it suffices to only work in the key part without exchanging any keys,
46097 * simplifying the sort.
46098 *
46099 * http://en.wikipedia.org/wiki/Insertion_sort
46100 *
46101 * (Compiles to about 160 bytes now as a stand-alone function.)
46102 */
46103
46105 duk_hstring **keys;
46106 duk_hstring **p_curr, **p_insert, **p_end;
46107 duk_hstring *h_curr;
46108 duk_uarridx_t val_highest, val_curr, val_insert;
46109
46110 DUK_ASSERT(h_obj != NULL);
46111 DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h_obj) >= 2); /* control props */
46112 DUK_UNREF(thr);
46113
46114 if (DUK_HOBJECT_GET_ENEXT(h_obj) <= 1 + DUK__ENUM_START_INDEX) {
46115 return;
46116 }
46117
46118 keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
46119 p_end = keys + DUK_HOBJECT_GET_ENEXT(h_obj);
46120 keys += DUK__ENUM_START_INDEX;
46121
46122 DUK_DDD(DUK_DDDPRINT("keys=%p, p_end=%p (after skipping enum props)",
46123 (void *) keys, (void *) p_end));
46124
46125#ifdef DUK_USE_DDDPRINT
46126 {
46128 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
46129 DUK_DDD(DUK_DDDPRINT("initial: %ld %p -> %!O",
46130 (long) i,
46131 (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
46132 (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
46133 }
46134 }
46135#endif
46136
46137 val_highest = DUK_HSTRING_GET_ARRIDX_SLOW(keys[0]);
46138 for (p_curr = keys + 1; p_curr < p_end; p_curr++) {
46139 DUK_ASSERT(*p_curr != NULL);
46140 val_curr = DUK_HSTRING_GET_ARRIDX_SLOW(*p_curr);
46141
46142 if (val_curr >= val_highest) {
46143 DUK_DDD(DUK_DDDPRINT("p_curr=%p, p_end=%p, val_highest=%ld, val_curr=%ld -> "
46144 "already in correct order, next",
46145 (void *) p_curr, (void *) p_end, (long) val_highest, (long) val_curr));
46146 val_highest = val_curr;
46147 continue;
46148 }
46149
46150 DUK_DDD(DUK_DDDPRINT("p_curr=%p, p_end=%p, val_highest=%ld, val_curr=%ld -> "
46151 "needs to be inserted",
46152 (void *) p_curr, (void *) p_end, (long) val_highest, (long) val_curr));
46153
46154 /* Needs to be inserted; scan backwards, since we optimize
46155 * for the case where elements are nearly in order.
46156 */
46157
46158 p_insert = p_curr - 1;
46159 for (;;) {
46160 val_insert = DUK_HSTRING_GET_ARRIDX_SLOW(*p_insert);
46161 if (val_insert < val_curr) {
46162 DUK_DDD(DUK_DDDPRINT("p_insert=%p, val_insert=%ld, val_curr=%ld -> insert after this",
46163 (void *) p_insert, (long) val_insert, (long) val_curr));
46164 p_insert++;
46165 break;
46166 }
46167 if (p_insert == keys) {
46168 DUK_DDD(DUK_DDDPRINT("p_insert=%p -> out of keys, insert to beginning", (void *) p_insert));
46169 break;
46170 }
46171 DUK_DDD(DUK_DDDPRINT("p_insert=%p, val_insert=%ld, val_curr=%ld -> search backwards",
46172 (void *) p_insert, (long) val_insert, (long) val_curr));
46173 p_insert--;
46174 }
46175
46176 DUK_DDD(DUK_DDDPRINT("final p_insert=%p", (void *) p_insert));
46177
46178 /* .-- p_insert .-- p_curr
46179 * v v
46180 * | ... | insert | ... | curr
46181 */
46182
46183 h_curr = *p_curr;
46184 DUK_DDD(DUK_DDDPRINT("memmove: dest=%p, src=%p, size=%ld, h_curr=%p",
46185 (void *) (p_insert + 1), (void *) p_insert,
46186 (long) (p_curr - p_insert), (void *) h_curr));
46187
46188 DUK_MEMMOVE((void *) (p_insert + 1),
46189 (const void *) p_insert,
46190 (size_t) ((p_curr - p_insert) * sizeof(duk_hstring *)));
46191 *p_insert = h_curr;
46192 /* keep val_highest */
46193 }
46194
46195#ifdef DUK_USE_DDDPRINT
46196 {
46198 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
46199 DUK_DDD(DUK_DDDPRINT("final: %ld %p -> %!O",
46200 (long) i,
46201 (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
46202 (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
46203 }
46204 }
46205#endif
46206}
46207
46208/*
46209 * Create an internal enumerator object E, which has its keys ordered
46210 * to match desired enumeration ordering. Also initialize internal control
46211 * properties for enumeration.
46212 *
46213 * Note: if an array was used to hold enumeration keys instead, an array
46214 * scan would be needed to eliminate duplicates found in the prototype chain.
46215 */
46216
46218 duk_hthread *thr = (duk_hthread *) ctx;
46219 duk_hobject *enum_target;
46220 duk_hobject *curr;
46221 duk_hobject *res;
46222#if defined(DUK_USE_ES6_PROXY)
46223 duk_hobject *h_proxy_target;
46224 duk_hobject *h_proxy_handler;
46225 duk_hobject *h_trap_result;
46226#endif
46227 duk_uint_fast32_t i, len; /* used for array, stack, and entry indices */
46228
46229 DUK_ASSERT(ctx != NULL);
46230
46231 DUK_DDD(DUK_DDDPRINT("create enumerator, stack top: %ld", (long) duk_get_top(ctx)));
46232
46233 enum_target = duk_require_hobject(ctx, -1);
46234 DUK_ASSERT(enum_target != NULL);
46235
46237 res = duk_require_hobject(ctx, -1);
46238
46239 DUK_DDD(DUK_DDDPRINT("created internal object"));
46240
46241 /* [enum_target res] */
46242
46243 /* Target must be stored so that we can recheck whether or not
46244 * keys still exist when we enumerate. This is not done if the
46245 * enumeration result comes from a proxy trap as there is no
46246 * real object to check against.
46247 */
46248 duk_push_hobject(ctx, enum_target);
46250
46251 /* Initialize index so that we skip internal control keys. */
46254
46255 /*
46256 * Proxy object handling
46257 */
46258
46259#if defined(DUK_USE_ES6_PROXY)
46260 if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
46261 goto skip_proxy;
46262 }
46264 enum_target,
46265 &h_proxy_target,
46266 &h_proxy_handler))) {
46267 goto skip_proxy;
46268 }
46269
46270 DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
46271 duk_push_hobject(ctx, h_proxy_handler);
46273 /* No need to replace the 'enum_target' value in stack, only the
46274 * enum_target reference. This also ensures that the original
46275 * enum target is reachable, which keeps the proxy and the proxy
46276 * target reachable. We do need to replace the internal _Target.
46277 */
46278 DUK_DDD(DUK_DDDPRINT("no enumerate trap, enumerate proxy target instead"));
46279 DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
46280 enum_target = h_proxy_target;
46281
46282 duk_push_hobject(ctx, enum_target); /* -> [ ... enum_target res handler undefined target ] */
46284
46285 duk_pop_2(ctx); /* -> [ ... enum_target res ] */
46286 goto skip_proxy;
46287 }
46288
46289 /* [ ... enum_target res handler trap ] */
46290 duk_insert(ctx, -2);
46291 duk_push_hobject(ctx, h_proxy_target); /* -> [ ... enum_target res trap handler target ] */
46292 duk_call_method(ctx, 1 /*nargs*/); /* -> [ ... enum_target res trap_result ] */
46293 h_trap_result = duk_require_hobject(ctx, -1);
46294 DUK_UNREF(h_trap_result);
46295
46296 /* Copy trap result keys into the enumerator object. */
46297 len = (duk_uint_fast32_t) duk_get_length(ctx, -1);
46298 for (i = 0; i < len; i++) {
46299 /* XXX: not sure what the correct semantic details are here,
46300 * e.g. handling of missing values (gaps), handling of non-array
46301 * trap results, etc.
46302 *
46303 * For keys, we simply skip non-string keys which seems to be
46304 * consistent with how e.g. Object.keys() will process proxy trap
46305 * results (ES6, Section 19.1.2.14).
46306 */
46307 if (duk_get_prop_index(ctx, -1, i) && duk_is_string(ctx, -1)) {
46308 /* [ ... enum_target res trap_result val ] */
46309 duk_push_true(ctx);
46310 /* [ ... enum_target res trap_result val true ] */
46311 duk_put_prop(ctx, -4);
46312 } else {
46313 duk_pop(ctx);
46314 }
46315 }
46316 /* [ ... enum_target res trap_result ] */
46317 duk_pop(ctx);
46318 duk_remove(ctx, -2);
46319
46320 /* [ ... res ] */
46321
46322 /* The internal _Target property is kept pointing to the original
46323 * enumeration target (the proxy object), so that the enumerator
46324 * 'next' operation can read property values if so requested. The
46325 * fact that the _Target is a proxy disables key existence check
46326 * during enumeration.
46327 */
46328 DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
46329 goto compact_and_return;
46330
46331 skip_proxy:
46332#endif /* DUK_USE_ES6_PROXY */
46333
46334 curr = enum_target;
46335 while (curr) {
46336 /*
46337 * Virtual properties.
46338 *
46339 * String and buffer indices are virtual and always enumerable,
46340 * 'length' is virtual and non-enumerable. Array and arguments
46341 * object props have special behavior but are concrete.
46342 */
46343
46346 /* String and buffer enumeration behavior is identical now,
46347 * so use shared handler.
46348 */
46350 duk_hstring *h_val;
46351 h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
46352 DUK_ASSERT(h_val != NULL); /* string objects must not created without internal value */
46354 } else {
46355 duk_hbufferobject *h_bufobj;
46357 h_bufobj = (duk_hbufferobject *) curr;
46358 if (h_bufobj == NULL) {
46359 /* Neutered buffer, zero length seems
46360 * like good behavior here.
46361 */
46362 len = 0;
46363 } else {
46364 /* There's intentionally no check for
46365 * current underlying buffer length.
46366 */
46367 len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
46368 }
46369 }
46370
46371 for (i = 0; i < len; i++) {
46372 duk_hstring *k;
46373
46375 DUK_ASSERT(k);
46376 duk_push_hstring(ctx, k);
46377 duk_push_true(ctx);
46378
46379 /* [enum_target res key true] */
46380 duk_put_prop(ctx, -3);
46381
46382 /* [enum_target res] */
46383 }
46384
46385 /* 'length' and other virtual properties are not
46386 * enumerable, but are included if non-enumerable
46387 * properties are requested.
46388 */
46389
46390 if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
46392
46393 if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
46394 n = sizeof(duk__bufferobject_virtual_props) / sizeof(duk_uint16_t);
46395 } else {
46398 n = 1; /* only 'length' */
46399 }
46400
46401 for (i = 0; i < n; i++) {
46403 duk_push_true(ctx);
46404 duk_put_prop(ctx, -3);
46405 }
46406
46407 }
46408 } else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(curr)) {
46409 if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
46411 duk_push_true(ctx);
46412 duk_put_prop(ctx, -3);
46413 }
46414 }
46415
46416 /*
46417 * Array part
46418 *
46419 * Note: ordering between array and entry part must match 'abandon array'
46420 * behavior in duk_hobject_props.c: key order after an array is abandoned
46421 * must be the same.
46422 */
46423
46424 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
46425 duk_hstring *k;
46426 duk_tval *tv;
46427
46428 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
46429 if (DUK_TVAL_IS_UNUSED(tv)) {
46430 continue;
46431 }
46433 DUK_ASSERT(k);
46434
46435 duk_push_hstring(ctx, k);
46436 duk_push_true(ctx);
46437
46438 /* [enum_target res key true] */
46439 duk_put_prop(ctx, -3);
46440
46441 /* [enum_target res] */
46442 }
46443
46444 /*
46445 * Entries part
46446 */
46447
46448 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
46449 duk_hstring *k;
46450
46451 k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
46452 if (!k) {
46453 continue;
46454 }
46455 if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i) &&
46456 !(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
46457 continue;
46458 }
46459 if (DUK_HSTRING_HAS_INTERNAL(k) &&
46460 !(enum_flags & DUK_ENUM_INCLUDE_INTERNAL)) {
46461 continue;
46462 }
46463 if ((enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) &&
46465 continue;
46466 }
46467
46470
46471 duk_push_hstring(ctx, k);
46472 duk_push_true(ctx);
46473
46474 /* [enum_target res key true] */
46475 duk_put_prop(ctx, -3);
46476
46477 /* [enum_target res] */
46478 }
46479
46480 if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
46481 break;
46482 }
46483
46484 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
46485 }
46486
46487 /* [enum_target res] */
46488
46489 duk_remove(ctx, -2);
46490
46491 /* [res] */
46492
46495 /*
46496 * Some E5/E5.1 algorithms require that array indices are iterated
46497 * in a strictly ascending order. This is the case for e.g.
46498 * Array.prototype.forEach() and JSON.stringify() PropertyList
46499 * handling.
46500 *
46501 * To ensure this property for arrays with an array part (and
46502 * arbitrary objects too, since e.g. forEach() can be applied
46503 * to an array), the caller can request that we sort the keys
46504 * here.
46505 */
46506
46507 /* XXX: avoid this at least when enum_target is an Array, it has an
46508 * array part, and no ancestor properties were included? Not worth
46509 * it for JSON, but maybe worth it for forEach().
46510 */
46511
46512 /* XXX: may need a 'length' filter for forEach()
46513 */
46514 DUK_DDD(DUK_DDDPRINT("sort array indices by caller request"));
46515 duk__sort_array_indices(thr, res);
46516 }
46517
46518#if defined(DUK_USE_ES6_PROXY)
46519 compact_and_return:
46520#endif
46521 /* compact; no need to seal because object is internal */
46522 duk_hobject_compact_props(thr, res);
46523
46524 DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
46525}
46526
46527/*
46528 * Returns non-zero if a key and/or value was enumerated, and:
46529 *
46530 * [enum] -> [key] (get_value == 0)
46531 * [enum] -> [key value] (get_value == 1)
46532 *
46533 * Returns zero without pushing anything on the stack otherwise.
46534 */
46536 duk_hthread *thr = (duk_hthread *) ctx;
46537 duk_hobject *e;
46538 duk_hobject *enum_target;
46539 duk_hstring *res = NULL;
46541 duk_bool_t check_existence;
46542
46543 DUK_ASSERT(ctx != NULL);
46544
46545 /* [... enum] */
46546
46547 e = duk_require_hobject(ctx, -1);
46548
46549 /* XXX use get tval ptr, more efficient */
46551 idx = (duk_uint_fast32_t) duk_require_uint(ctx, -1);
46552 duk_pop(ctx);
46553 DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
46554
46555 /* Enumeration keys are checked against the enumeration target (to see
46556 * that they still exist). In the proxy enumeration case _Target will
46557 * be the proxy, and checking key existence against the proxy is not
46558 * required (or sensible, as the keys may be fully virtual).
46559 */
46561 enum_target = duk_require_hobject(ctx, -1);
46562 DUK_ASSERT(enum_target != NULL);
46563#if defined(DUK_USE_ES6_PROXY)
46564 check_existence = (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(enum_target));
46565#else
46566 check_existence = 1;
46567#endif
46568 duk_pop(ctx); /* still reachable */
46569
46570 DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
46571 (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(ctx, -1)));
46572
46573 /* no array part */
46574 for (;;) {
46575 duk_hstring *k;
46576
46577 if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
46578 DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
46579 break;
46580 }
46581
46582 /* we know these because enum objects are internally created */
46583 k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
46584 DUK_ASSERT(k != NULL);
46587
46588 idx++;
46589
46590 /* recheck that the property still exists */
46591 if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
46592 DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
46593 continue;
46594 }
46595
46596 DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
46597 res = k;
46598 break;
46599 }
46600
46601 DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
46602
46603 duk_push_u32(ctx, (duk_uint32_t) idx);
46605
46606 /* [... enum] */
46607
46608 if (res) {
46609 duk_push_hstring(ctx, res);
46610 if (get_value) {
46611 duk_push_hobject(ctx, enum_target);
46612 duk_dup(ctx, -2); /* -> [... enum key enum_target key] */
46613 duk_get_prop(ctx, -2); /* -> [... enum key enum_target val] */
46614 duk_remove(ctx, -2); /* -> [... enum key val] */
46615 duk_remove(ctx, -3); /* -> [... key val] */
46616 } else {
46617 duk_remove(ctx, -2); /* -> [... key] */
46618 }
46619 return 1;
46620 } else {
46621 duk_pop(ctx); /* -> [...] */
46622 return 0;
46623 }
46624}
46625
46626/*
46627 * Get enumerated keys in an Ecmascript array. Matches Object.keys() behavior
46628 * described in E5 Section 15.2.3.14.
46629 */
46630
46632 duk_hthread *thr = (duk_hthread *) ctx;
46633 duk_hobject *e;
46636
46637 DUK_ASSERT(ctx != NULL);
46638 DUK_ASSERT(duk_get_hobject(ctx, -1) != NULL);
46639 DUK_UNREF(thr);
46640
46641 /* Create a temporary enumerator to get the (non-duplicated) key list;
46642 * the enumerator state is initialized without being needed, but that
46643 * has little impact.
46644 */
46645
46646 duk_hobject_enumerator_create(ctx, enum_flags);
46647 duk_push_array(ctx);
46648
46649 /* [enum_target enum res] */
46650
46651 e = duk_require_hobject(ctx, -2);
46652 DUK_ASSERT(e != NULL);
46653
46654 idx = 0;
46656 duk_hstring *k;
46657
46658 k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, i);
46659 DUK_ASSERT(k); /* enumerator must have no keys deleted */
46660
46661 /* [enum_target enum res] */
46662 duk_push_hstring(ctx, k);
46663 duk_put_prop_index(ctx, -2, idx);
46664 idx++;
46665 }
46666
46667 /* [enum_target enum res] */
46668 duk_remove(ctx, -2);
46669
46670 /* [enum_target res] */
46671
46672 return 1; /* return 1 to allow callers to tail call */
46673}
46674/*
46675 * Run an duk_hobject finalizer. Used for both reference counting
46676 * and mark-and-sweep algorithms. Must never throw an error.
46677 *
46678 * There is no return value. Any return value or error thrown by
46679 * the finalizer is ignored (although errors are debug logged).
46680 *
46681 * Notes:
46682 *
46683 * - The thread used for calling the finalizer is the same as the
46684 * 'thr' argument. This may need to change later.
46685 *
46686 * - The finalizer thread 'top' assertions are there because it is
46687 * critical that strict stack policy is observed (i.e. no cruft
46688 * left on the finalizer stack).
46689 */
46690
46691/* include removed: duk_internal.h */
46692
46694 duk_hthread *thr;
46695
46696 DUK_ASSERT(ctx != NULL);
46697 thr = (duk_hthread *) ctx;
46698
46699 DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
46700
46701 /* [... obj] */
46702
46703 /* XXX: Finalizer lookup should traverse the prototype chain (to allow
46704 * inherited finalizers) but should not invoke accessors or proxy object
46705 * behavior. At the moment this lookup will invoke proxy behavior, so
46706 * caller must ensure that this function is not called if the target is
46707 * a Proxy.
46708 */
46709
46710 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */
46711 if (!duk_is_callable(ctx, -1)) {
46712 DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
46713 return 0;
46714 }
46715 duk_dup(ctx, -2);
46717 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
46718 duk_call(ctx, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
46719 DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
46720 return 0;
46721
46722 /* Note: we rely on duk_safe_call() to fix up the stack for the caller,
46723 * so we don't need to pop stuff here. There is no return value;
46724 * caller determines rescued status based on object refcount.
46725 */
46726}
46727
46729 duk_context *ctx = (duk_context *) thr;
46730 duk_ret_t rc;
46731#ifdef DUK_USE_ASSERTIONS
46732 duk_idx_t entry_top;
46733#endif
46734
46735 DUK_DDD(DUK_DDDPRINT("running object finalizer for object: %p", (void *) obj));
46736
46737 DUK_ASSERT(thr != NULL);
46738 DUK_ASSERT(ctx != NULL);
46739 DUK_ASSERT(obj != NULL);
46741
46742#ifdef DUK_USE_ASSERTIONS
46743 entry_top = duk_get_top(ctx);
46744#endif
46745 /*
46746 * Get and call the finalizer. All of this must be wrapped
46747 * in a protected call, because even getting the finalizer
46748 * may trigger an error (getter may throw one, for instance).
46749 */
46750
46753 DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
46754 return;
46755 }
46756 DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */
46758 /* This shouldn't happen; call sites should avoid looking up
46759 * _Finalizer "through" a Proxy, but ignore if we come here
46760 * with a Proxy to avoid finalizer re-entry.
46761 */
46762 DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call"));
46763 return;
46764 }
46765
46766 /* XXX: use a NULL error handler for the finalizer call? */
46767
46768 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
46769 duk_push_hobject(ctx, obj); /* this also increases refcount by one */
46770 rc = duk_safe_call(ctx, duk__finalize_helper, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
46771 DUK_ASSERT_TOP(ctx, entry_top + 2); /* duk_safe_call discipline */
46772
46773 if (rc != DUK_EXEC_SUCCESS) {
46774 /* Note: we ask for one return value from duk_safe_call to get this
46775 * error debugging here.
46776 */
46777 DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
46778 (void *) obj, (duk_tval *) duk_get_tval(ctx, -1)));
46779 }
46780 duk_pop_2(ctx); /* -> [...] */
46781
46782 DUK_ASSERT_TOP(ctx, entry_top);
46783}
46784/*
46785 * Misc support functions
46786 */
46787
46788/* include removed: duk_internal.h */
46789
46791 duk_uint_t sanity;
46792
46793 DUK_ASSERT(thr != NULL);
46794
46795 /* False if the object is NULL or the prototype 'p' is NULL.
46796 * In particular, false if both are NULL (don't compare equal).
46797 */
46798 if (h == NULL || p == NULL) {
46799 return 0;
46800 }
46801
46803 do {
46804 if (h == p) {
46805 return 1;
46806 }
46807
46808 if (sanity-- == 0) {
46809 if (ignore_loop) {
46810 break;
46811 } else {
46813 }
46814 }
46815 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
46816 } while (h);
46817
46818 return 0;
46819}
46820
46822#ifdef DUK_USE_REFERENCE_COUNTING
46823 duk_hobject *tmp;
46824
46825 DUK_ASSERT(h);
46826 tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
46827 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
46828 DUK_HOBJECT_INCREF_ALLOWNULL(thr, p); /* avoid problems if p == h->prototype */
46830#else
46831 DUK_ASSERT(h);
46832 DUK_UNREF(thr);
46834#endif
46835}
46836/*
46837 * Helpers for creating and querying pc2line debug data, which
46838 * converts a bytecode program counter to a source line number.
46839 *
46840 * The run-time pc2line data is bit-packed, and documented in:
46841 *
46842 * doc/function-objects.rst
46843 */
46844
46845/* include removed: duk_internal.h */
46846
46847#if defined(DUK_USE_PC2LINE)
46848
46849/* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
46851 duk_context *ctx = (duk_context *) thr;
46852 duk_hbuffer_dynamic *h_buf;
46853 duk_bitencoder_ctx be_ctx_alloc;
46854 duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
46855 duk_uint32_t *hdr;
46856 duk_size_t new_size;
46857 duk_uint_fast32_t num_header_entries;
46858 duk_uint_fast32_t curr_offset;
46859 duk_int_fast32_t curr_line, next_line, diff_line;
46860 duk_uint_fast32_t curr_pc;
46861 duk_uint_fast32_t hdr_index;
46862
46864
46865 /* XXX: add proper spare handling to dynamic buffer, to minimize
46866 * reallocs; currently there is no spare at all.
46867 */
46868
46869 num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
46870 curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
46871
46872 duk_push_dynamic_buffer(ctx, (duk_size_t) curr_offset);
46873 h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
46874 DUK_ASSERT(h_buf != NULL);
46876
46877 hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
46878 DUK_ASSERT(hdr != NULL);
46879 hdr[0] = (duk_uint32_t) length; /* valid pc range is [0, length[ */
46880
46881 curr_pc = 0U;
46882 while (curr_pc < length) {
46883 new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
46884 duk_hbuffer_resize(thr, h_buf, new_size);
46885
46886 hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
46887 DUK_ASSERT(hdr != NULL);
46888 DUK_ASSERT(curr_pc < length);
46889 hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
46890 curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
46891 hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
46892 hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
46893
46894#if 0
46895 DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
46896 (long) (curr_pc / DUK_PC2LINE_SKIP),
46897 (long) curr_pc,
46898 (long) hdr[hdr_index + 0],
46899 (long) hdr[hdr_index + 1]));
46900#endif
46901
46902 DUK_MEMZERO(be_ctx, sizeof(*be_ctx));
46903 be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
46905
46906 for (;;) {
46907 curr_pc++;
46908 if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) || /* end of diff run */
46909 (curr_pc >= length) ) { /* end of bytecode */
46910 break;
46911 }
46912 DUK_ASSERT(curr_pc < length);
46913 next_line = (duk_int32_t) instrs[curr_pc].line;
46914 diff_line = next_line - curr_line;
46915
46916#if 0
46917 DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
46918 (long) curr_line, (long) next_line, (long) diff_line));
46919#endif
46920
46921 if (diff_line == 0) {
46922 /* 0 */
46923 duk_be_encode(be_ctx, 0, 1);
46924 } else if (diff_line >= 1 && diff_line <= 4) {
46925 /* 1 0 <2 bits> */
46926 duk_be_encode(be_ctx, (0x02 << 2) + (diff_line - 1), 4);
46927 } else if (diff_line >= -0x80 && diff_line <= 0x7f) {
46928 /* 1 1 0 <8 bits> */
46929 DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
46930 duk_be_encode(be_ctx, (0x06 << 8) + (diff_line + 0x80), 11);
46931 } else {
46932 /* 1 1 1 <32 bits>
46933 * Encode in two parts to avoid bitencode 24-bit limitation
46934 */
46935 duk_be_encode(be_ctx, (0x07 << 16) + ((next_line >> 16) & 0xffffU), 19);
46936 duk_be_encode(be_ctx, next_line & 0xffffU, 16);
46937 }
46938
46939 curr_line = next_line;
46940 }
46941
46942 duk_be_finish(be_ctx);
46943 DUK_ASSERT(!be_ctx->truncated);
46944
46945 /* be_ctx->offset == length of encoded bitstream */
46946 curr_offset += (duk_uint_fast32_t) be_ctx->offset;
46948
46949 /* compact */
46950 new_size = (duk_size_t) curr_offset;
46951 duk_hbuffer_resize(thr, h_buf, new_size);
46952
46953 (void) duk_to_fixed_buffer(ctx, -1, NULL);
46954
46955 DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
46956 (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
46957 (duk_tval *) duk_get_tval(ctx, -1)));
46958}
46959
46960/* PC is unsigned. If caller does PC arithmetic and gets a negative result,
46961 * it will map to a large PC which is out of bounds and causes a zero to be
46962 * returned.
46963 */
46965 duk_bitdecoder_ctx bd_ctx_alloc;
46966 duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
46967 duk_uint32_t *hdr;
46968 duk_uint_fast32_t start_offset;
46969 duk_uint_fast32_t pc_limit;
46970 duk_uint_fast32_t hdr_index;
46971 duk_uint_fast32_t pc_base;
46973 duk_uint_fast32_t curr_line;
46974
46975 DUK_ASSERT(buf != NULL);
46977 DUK_UNREF(thr);
46978
46979 /*
46980 * Use the index in the header to find the right starting point
46981 */
46982
46983 hdr_index = pc / DUK_PC2LINE_SKIP;
46984 pc_base = hdr_index * DUK_PC2LINE_SKIP;
46985 n = pc - pc_base;
46986
46987 if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
46988 DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
46989 goto error;
46990 }
46991
46992 hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
46993 pc_limit = hdr[0];
46994 if (pc >= pc_limit) {
46995 /* Note: pc is unsigned and cannot be negative */
46996 DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
46997 (long) pc, (long) pc_limit));
46998 goto error;
46999 }
47000
47001 curr_line = hdr[1 + hdr_index * 2];
47002 start_offset = hdr[1 + hdr_index * 2 + 1];
47003 if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
47004 DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
47005 (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
47006 goto error;
47007 }
47008
47009 /*
47010 * Iterate the bitstream (line diffs) until PC is reached
47011 */
47012
47013 DUK_MEMZERO(bd_ctx, sizeof(*bd_ctx));
47014 bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
47015 bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
47016
47017#if 0
47018 DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
47019 (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
47020#endif
47021
47022 while (n > 0) {
47023#if 0
47024 DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
47025#endif
47026
47027 if (duk_bd_decode_flag(bd_ctx)) {
47028 if (duk_bd_decode_flag(bd_ctx)) {
47029 if (duk_bd_decode_flag(bd_ctx)) {
47030 /* 1 1 1 <32 bits> */
47032 t = duk_bd_decode(bd_ctx, 16); /* workaround: max nbits = 24 now */
47033 t = (t << 16) + duk_bd_decode(bd_ctx, 16);
47034 curr_line = t;
47035 } else {
47036 /* 1 1 0 <8 bits> */
47038 t = duk_bd_decode(bd_ctx, 8);
47039 curr_line = curr_line + t - 0x80;
47040 }
47041 } else {
47042 /* 1 0 <2 bits> */
47044 t = duk_bd_decode(bd_ctx, 2);
47045 curr_line = curr_line + t + 1;
47046 }
47047 } else {
47048 /* 0: no change */
47049 }
47050
47051 n--;
47052 }
47053
47054 DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
47055 return curr_line;
47056
47057 error:
47058 DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
47059 return 0;
47060}
47061
47063 duk_hbuffer_fixed *pc2line;
47064 duk_uint_fast32_t line;
47065
47066 /* XXX: now that pc2line is used by the debugger quite heavily in
47067 * checked execution, this should be optimized to avoid value stack
47068 * and perhaps also implement some form of pc2line caching (see
47069 * future work in debugger.rst).
47070 */
47071
47073 pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
47074 if (pc2line != NULL) {
47076 line = duk__hobject_pc2line_query_raw((duk_hthread *) ctx, pc2line, (duk_uint_fast32_t) pc);
47077 } else {
47078 line = 0;
47079 }
47080 duk_pop(ctx);
47081
47082 return line;
47083}
47084
47085#endif /* DUK_USE_PC2LINE */
47086/*
47087 * Hobject property set/get functionality.
47088 *
47089 * This is very central functionality for size, performance, and compliance.
47090 * It is also rather intricate; see hobject-algorithms.rst for discussion on
47091 * the algorithms and memory-management.rst for discussion on refcounts and
47092 * side effect issues.
47093 *
47094 * Notes:
47095 *
47096 * - It might be tempting to assert "refcount nonzero" for objects
47097 * being operated on, but that's not always correct: objects with
47098 * a zero refcount may be operated on by the refcount implementation
47099 * (finalization) for instance. Hence, no refcount assertions are made.
47100 *
47101 * - Many operations (memory allocation, identifier operations, etc)
47102 * may cause arbitrary side effects (e.g. through GC and finalization).
47103 * These side effects may invalidate duk_tval pointers which point to
47104 * areas subject to reallocation (like value stack). Heap objects
47105 * themselves have stable pointers. Holding heap object pointers or
47106 * duk_tval copies is not problematic with respect to side effects;
47107 * care must be taken when holding and using argument duk_tval pointers.
47108 *
47109 * - If a finalizer is executed, it may operate on the the same object
47110 * we're currently dealing with. For instance, the finalizer might
47111 * delete a certain property which has already been looked up and
47112 * confirmed to exist. Ideally finalizers would be disabled if GC
47113 * happens during property access. At the moment property table realloc
47114 * disables finalizers, and all DECREFs may cause arbitrary changes so
47115 * handle DECREF carefully.
47116 *
47117 * - The order of operations for a DECREF matters. When DECREF is executed,
47118 * the entire object graph must be consistent; note that a refzero may
47119 * lead to a mark-and-sweep through a refcount finalizer.
47121
47122/*
47123 * XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
47124 * might be more appropriate.
47125 */
47126
47128 * XXX: duk_uint_fast32_t should probably be used in many places here.
47129 */
47130
47131/* include removed: duk_internal.h */
47132
47134 * Local defines
47135 */
47136
47137#define DUK__NO_ARRAY_INDEX DUK_HSTRING_NO_ARRAY_INDEX
47139/* hash probe sequence */
47140#define DUK__HASH_INITIAL(hash,h_size) DUK_HOBJECT_HASH_INITIAL((hash),(h_size))
47141#define DUK__HASH_PROBE_STEP(hash) DUK_HOBJECT_HASH_PROBE_STEP((hash))
47142
47143/* marker values for hash part */
47144#define DUK__HASH_UNUSED DUK_HOBJECT_HASHIDX_UNUSED
47145#define DUK__HASH_DELETED DUK_HOBJECT_HASHIDX_DELETED
47146
47147/* valstack space that suffices for all local calls, including recursion
47148 * of other than Duktape calls (getters etc)
47149 */
47150#define DUK__VALSTACK_SPACE 10
47151
47152/* valstack space allocated especially for proxy lookup which does a
47153 * recursive property lookup
47154 */
47155#define DUK__VALSTACK_PROXY_LOOKUP 20
47156
47157/*
47158 * Local prototypes
47159 */
47160
47164
47165DUK_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);
47167
47170DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc);
47171
47172/*
47173 * Misc helpers
47174 */
47175
47176/* Convert a duk_tval number (caller checks) to a 32-bit index. Returns
47177 * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
47178 * index.
47179 */
47180/* XXX: for fastints, could use a variant which assumes a double duk_tval
47181 * (and doesn't need to check for fastint again).
47182 */
47184 duk_double_t dbl;
47185 duk_uint32_t idx;
47186
47187 DUK_ASSERT(tv != NULL);
47189
47190 /* -0 is accepted here as index 0 because ToString(-0) == "0" which is
47191 * in canonical form and thus an array index.
47192 */
47193 dbl = DUK_TVAL_GET_NUMBER(tv);
47194 idx = (duk_uint32_t) dbl;
47195 if ((duk_double_t) idx == dbl) {
47196 /* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
47197 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
47198 */
47199 return idx;
47200 }
47201 return DUK__NO_ARRAY_INDEX;
47202}
47203
47204#if defined(DUK_USE_FASTINT)
47205/* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
47206DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
47207 duk_int64_t t;
47208
47209 DUK_ASSERT(tv != NULL);
47210 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
47212 t = DUK_TVAL_GET_FASTINT(tv);
47213 if ((t & ~0xffffffffULL) != 0) {
47214 /* Catches >0x100000000 and negative values. */
47215 return DUK__NO_ARRAY_INDEX;
47216 }
47217
47218 /* If the value happens to be 0xFFFFFFFF, it's not a valid array index
47219 * but will then match DUK__NO_ARRAY_INDEX.
47220 */
47221 return (duk_uint32_t) t;
47222}
47223#endif /* DUK_USE_FASTINT */
47224
47225/* Push an arbitrary duk_tval to the stack, coerce it to string, and return
47226 * both a duk_hstring pointer and an array index (or DUK__NO_ARRAY_INDEX).
47227 */
47229 duk_uint32_t arr_idx;
47231
47232 DUK_ASSERT(ctx != NULL);
47233 DUK_ASSERT(tv != NULL);
47234 DUK_ASSERT(out_h != NULL);
47235
47236 duk_push_tval(ctx, tv);
47237 duk_to_string(ctx, -1);
47238 h = duk_get_hstring(ctx, -1);
47239 DUK_ASSERT(h != NULL);
47240 *out_h = h;
47241
47243 return arr_idx;
47244}
47245
47246/* String is an own (virtual) property of a lightfunc. */
47248 DUK_UNREF(thr);
47249 return (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
47250 key == DUK_HTHREAD_STRING_NAME(thr));
47251}
47252
47253/*
47254 * Helpers for managing property storage size
47255 */
47256
47257/* Get default hash part size for a certain entry part size. */
47258#if defined(DUK_USE_HOBJECT_HASH_PART)
47259DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
47262 if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
47263 duk_uint32_t res;
47264
47265 /* result: hash_prime(floor(1.2 * e_size)) */
47266 res = duk_util_get_hash_prime(e_size + e_size / DUK_HOBJECT_H_SIZE_DIVISOR);
47267
47268 /* if fails, e_size will be zero = not an issue, except performance-wise */
47269 DUK_ASSERT(res == 0 || res > e_size);
47270 return res;
47271 } else {
47272 return 0;
47273 }
47274}
47275#endif /* USE_PROP_HASH_PART */
47276
47277/* Get minimum entry part growth for a certain size. */
47278DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
47279 duk_uint32_t res;
47280
47282
47284 DUK_ASSERT(res >= 1); /* important for callers */
47285 return res;
47286}
47287
47288/* Get minimum array part growth for a certain size. */
47289DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
47290 duk_uint32_t res;
47291
47293
47295 DUK_ASSERT(res >= 1); /* important for callers */
47296 return res;
47297}
47298
47299/* Count actually used entry part entries (non-NULL keys). */
47302 duk_uint_fast32_t n = 0;
47303 duk_hstring **e;
47304
47306 DUK_UNREF(thr);
47307
47308 e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
47309 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
47310 if (*e++) {
47311 n++;
47312 }
47313 }
47314 return (duk_uint32_t) n;
47315}
47316
47317/* Count actually used array part entries and array minimum size.
47318 * NOTE: 'out_min_size' can be computed much faster by starting from the
47319 * end and breaking out early when finding first used entry, but this is
47320 * not needed now.
47321 */
47322DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
47324 duk_uint_fast32_t used = 0;
47325 duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1; /* see below */
47326 duk_tval *a;
47327
47328 DUK_ASSERT(obj != NULL);
47329 DUK_ASSERT(out_used != NULL);
47330 DUK_ASSERT(out_min_size != NULL);
47331 DUK_UNREF(thr);
47332
47333 a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
47334 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
47335 duk_tval *tv = a++;
47336 if (!DUK_TVAL_IS_UNUSED(tv)) {
47337 used++;
47338 highest_idx = i;
47339 }
47340 }
47341
47342 /* Initial value for highest_idx is -1 coerced to unsigned. This
47343 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
47344 * for out_min_size as intended.
47345 */
47346
47347 *out_used = used;
47348 *out_min_size = highest_idx + 1; /* 0 if no used entries */
47349}
47350
47351/* Check array density and indicate whether or not the array part should be abandoned. */
47352DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
47353 /*
47354 * Array abandon check; abandon if:
47355 *
47356 * new_used / new_size < limit
47357 * new_used < limit * new_size || limit is 3 bits fixed point
47358 * new_used < limit' / 8 * new_size || *8
47359 * 8*new_used < limit' * new_size || :8
47360 * new_used < limit' * (new_size / 8)
47361 *
47362 * Here, new_used = a_used, new_size = a_size.
47363 *
47364 * Note: some callers use approximate values for a_used and/or a_size
47365 * (e.g. dropping a '+1' term). This doesn't affect the usefulness
47366 * of the check, but may confuse debugging.
47367 */
47368
47369 return (a_used < DUK_HOBJECT_A_ABANDON_LIMIT * (a_size >> 3));
47370}
47371
47372/* Fast check for extending array: check whether or not a slow density check is required. */
47373DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
47374 /*
47375 * In a fast check we assume old_size equals old_used (i.e., existing
47376 * array is fully dense).
47377 *
47378 * Slow check if:
47379 *
47380 * (new_size - old_size) / old_size > limit
47381 * new_size - old_size > limit * old_size
47382 * new_size > (1 + limit) * old_size || limit' is 3 bits fixed point
47383 * new_size > (1 + (limit' / 8)) * old_size || * 8
47384 * 8 * new_size > (8 + limit') * old_size || : 8
47385 * new_size > (8 + limit') * (old_size / 8)
47386 * new_size > limit'' * (old_size / 8) || limit'' = 9 -> max 25% increase
47387 * arr_idx + 1 > limit'' * (old_size / 8)
47388 *
47389 * This check doesn't work well for small values, so old_size is rounded
47390 * up for the check (and the '+ 1' of arr_idx can be ignored in practice):
47391 *
47392 * arr_idx > limit'' * ((old_size + 7) / 8)
47393 */
47394
47395 return (arr_idx > DUK_HOBJECT_A_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
47396}
47397
47398/*
47399 * Proxy helpers
47400 */
47401
47402#if defined(DUK_USE_ES6_PROXY)
47404 duk_tval *tv_target;
47405 duk_tval *tv_handler;
47406 duk_hobject *h_target;
47407 duk_hobject *h_handler;
47408
47409 DUK_ASSERT(thr != NULL);
47410 DUK_ASSERT(obj != NULL);
47411 DUK_ASSERT(out_target != NULL);
47412 DUK_ASSERT(out_handler != NULL);
47413
47414 /* Caller doesn't need to check exotic proxy behavior (but does so for
47415 * some fast paths).
47416 */
47418 return 0;
47419 }
47420
47422 if (!tv_handler) {
47424 return 0;
47425 }
47426 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_handler));
47427 h_handler = DUK_TVAL_GET_OBJECT(tv_handler);
47428 DUK_ASSERT(h_handler != NULL);
47429 *out_handler = h_handler;
47430 tv_handler = NULL; /* avoid issues with relocation */
47431
47433 if (!tv_target) {
47435 return 0;
47436 }
47437 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
47438 h_target = DUK_TVAL_GET_OBJECT(tv_target);
47439 DUK_ASSERT(h_target != NULL);
47440 *out_target = h_target;
47441 tv_target = NULL; /* avoid issues with relocation */
47442
47443 return 1;
47444}
47445#endif /* DUK_USE_ES6_PROXY */
47446
47447/* Get Proxy target object. If the argument is not a Proxy, return it as is.
47448 * If a Proxy is revoked, an error is thrown.
47449 */
47450#if defined(DUK_USE_ES6_PROXY)
47452 duk_hobject *h_target;
47453 duk_hobject *h_handler;
47454
47455 DUK_ASSERT(thr != NULL);
47456 DUK_ASSERT(obj != NULL);
47457
47458 /* Resolve Proxy targets until Proxy chain ends. No explicit check for
47459 * a Proxy loop: user code cannot create such a loop without tweaking
47460 * internal properties directly.
47462
47464 if (duk_hobject_proxy_check(thr, obj, &h_target, &h_handler)) {
47465 DUK_ASSERT(h_target != NULL);
47466 obj = h_target;
47467 } else {
47468 break;
47469 }
47470 }
47471
47472 DUK_ASSERT(obj != NULL);
47473 return obj;
47474}
47475#endif /* DUK_USE_ES6_PROXY */
47476
47477#if defined(DUK_USE_ES6_PROXY)
47479 duk_context *ctx = (duk_context *) thr;
47480 duk_hobject *h_handler;
47481
47482 DUK_ASSERT(thr != NULL);
47483 DUK_ASSERT(obj != NULL);
47484 DUK_ASSERT(tv_key != NULL);
47485 DUK_ASSERT(out_target != NULL);
47486
47487 if (!duk_hobject_proxy_check(thr, obj, out_target, &h_handler)) {
47488 return 0;
47489 }
47490 DUK_ASSERT(*out_target != NULL);
47491 DUK_ASSERT(h_handler != NULL);
47492
47493 /* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
47494 * normal property set/get which would allow a proxy handler to interfere with
47495 * such behavior and to get access to internal key strings. This is not a problem
47496 * as such because internal key strings can be created in other ways too (e.g.
47497 * through buffers). The best fix is to change Duktape internal lookups to
47498 * skip proxy behavior. Until that, internal property accesses bypass the
47499 * proxy and are applied to the target (as if the handler did not exist).
47500 * This has some side effects, see test-bi-proxy-internal-keys.js.
47501 */
47502
47503 if (DUK_TVAL_IS_STRING(tv_key)) {
47504 duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
47505 DUK_ASSERT(h_key != NULL);
47506 if (DUK_HSTRING_HAS_INTERNAL(h_key)) {
47507 DUK_DDD(DUK_DDDPRINT("internal key, skip proxy handler and apply to target"));
47508 return 0;
47509 }
47510 }
47511
47512 /* The handler is looked up with a normal property lookup; it may be an
47513 * accessor or the handler object itself may be a proxy object. If the
47514 * handler is a proxy, we need to extend the valstack as we make a
47515 * recursive proxy check without a function call in between (in fact
47516 * there is no limit to the potential recursion here).
47517 *
47518 * (For sanity, proxy creation rejects another proxy object as either
47519 * the handler or the target at the moment so recursive proxy cases
47520 * are not realized now.)
47521 */
47522
47523 /* XXX: C recursion limit if proxies are allowed as handler/target values */
47524
47526 duk_push_hobject(ctx, h_handler);
47527 if (duk_get_prop_stridx(ctx, -1, stridx_trap)) {
47528 /* -> [ ... handler trap ] */
47529 duk_insert(ctx, -2); /* -> [ ... trap handler ] */
47530
47531 /* stack prepped for func call: [ ... trap handler ] */
47532 return 1;
47533 } else {
47534 duk_pop_2(ctx);
47535 return 0;
47536 }
47537}
47538#endif /* DUK_USE_ES6_PROXY */
47539
47540/*
47541 * Reallocate property allocation, moving properties to the new allocation.
47542 *
47543 * Includes key compaction, rehashing, and can also optionally abandoning
47544 * the array part, 'migrating' array entries into the beginning of the
47545 * new entry part. Arguments are not validated here, so e.g. new_h_size
47546 * MUST be a valid prime.
47547 *
47548 * There is no support for in-place reallocation or just compacting keys
47549 * without resizing the property allocation. This is intentional to keep
47550 * code size minimal.
47551 *
47552 * The implementation is relatively straightforward, except for the array
47553 * abandonment process. Array abandonment requires that new string keys
47554 * are interned, which may trigger GC. All keys interned so far must be
47555 * reachable for GC at all times; valstack is used for that now.
47557 * Also, a GC triggered during this reallocation process must not interfere
47558 * with the object being resized. This is currently controlled by using
47559 * heap->mark_and_sweep_base_flags to indicate that no finalizers will be
47560 * executed (as they can affect ANY object) and no objects are compacted
47561 * (it would suffice to protect this particular object only, though).
47562 *
47563 * Note: a non-checked variant would be nice but is a bit tricky to
47564 * implement for the array abandonment process. It's easy for
47565 * everything else.
47566 *
47567 * Note: because we need to potentially resize the valstack (as part
47568 * of abandoning the array part), any tval pointers to the valstack
47569 * will become invalid after this call.
47570 */
47571
47574 duk_hobject *obj,
47575 duk_uint32_t new_e_size,
47576 duk_uint32_t new_a_size,
47577 duk_uint32_t new_h_size,
47578 duk_bool_t abandon_array) {
47579 duk_context *ctx = (duk_context *) thr;
47580#ifdef DUK_USE_MARK_AND_SWEEP
47581 duk_small_uint_t prev_mark_and_sweep_base_flags;
47582#endif
47583 duk_uint32_t new_alloc_size;
47584 duk_uint32_t new_e_size_adjusted;
47585 duk_uint8_t *new_p;
47586 duk_hstring **new_e_k;
47587 duk_propvalue *new_e_pv;
47588 duk_uint8_t *new_e_f;
47589 duk_tval *new_a;
47590 duk_uint32_t *new_h;
47591 duk_uint32_t new_e_next;
47593
47594 DUK_ASSERT(thr != NULL);
47595 DUK_ASSERT(ctx != NULL);
47596 DUK_ASSERT(obj != NULL);
47597 DUK_ASSERT(!abandon_array || new_a_size == 0); /* if abandon_array, new_a_size must be 0 */
47598 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
47599 DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size); /* required to guarantee success of rehashing,
47600 * intentionally use unadjusted new_e_size
47601 */
47604
47605 /*
47606 * Pre resize assertions.
47607 */
47608
47609#ifdef DUK_USE_ASSERTIONS
47610 /* XXX: pre-checks (such as no duplicate keys) */
47611#endif
47612
47613 /*
47614 * For property layout 1, tweak e_size to ensure that the whole entry
47615 * part (key + val + flags) is a suitable multiple for alignment
47616 * (platform specific).
47617 *
47618 * Property layout 2 does not require this tweaking and is preferred
47619 * on low RAM platforms requiring alignment.
47620 */
47621
47622#if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
47623 DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
47624 new_e_size_adjusted = new_e_size;
47625#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
47626 DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
47627 new_e_size_adjusted = new_e_size;
47628#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
47629 new_e_size_adjusted = (new_e_size + DUK_HOBJECT_ALIGN_TARGET - 1) & (~(DUK_HOBJECT_ALIGN_TARGET - 1));
47630 DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
47631 (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
47632 DUK_ASSERT(new_e_size_adjusted >= new_e_size);
47633#else
47634#error invalid hobject layout defines
47635#endif
47636
47637 /*
47638 * Debug logging after adjustment.
47639 */
47640
47641 DUK_DDD(DUK_DDDPRINT("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 "
47642 "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
47643 (void *) obj,
47647 (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
47648 (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
47649 (long) DUK_HOBJECT_GET_ESIZE(obj),
47650 (long) DUK_HOBJECT_GET_ENEXT(obj),
47651 (long) DUK_HOBJECT_GET_ASIZE(obj),
47652 (long) DUK_HOBJECT_GET_HSIZE(obj),
47653 (long) new_e_size_adjusted,
47654 (long) new_a_size,
47655 (long) new_h_size,
47656 (long) abandon_array,
47657 (long) new_e_size));
47658
47659 /*
47660 * Property count check. This is the only point where we ensure that
47661 * we don't get more (allocated) property space that we can handle.
47662 * There aren't hard limits as such, but some algorithms fail (e.g.
47663 * finding next higher prime, selecting hash part size) if we get too
47664 * close to the 4G property limit.
47665 *
47666 * Since this works based on allocation size (not actually used size),
47667 * the limit is a bit approximate but good enough in practice.
47668 */
47669
47670 if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
47672 }
47673
47674 /*
47675 * Compute new alloc size and alloc new area.
47676 *
47677 * The new area is allocated as a dynamic buffer and placed into the
47678 * valstack for reachability. The actual buffer is then detached at
47679 * the end.
47680 *
47681 * Note: heap_mark_and_sweep_base_flags are altered here to ensure
47682 * no-one touches this object while we're resizing and rehashing it.
47683 * The flags must be reset on every exit path after it. Finalizers
47684 * and compaction is prevented currently for all objects while it
47685 * would be enough to restrict it only for the current object.
47686 */
47687
47688#ifdef DUK_USE_MARK_AND_SWEEP
47689 prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
47691 DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */
47692 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact the current object */
47693#endif
47694
47695 new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
47696 DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
47697 if (new_alloc_size == 0) {
47698 /* for zero size, don't push anything on valstack */
47699 DUK_ASSERT(new_e_size_adjusted == 0);
47700 DUK_ASSERT(new_a_size == 0);
47701 DUK_ASSERT(new_h_size == 0);
47702 new_p = NULL;
47703 } else {
47704 /* This may trigger mark-and-sweep with arbitrary side effects,
47705 * including an attempted resize of the object we're resizing,
47706 * executing a finalizer which may add or remove properties of
47707 * the object we're resizing etc.
47708 */
47709
47710 /* Note: buffer is dynamic so that we can 'steal' the actual
47711 * allocation later.
47712 */
47713
47714 new_p = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, new_alloc_size); /* errors out if out of memory */
47715 DUK_ASSERT(new_p != NULL); /* since new_alloc_size > 0 */
47716 }
47717
47718 /* Set up pointers to the new property area: this is hidden behind a macro
47719 * because it is memory layout specific.
47720 */
47721 DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
47722 new_e_size_adjusted, new_a_size, new_h_size);
47723 DUK_UNREF(new_h); /* happens when hash part dropped */
47724 new_e_next = 0;
47725
47726 /* if new_p == NULL, all of these pointers are NULL */
47727 DUK_ASSERT((new_p != NULL) ||
47728 (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
47729 new_a == NULL && new_h == NULL));
47730
47731 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",
47732 (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
47733 (void *) new_a, (void *) new_h));
47734
47735 /*
47736 * Migrate array to start of entries if requested.
47737 *
47738 * Note: from an enumeration perspective the order of entry keys matters.
47739 * Array keys should appear wherever they appeared before the array abandon
47740 * operation.
47741 */
47742
47743 if (abandon_array) {
47744 /*
47745 * Note: assuming new_a_size == 0, and that entry part contains
47746 * no conflicting keys, refcounts do not need to be adjusted for
47747 * the values, as they remain exactly the same.
47748 *
47749 * The keys, however, need to be interned, incref'd, and be
47750 * reachable for GC. Any intern attempt may trigger a GC and
47751 * claim any non-reachable strings, so every key must be reachable
47752 * at all times.
47753 *
47754 * A longjmp must not occur here, as the new_p allocation would
47755 * be freed without these keys being decref'd, hence the messy
47756 * decref handling if intern fails.
47757 */
47758 DUK_ASSERT(new_a_size == 0);
47759
47760 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
47761 duk_tval *tv1;
47762 duk_tval *tv2;
47763 duk_hstring *key;
47764
47766
47767 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
47768 if (DUK_TVAL_IS_UNUSED(tv1)) {
47769 continue;
47770 }
47771
47772 DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
47773 new_e_pv != NULL && new_e_f != NULL);
47774
47775 /*
47776 * Intern key via the valstack to ensure reachability behaves
47777 * properly. We must avoid longjmp's here so use non-checked
47778 * primitives.
47779 *
47780 * Note: duk_check_stack() potentially reallocs the valstack,
47781 * invalidating any duk_tval pointers to valstack. Callers
47782 * must be careful.
47783 */
47784
47785 /* never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which is generous */
47786 if (!duk_check_stack(ctx, 1)) {
47787 goto abandon_error;
47788 }
47790 key = duk_heap_string_intern_u32(thr->heap, i);
47791 if (!key) {
47792 goto abandon_error;
47793 }
47794 duk_push_hstring(ctx, key); /* keep key reachable for GC etc; guaranteed not to fail */
47795
47796 /* key is now reachable in the valstack */
47797
47798 DUK_HSTRING_INCREF(thr, key); /* second incref for the entry reference */
47799 new_e_k[new_e_next] = key;
47800 tv2 = &new_e_pv[new_e_next].v; /* array entries are all plain values */
47801 DUK_TVAL_SET_TVAL(tv2, tv1);
47802 new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
47805 new_e_next++;
47806
47807 /* Note: new_e_next matches pushed temp key count, and nothing can
47808 * fail above between the push and this point.
47809 */
47810 }
47811
47812 DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
47813 duk_pop_n(ctx, new_e_next);
47814 }
47815
47816 /*
47817 * Copy keys and values in the entry part (compacting them at the same time).
47818 */
47819
47820 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
47821 duk_hstring *key;
47822
47824
47825 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
47826 if (!key) {
47827 continue;
47828 }
47829
47830 DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
47831 new_e_pv != NULL && new_e_f != NULL);
47832
47833 new_e_k[new_e_next] = key;
47834 new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
47835 new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
47836 new_e_next++;
47837 }
47838 /* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
47839
47840 /*
47841 * Copy array elements to new array part.
47842 */
47843
47844 if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
47845 /* copy existing entries as is */
47846 DUK_ASSERT(new_p != NULL && new_a != NULL);
47847 if (DUK_HOBJECT_GET_ASIZE(obj) > 0) {
47848 /* Avoid zero copy with an invalid pointer. If obj->p is NULL,
47849 * the 'new_a' pointer will be invalid which is not allowed even
47850 * when copy size is zero.
47851 */
47854 DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj));
47855 }
47856
47857 /* fill new entries with -unused- (required, gc reachable) */
47858 for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
47859 duk_tval *tv = &new_a[i];
47861 }
47862 } else {
47863#ifdef DUK_USE_ASSERTIONS
47864 /* caller must have decref'd values above new_a_size (if that is necessary) */
47865 if (!abandon_array) {
47866 for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
47867 duk_tval *tv;
47868 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
47869
47870 /* current assertion is quite strong: decref's and set to unused */
47872 }
47873 }
47874#endif
47875 if (new_a_size > 0) {
47876 /* Avoid zero copy with an invalid pointer. If obj->p is NULL,
47877 * the 'new_a' pointer will be invalid which is not allowed even
47878 * when copy size is zero.
47879 */
47881 DUK_ASSERT(new_a_size > 0);
47882 DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * new_a_size);
47883 }
47884 }
47885
47886 /*
47887 * Rebuild the hash part always from scratch (guaranteed to finish).
47888 *
47889 * Any resize of hash part requires rehashing. In addition, by rehashing
47890 * get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
47891 * to ensuring the hash part never fills up.
47892 */
47893
47894#if defined(DUK_USE_HOBJECT_HASH_PART)
47895 if (DUK_UNLIKELY(new_h_size > 0)) {
47896 DUK_ASSERT(new_h != NULL);
47897
47898 /* fill new_h with u32 0xff = UNUSED */
47900 DUK_ASSERT(new_h_size > 0);
47901 DUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
47902
47903 DUK_ASSERT(new_e_next <= new_h_size); /* equality not actually possible */
47904 for (i = 0; i < new_e_next; i++) {
47905 duk_hstring *key = new_e_k[i];
47906 duk_uint32_t j, step;
47907
47908 DUK_ASSERT(key != NULL);
47909 j = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size);
47911
47912 for (;;) {
47913 DUK_ASSERT(new_h[j] != DUK__HASH_DELETED); /* should never happen */
47914 if (new_h[j] == DUK__HASH_UNUSED) {
47915 DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
47916 new_h[j] = i;
47917 break;
47918 }
47919 DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
47920 j = (j + step) % new_h_size;
47921
47922 /* guaranteed to finish */
47923 DUK_ASSERT(j != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size));
47924 }
47925 }
47926 } else {
47927 DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
47928 }
47929#endif /* DUK_USE_HOBJECT_HASH_PART */
47930
47931 /*
47932 * Nice debug log.
47933 */
47934
47935 DUK_DD(DUK_DDPRINT("resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to "
47936 "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
47937 (void *) obj,
47941 (long) new_alloc_size,
47942 (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
47943 (long) DUK_HOBJECT_GET_ESIZE(obj),
47944 (long) DUK_HOBJECT_GET_ENEXT(obj),
47945 (long) DUK_HOBJECT_GET_ASIZE(obj),
47946 (long) DUK_HOBJECT_GET_HSIZE(obj),
47947 (void *) new_p,
47948 (long) new_e_size_adjusted,
47949 (long) new_e_next,
47950 (long) new_a_size,
47951 (long) new_h_size,
47952 (long) abandon_array,
47953 (long) new_e_size));
47954
47955 /*
47956 * All done, switch properties ('p') allocation to new one.
47957 */
47958
47959 DUK_FREE(thr->heap, DUK_HOBJECT_GET_PROPS(thr->heap, obj)); /* NULL obj->p is OK */
47960 DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
47961 DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
47962 DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
47963 DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
47964 DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
47965
47966 if (new_p) {
47967 /*
47968 * Detach actual buffer from dynamic buffer in valstack, and
47969 * pop it from the stack.
47970 *
47971 * XXX: the buffer object is certainly not reachable at this point,
47972 * so it would be nice to free it forcibly even with only
47973 * mark-and-sweep enabled. Not a big issue though.
47974 */
47975 (void) duk_steal_buffer(ctx, -1, NULL);
47976 duk_pop(ctx);
47977 } else {
47978 DUK_ASSERT(new_alloc_size == 0);
47979 /* no need to pop, nothing was pushed */
47980 }
47981
47982 /* clear array part flag only after switching */
47983 if (abandon_array) {
47985 }
47986
47987 DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
47988
47989#ifdef DUK_USE_MARK_AND_SWEEP
47990 thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
47991#endif
47992
47993 /*
47994 * Post resize assertions.
47995 */
47996
47997#ifdef DUK_USE_ASSERTIONS
47998 /* XXX: post-checks (such as no duplicate keys) */
47999#endif
48000 return;
48001
48002 /*
48003 * Abandon array failed, need to decref keys already inserted
48004 * into the beginning of new_e_k before unwinding valstack.
48005 */
48006
48007 abandon_error:
48008 DUK_D(DUK_DPRINT("hobject resize failed during abandon array, decref keys"));
48009 i = new_e_next;
48010 while (i > 0) {
48011 i--;
48012 DUK_ASSERT(new_e_k != NULL);
48013 DUK_ASSERT(new_e_k[i] != NULL);
48014 DUK_HSTRING_DECREF(thr, new_e_k[i]); /* side effects */
48015 }
48016
48017#ifdef DUK_USE_MARK_AND_SWEEP
48018 thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
48019#endif
48020
48022}
48023
48024/*
48025 * Helpers to resize properties allocation on specific needs.
48026 */
48027
48028/* Grow entry part allocation for one additional entry. */
48030 duk_uint32_t old_e_used; /* actually used, non-NULL entries */
48031 duk_uint32_t new_e_size;
48032 duk_uint32_t new_a_size;
48033 duk_uint32_t new_h_size;
48034
48035 DUK_ASSERT(thr != NULL);
48036 DUK_ASSERT(obj != NULL);
48037
48038 /* Duktape 0.11.0 and prior tried to optimize the resize by not
48039 * counting the number of actually used keys prior to the resize.
48040 * This worked mostly well but also caused weird leak-like behavior
48041 * as in: test-bug-object-prop-alloc-unbounded.js. So, now we count
48042 * the keys explicitly to compute the new entry part size.
48043 */
48044
48045 old_e_used = duk__count_used_e_keys(thr, obj);
48046 new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
48047#if defined(DUK_USE_HOBJECT_HASH_PART)
48048 new_h_size = duk__get_default_h_size(new_e_size);
48049#else
48050 new_h_size = 0;
48051#endif
48052 new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
48053 DUK_ASSERT(new_e_size >= old_e_used + 1); /* duk__get_min_grow_e() is always >= 1 */
48054
48055 duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
48056}
48057
48058/* Grow array part for a new highest array index. */
48059DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
48060 duk_uint32_t new_e_size;
48061 duk_uint32_t new_a_size;
48062 duk_uint32_t new_h_size;
48063
48064 DUK_ASSERT(thr != NULL);
48065 DUK_ASSERT(obj != NULL);
48066 DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
48067
48068 /* minimum new length is highest_arr_idx + 1 */
48069
48070 new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
48071 new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
48072 new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
48073 DUK_ASSERT(new_a_size >= highest_arr_idx + 1); /* duk__get_min_grow_a() is always >= 1 */
48074
48075 duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
48076}
48077
48078/* Abandon array part, moving array entries into entries part.
48079 * This requires a props resize, which is a heavy operation.
48080 * We also compact the entries part while we're at it, although
48081 * this is not strictly required.
48082 */
48084 duk_uint32_t new_e_size;
48085 duk_uint32_t new_a_size;
48086 duk_uint32_t new_h_size;
48087 duk_uint32_t e_used; /* actually used, non-NULL keys */
48088 duk_uint32_t a_used;
48089 duk_uint32_t a_size;
48090
48091 DUK_ASSERT(thr != NULL);
48092 DUK_ASSERT(obj != NULL);
48093
48094 e_used = duk__count_used_e_keys(thr, obj);
48095 duk__compute_a_stats(thr, obj, &a_used, &a_size);
48096
48097 /*
48098 * Must guarantee all actually used array entries will fit into
48099 * new entry part. Add one growth step to ensure we don't run out
48100 * of space right away.
48101 */
48102
48103 new_e_size = e_used + a_used;
48104 new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
48105 new_a_size = 0;
48106#if defined(DUK_USE_HOBJECT_HASH_PART)
48107 new_h_size = duk__get_default_h_size(new_e_size);
48108#else
48109 new_h_size = 0;
48110#endif
48111
48112 DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
48113 "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
48114 "resize to e_size=%ld, a_size=%ld, h_size=%ld",
48115 (void *) obj, (long) e_used, (long) a_used, (long) a_size,
48116 (long) new_e_size, (long) new_a_size, (long) new_h_size));
48117
48118 duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
48119}
48120
48121/*
48122 * Compact an object. Minimizes allocation size for objects which are
48123 * not likely to be extended. This is useful for internal and non-
48124 * extensible objects, but can also be called for non-extensible objects.
48125 * May abandon the array part if it is computed to be too sparse.
48126 *
48127 * This call is relatively expensive, as it needs to scan both the
48128 * entries and the array part.
48129 *
48130 * The call may fail due to allocation error.
48131 */
48132
48134 duk_uint32_t e_size; /* currently used -> new size */
48135 duk_uint32_t a_size; /* currently required */
48136 duk_uint32_t a_used; /* actually used */
48137 duk_uint32_t h_size;
48138 duk_bool_t abandon_array;
48139
48140 DUK_ASSERT(thr != NULL);
48141 DUK_ASSERT(obj != NULL);
48142
48143#if defined(DUK_USE_ROM_OBJECTS)
48145 DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
48146 return;
48147 }
48148#endif
48149
48150 e_size = duk__count_used_e_keys(thr, obj);
48151 duk__compute_a_stats(thr, obj, &a_used, &a_size);
48152
48153 DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
48154 "resized array density would be: %ld/%ld = %lf",
48155 (long) e_size, (long) a_used, (long) a_size,
48156 (long) a_used, (long) a_size,
48157 (double) a_used / (double) a_size));
48158
48159 if (duk__abandon_array_density_check(a_used, a_size)) {
48160 DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
48161 (long) a_used, (long) a_size));
48162 abandon_array = 1;
48163 e_size += a_used;
48164 a_size = 0;
48165 } else {
48166 DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
48167 abandon_array = 0;
48168 }
48169
48170#if defined(DUK_USE_HOBJECT_HASH_PART)
48171 if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
48172 h_size = duk__get_default_h_size(e_size);
48173 } else {
48174 h_size = 0;
48175 }
48176#else
48177 h_size = 0;
48178#endif
48180 DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
48181 (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
48182
48183 duk__realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
48184}
48185
48186/*
48187 * Find an existing key from entry part either by linear scan or by
48188 * using the hash index (if it exists).
48189 *
48190 * Sets entry index (and possibly the hash index) to output variables,
48191 * which allows the caller to update the entry and hash entries in-place.
48192 * If entry is not found, both values are set to -1. If entry is found
48193 * but there is no hash part, h_idx is set to -1.
48194 */
48195
48197 DUK_ASSERT(obj != NULL);
48198 DUK_ASSERT(key != NULL);
48199 DUK_ASSERT(e_idx != NULL);
48200 DUK_ASSERT(h_idx != NULL);
48201 DUK_UNREF(heap);
48202
48203 if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
48204 {
48205 /* Linear scan: more likely because most objects are small.
48206 * This is an important fast path.
48207 *
48208 * XXX: this might be worth inlining for property lookups.
48209 */
48212 duk_hstring **h_keys_base;
48213 DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
48214
48215 h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
48216 n = DUK_HOBJECT_GET_ENEXT(obj);
48217 for (i = 0; i < n; i++) {
48218 if (h_keys_base[i] == key) {
48219 *e_idx = i;
48220 *h_idx = -1;
48221 return;
48222 }
48223 }
48224 }
48225#if defined(DUK_USE_HOBJECT_HASH_PART)
48226 else
48227 {
48228 /* hash lookup */
48229 duk_uint32_t n;
48230 duk_uint32_t i, step;
48231 duk_uint32_t *h_base;
48232
48233 DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
48234
48235 h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
48236 n = DUK_HOBJECT_GET_HSIZE(obj);
48239
48240 for (;;) {
48241 duk_uint32_t t;
48242
48243 DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
48245 t = h_base[i];
48247 (t < DUK_HOBJECT_GET_ESIZE(obj))); /* t >= 0 always true, unsigned */
48248
48249 if (t == DUK__HASH_UNUSED) {
48250 break;
48251 } else if (t == DUK__HASH_DELETED) {
48252 DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
48253 (long) i, (long) t));
48254 } else {
48256 if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
48257 DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
48258 (long) i, (long) t, (void *) key));
48259 *e_idx = t;
48260 *h_idx = i;
48261 return;
48262 }
48263 DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
48264 (long) i, (long) t));
48265 }
48266 i = (i + step) % n;
48267
48268 /* guaranteed to finish, as hash is never full */
48269 DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n));
48270 }
48271 }
48272#endif /* DUK_USE_HOBJECT_HASH_PART */
48273
48274 /* not found */
48275 *e_idx = -1;
48276 *h_idx = -1;
48277}
48278
48279/* For internal use: get non-accessor entry value */
48281 duk_int_t e_idx;
48282 duk_int_t h_idx;
48283
48284 DUK_ASSERT(obj != NULL);
48285 DUK_ASSERT(key != NULL);
48286 DUK_UNREF(heap);
48287
48288 duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
48289 if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
48290 return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
48291 } else {
48292 return NULL;
48293 }
48294}
48295
48296/* For internal use: get non-accessor entry value and attributes */
48298 duk_int_t e_idx;
48299 duk_int_t h_idx;
48301 DUK_ASSERT(obj != NULL);
48302 DUK_ASSERT(key != NULL);
48303 DUK_ASSERT(out_attrs != NULL);
48304 DUK_UNREF(heap);
48305
48306 duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
48307 if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
48308 *out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
48309 return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
48310 } else {
48311 *out_attrs = 0;
48312 return NULL;
48313 }
48314}
48315
48316/* For internal use: get array part value */
48318 duk_tval *tv;
48319
48320 DUK_ASSERT(obj != NULL);
48321 DUK_UNREF(heap);
48322
48323 if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
48324 return NULL;
48326 if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
48327 return NULL;
48328 }
48329 tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
48330 return tv;
48331}
48332
48333/*
48334 * Allocate and initialize a new entry, resizing the properties allocation
48335 * if necessary. Returns entry index (e_idx) or throws an error if alloc fails.
48336 *
48337 * Sets the key of the entry (increasing the key's refcount), and updates
48338 * the hash part if it exists. Caller must set value and flags, and update
48339 * the entry value refcount. A decref for the previous value is not necessary.
48340 */
48341
48343 duk_uint32_t idx;
48344
48345 DUK_ASSERT(thr != NULL);
48346 DUK_ASSERT(obj != NULL);
48347 DUK_ASSERT(key != NULL);
48349
48350#ifdef DUK_USE_ASSERTIONS
48351 /* key must not already exist in entry part */
48352 {
48354 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
48355 DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
48356 }
48357 }
48358#endif
48359
48361 /* only need to guarantee 1 more slot, but allocation growth is in chunks */
48362 DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
48364 }
48366 idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
48367
48368 /* previous value is assumed to be garbage, so don't touch it */
48369 DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
48370 DUK_HSTRING_INCREF(thr, key);
48371
48372#if defined(DUK_USE_HOBJECT_HASH_PART)
48373 if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
48374 duk_uint32_t n;
48375 duk_uint32_t i, step;
48376 duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
48377
48378 n = DUK_HOBJECT_GET_HSIZE(obj);
48381
48382 for (;;) {
48383 duk_uint32_t t = h_base[i];
48384 if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
48385 DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() inserted key into hash part, %ld -> %ld",
48386 (long) i, (long) idx));
48387 DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
48389 DUK_ASSERT_DISABLE(idx >= 0);
48391 h_base[i] = idx;
48392 break;
48393 }
48394 DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() miss %ld", (long) i));
48395 i = (i + step) % n;
48396
48397 /* guaranteed to find an empty slot */
48399 }
48400 }
48401#endif /* DUK_USE_HOBJECT_HASH_PART */
48402
48403 /* Note: we could return the hash index here too, but it's not
48404 * needed right now.
48405 */
48406
48407 DUK_ASSERT_DISABLE(idx >= 0);
48410 return idx;
48411}
48412
48413/*
48414 * Object internal value
48415 *
48416 * Returned value is guaranteed to be reachable / incref'd, caller does not need
48417 * to incref OR decref. No proxies or accessors are invoked, no prototype walk.
48418 */
48419
48421 duk_int_t e_idx;
48423
48424 DUK_ASSERT(heap != NULL);
48425 DUK_ASSERT(obj != NULL);
48426 DUK_ASSERT(tv_out != NULL);
48427
48428 /* always in entry part, no need to look up parents etc */
48429 duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx);
48430 if (e_idx >= 0) {
48431 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
48432 DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
48433 return 1;
48434 }
48435 DUK_TVAL_SET_UNDEFINED(tv_out);
48436 return 0;
48437}
48438
48440 duk_tval tv;
48441
48442 DUK_ASSERT(heap != NULL);
48443 DUK_ASSERT(obj != NULL);
48444
48445 /* This is not strictly necessary, but avoids compiler warnings; e.g.
48446 * gcc won't reliably detect that no uninitialized data is read below.
48447 */
48448 DUK_MEMZERO((void *) &tv, sizeof(duk_tval));
48449
48450 if (duk_hobject_get_internal_value(heap, obj, &tv)) {
48451 duk_hstring *h;
48453 h = DUK_TVAL_GET_STRING(&tv);
48454 return h;
48455 }
48456
48457 return NULL;
48458}
48459
48460/*
48461 * Arguments handling helpers (argument map mainly).
48462 *
48463 * An arguments object has exotic behavior for some numeric indices.
48464 * Accesses may translate to identifier operations which may have
48465 * arbitrary side effects (potentially invalidating any duk_tval
48466 * pointers).
48467 */
48468
48469/* Lookup 'key' from arguments internal 'map', perform a variable lookup
48470 * if mapped, and leave the result on top of stack (and return non-zero).
48471 * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
48472 */
48475 duk_hobject *obj,
48476 duk_hstring *key,
48477 duk_propdesc *temp_desc,
48478 duk_hobject **out_map,
48479 duk_hobject **out_varenv) {
48480 duk_context *ctx = (duk_context *) thr;
48481 duk_hobject *map;
48482 duk_hobject *varenv;
48483 duk_bool_t rc;
48484
48486
48487 DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
48488 "(obj -> %!O, key -> %!O)",
48489 (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
48490 (duk_heaphdr *) obj, (duk_heaphdr *) key));
48491
48493 DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
48494 return 0;
48495 }
48496
48497 map = duk_require_hobject(ctx, -1);
48498 DUK_ASSERT(map != NULL);
48499 duk_pop(ctx); /* map is reachable through obj */
48500
48501 if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
48502 DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
48503 return 0;
48504 }
48505
48506 /* [... varname] */
48507 DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
48508 (duk_tval *) duk_get_tval(ctx, -1)));
48509 DUK_ASSERT(duk_is_string(ctx, -1)); /* guaranteed when building arguments */
48510
48511 /* get varenv for varname (callee's declarative lexical environment) */
48513 DUK_UNREF(rc);
48514 DUK_ASSERT(rc != 0); /* arguments MUST have an initialized lexical environment reference */
48515 varenv = duk_require_hobject(ctx, -1);
48516 DUK_ASSERT(varenv != NULL);
48517 duk_pop(ctx); /* varenv remains reachable through 'obj' */
48518
48519 DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
48520
48521 /* success: leave varname in stack */
48522 *out_map = map;
48523 *out_varenv = varenv;
48524 return 1; /* [... varname] */
48525}
48526
48527/* Lookup 'key' from arguments internal 'map', and leave replacement value
48528 * on stack top if mapped (and return non-zero).
48529 * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
48530 */
48532 duk_context *ctx = (duk_context *) thr;
48533 duk_hobject *map;
48534 duk_hobject *varenv;
48535 duk_hstring *varname;
48536
48538
48539 if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
48540 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
48541 return 0;
48542 }
48543
48544 /* [... varname] */
48545
48546 varname = duk_require_hstring(ctx, -1);
48547 DUK_ASSERT(varname != NULL);
48548 duk_pop(ctx); /* varname is still reachable */
48549
48550 DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
48551 "key=%!O, varname=%!O",
48553 (duk_heaphdr *) varname));
48554
48555 (void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
48556
48557 /* [... value this_binding] */
48558
48559 duk_pop(ctx);
48560
48561 /* leave result on stack top */
48562 return 1;
48563}
48564
48565/* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
48566 * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
48567 * Assumes stack top contains 'put' value (which is NOT popped).
48568 */
48570 duk_context *ctx = (duk_context *) thr;
48571 duk_hobject *map;
48572 duk_hobject *varenv;
48573 duk_hstring *varname;
48574
48576
48577 if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
48578 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
48579 return;
48580 }
48581
48582 /* [... put_value varname] */
48583
48584 varname = duk_require_hstring(ctx, -1);
48585 DUK_ASSERT(varname != NULL);
48586 duk_pop(ctx); /* varname is still reachable */
48587
48588 DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
48589 "key=%!O, varname=%!O, value=%!T",
48590 (duk_heaphdr *) key,
48591 (duk_heaphdr *) varname,
48592 (duk_tval *) duk_require_tval(ctx, -1)));
48593
48594 /* [... put_value] */
48595
48597 * Note: although arguments object variable mappings are only established
48598 * for non-strict functions (and a call to a non-strict function created
48599 * the arguments object in question), an inner strict function may be doing
48600 * the actual property write. Hence the throw_flag applied here comes from
48601 * the property write call.
48602 */
48603
48604 duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, -1), throw_flag);
48605
48606 /* [... put_value] */
48607}
48608
48609/* Lookup 'key' from arguments internal 'map', delete mapping if found.
48610 * Used in E5 Section 10.6 algorithm for [[Delete]]. Note that the
48611 * variable/argument itself (where the map points) is not deleted.
48612 */
48614 duk_context *ctx = (duk_context *) thr;
48615 duk_hobject *map;
48616
48618
48620 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
48621 return;
48622 }
48623
48624 map = duk_require_hobject(ctx, -1);
48625 DUK_ASSERT(map != NULL);
48626 duk_pop(ctx); /* map is reachable through obj */
48627
48628 DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
48629 (duk_heaphdr *) key));
48630
48631 /* Note: no recursion issue, we can trust 'map' to behave */
48633 DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
48634 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
48635 DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
48636}
48637
48638/*
48639 * Ecmascript compliant [[GetOwnProperty]](P), for internal use only.
48640 *
48641 * If property is found:
48642 * - Fills descriptor fields to 'out_desc'
48643 * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
48644 * property onto the stack ('undefined' for accessor properties).
48645 * - Returns non-zero
48646 *
48647 * If property is not found:
48648 * - 'out_desc' is left in untouched state (possibly garbage)
48649 * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
48650 * set)
48651 * - Returns zero
48652 *
48653 * Notes:
48654 *
48655 * - Getting a property descriptor may cause an allocation (and hence
48656 * GC) to take place, hence reachability and refcount of all related
48657 * values matter. Reallocation of value stack, properties, etc may
48658 * invalidate many duk_tval pointers (concretely, those which reside
48659 * in memory areas subject to reallocation). However, heap object
48660 * pointers are never affected (heap objects have stable pointers).
48661 *
48662 * - The value of a plain property is always reachable and has a non-zero
48663 * reference count.
48664 *
48665 * - The value of a virtual property is not necessarily reachable from
48666 * elsewhere and may have a refcount of zero. Hence we push it onto
48667 * the valstack for the caller, which ensures it remains reachable
48668 * while it is needed.
48669 *
48670 * - There are no virtual accessor properties. Hence, all getters and
48671 * setters are always related to concretely stored properties, which
48672 * ensures that the get/set functions in the resulting descriptor are
48673 * reachable and have non-zero refcounts. Should there be virtual
48674 * accessor properties later, this would need to change.
48675 */
48676
48677DUK_LOCAL 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) {
48678 duk_context *ctx = (duk_context *) thr;
48679 duk_tval *tv;
48680
48681 DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
48682 "arr_idx=%ld (obj -> %!O, key -> %!O)",
48683 (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
48684 (long) flags, (long) arr_idx,
48685 (duk_heaphdr *) obj, (duk_heaphdr *) key));
48686
48687 DUK_ASSERT(ctx != NULL);
48688 DUK_ASSERT(thr != NULL);
48689 DUK_ASSERT(thr->heap != NULL);
48690 DUK_ASSERT(obj != NULL);
48691 DUK_ASSERT(key != NULL);
48692 DUK_ASSERT(out_desc != NULL);
48694
48695 /* XXX: optimize this filling behavior later */
48696 out_desc->flags = 0;
48697 out_desc->get = NULL;
48698 out_desc->set = NULL;
48699 out_desc->e_idx = -1;
48700 out_desc->h_idx = -1;
48701 out_desc->a_idx = -1;
48702
48703 /*
48704 * Array part
48705 */
48706
48707 if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
48708 if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
48709 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
48710 if (!DUK_TVAL_IS_UNUSED(tv)) {
48711 DUK_DDD(DUK_DDDPRINT("-> found in array part"));
48712 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48713 duk_push_tval(ctx, tv);
48714 }
48715 /* implicit attributes */
48716 out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
48719 out_desc->a_idx = arr_idx;
48720 goto prop_found;
48721 }
48722 }
48723 /* assume array part is comprehensive (contains all array indexed elements
48724 * or none of them); hence no need to check the entries part here.
48725 */
48726 DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property (has array part, "
48727 "should be there if present)"));
48728 goto prop_not_found_concrete;
48729 }
48730
48731 /*
48732 * Entries part
48733 */
48734
48735 duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx);
48736 if (out_desc->e_idx >= 0) {
48737 duk_int_t e_idx = out_desc->e_idx;
48738 out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
48739 if (out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR) {
48740 DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
48741 out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
48742 out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
48743 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48744 /* a dummy undefined value is pushed to make valstack
48745 * behavior uniform for caller
48746 */
48747 duk_push_undefined(ctx);
48748 }
48749 } else {
48750 DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
48751 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
48752 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48753 duk_push_tval(ctx, tv);
48754 }
48755 }
48756 goto prop_found;
48757 }
48758
48759 /*
48760 * Not found as a concrete property, check whether a String object
48761 * virtual property matches.
48762 */
48763
48764 prop_not_found_concrete:
48765
48767 DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
48768 (duk_heaphdr *) key, (long) arr_idx));
48769
48770 if (arr_idx != DUK__NO_ARRAY_INDEX) {
48771 duk_hstring *h_val;
48772
48773 DUK_DDD(DUK_DDDPRINT("array index exists"));
48774
48776 DUK_ASSERT(h_val);
48777 if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
48778 DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
48779 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48780 duk_push_hstring(ctx, h_val);
48781 duk_substring(ctx, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
48782 }
48783 out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE | /* E5 Section 15.5.5.2 */
48785
48787 return 1; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
48788 } else {
48789 /* index is above internal string length -> property is fully normal */
48790 DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
48791 }
48792 } else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
48793 duk_hstring *h_val;
48794
48795 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
48796
48798 DUK_ASSERT(h_val != NULL);
48799 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48801 }
48802 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* E5 Section 15.5.5.1 */
48803
48805 return 1; /* cannot be arguments exotic */
48806 }
48807 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
48808 duk_hbufferobject *h_bufobj;
48809 duk_uint_t byte_off;
48810 duk_small_uint_t elem_size;
48811
48812 h_bufobj = (duk_hbufferobject *) obj;
48814 DUK_DDD(DUK_DDDPRINT("bufferobject property get for key: %!O, arr_idx: %ld",
48815 (duk_heaphdr *) key, (long) arr_idx));
48816
48817 if (arr_idx != DUK__NO_ARRAY_INDEX) {
48818 DUK_DDD(DUK_DDDPRINT("array index exists"));
48819
48820 /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
48821 * length downshift won't.
48822 */
48823 if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
48824 byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
48825 elem_size = 1 << h_bufobj->shift;
48826 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48827 duk_uint8_t *data;
48828
48829 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
48830 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
48831 duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
48832 } else {
48833 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
48834 duk_push_uint(ctx, 0);
48835 }
48836 }
48837 out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
48840
48842 return 1; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
48843 } else {
48844 /* index is above internal buffer length -> property is fully normal */
48845 DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
48846 }
48847 } else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
48848 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
48849
48850 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48851 /* Length in elements: take into account shift, but
48852 * intentionally don't check the underlying buffer here.
48853 */
48854 duk_push_uint(ctx, h_bufobj->length >> h_bufobj->shift);
48855 }
48856 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48857
48859 return 1; /* cannot be arguments exotic */
48860 } else if (key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
48861 /* If neutered must return 0; length is zeroed during
48862 * neutering.
48863 */
48864 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48865 duk_push_uint(ctx, h_bufobj->length);
48866 }
48867 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48868 return 1; /* cannot be arguments exotic */
48869 } else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
48870 /* If neutered must return 0; offset is zeroed during
48871 * neutering.
48872 */
48873 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48874 duk_push_uint(ctx, h_bufobj->offset);
48875 }
48876 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48877 return 1; /* cannot be arguments exotic */
48878 } else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
48879 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48880 duk_push_uint(ctx, 1 << h_bufobj->shift);
48881 }
48882 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48883 return 1; /* cannot be arguments exotic */
48884 }
48885 } else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(obj)) {
48886 DUK_DDD(DUK_DDDPRINT("duktape/c object exotic property get for key: %!O, arr_idx: %ld",
48887 (duk_heaphdr *) key, (long) arr_idx));
48888
48889 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
48890 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
48891
48892 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48893 duk_int16_t func_nargs = ((duk_hnativefunction *) obj)->nargs;
48894 duk_push_int(ctx, func_nargs == DUK_HNATIVEFUNCTION_NARGS_VARARGS ? 0 : func_nargs);
48895 }
48896 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* not enumerable */
48897
48899 return 1; /* cannot be arguments exotic */
48900 }
48901 }
48902
48903 /* Array properties have exotic behavior but they are concrete,
48904 * so no special handling here.
48905 *
48906 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
48907 * is only relevant as a post-check implemented below; hence no
48908 * check here.
48909 */
48910
48911 /*
48912 * Not found as concrete or virtual
48913 */
48914
48915 DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
48916 return 0;
48917
48918 /*
48919 * Found
48920 *
48921 * Arguments object has exotic post-processing, see E5 Section 10.6,
48922 * description of [[GetOwnProperty]] variant for arguments.
48923 */
48924
48925 prop_found:
48926 DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
48927
48928 /* Notes:
48929 * - only numbered indices are relevant, so arr_idx fast reject is good
48930 * (this is valid unless there are more than 4**32-1 arguments).
48931 * - since variable lookup has no side effects, this can be skipped if
48932 * DUK_GETDESC_FLAG_PUSH_VALUE is not set.
48933 */
48934
48936 arr_idx != DUK__NO_ARRAY_INDEX &&
48937 (flags & DUK_GETDESC_FLAG_PUSH_VALUE)) {
48938 duk_propdesc temp_desc;
48939
48940 /* Magically bound variable cannot be an accessor. However,
48941 * there may be an accessor property (or a plain property) in
48942 * place with magic behavior removed. This happens e.g. when
48943 * a magic property is redefined with defineProperty().
48944 * Cannot assert for "not accessor" here.
48946
48947 /* replaces top of stack with new value if necessary */
48949
48950 if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
48951 DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
48952 (duk_tval *) duk_get_tval(ctx, -2),
48953 (duk_tval *) duk_get_tval(ctx, -1)));
48954 /* [... old_result result] -> [... result] */
48955 duk_remove(ctx, -2);
48956 }
48957 }
48958
48959 return 1;
48960}
48961
48963 DUK_ASSERT(thr != NULL);
48964 DUK_ASSERT(obj != NULL);
48965 DUK_ASSERT(key != NULL);
48966 DUK_ASSERT(out_desc != NULL);
48968
48969 return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
48970}
48971
48972/*
48973 * Ecmascript compliant [[GetProperty]](P), for internal use only.
48975 * If property is found:
48976 * - Fills descriptor fields to 'out_desc'
48977 * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
48978 * property onto the stack ('undefined' for accessor properties).
48979 * - Returns non-zero
48980 *
48981 * If property is not found:
48982 * - 'out_desc' is left in untouched state (possibly garbage)
48983 * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
48984 * set)
48985 * - Returns zero
48986 *
48987 * May cause arbitrary side effects and invalidate (most) duk_tval
48988 * pointers.
48989 */
48990
48992 duk_hobject *curr;
48993 duk_uint32_t arr_idx;
48994 duk_uint_t sanity;
48995
48996 DUK_ASSERT(thr != NULL);
48997 DUK_ASSERT(thr->heap != NULL);
48998 DUK_ASSERT(obj != NULL);
48999 DUK_ASSERT(key != NULL);
49000 DUK_ASSERT(out_desc != NULL);
49002
49003 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
49004
49005 DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
49006 "arr_idx=%ld (obj -> %!O, key -> %!O)",
49007 (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
49008 (long) flags, (long) arr_idx,
49009 (duk_heaphdr *) obj, (duk_heaphdr *) key));
49010
49011 curr = obj;
49012 DUK_ASSERT(curr != NULL);
49014 do {
49015 if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
49016 /* stack contains value (if requested), 'out_desc' is set */
49017 return 1;
49018 }
49019
49020 /* not found in 'curr', next in prototype chain; impose max depth */
49021 if (sanity-- == 0) {
49023 /* treat like property not found */
49024 break;
49025 } else {
49027 }
49028 }
49029 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
49030 } while (curr);
49031
49032 /* out_desc is left untouched (possibly garbage), caller must use return
49033 * value to determine whether out_desc can be looked up
49034 */
49035
49036 return 0;
49037}
49038
49039/*
49040 * Shallow fast path checks for accessing array elements with numeric
49041 * indices. The goal is to try to avoid coercing an array index to an
49042 * (interned) string for the most common lookups, in particular, for
49043 * standard Array objects.
49044 *
49045 * Interning is avoided but only for a very narrow set of cases:
49046 * - Object has array part, index is within array allocation, and
49047 * value is not unused (= key exists)
49048 * - Object has no interfering exotic behavior (e.g. arguments or
49049 * string object exotic behaviors interfere, array exotic
49050 * behavior does not).
49051 *
49052 * Current shortcoming: if key does not exist (even if it is within
49053 * the array allocation range) a slow path lookup with interning is
49054 * always required. This can probably be fixed so that there is a
49055 * quick fast path for non-existent elements as well, at least for
49056 * standard Array objects.
49057 */
49058
49060 duk_tval *tv;
49061 duk_uint32_t idx;
49062
49063 DUK_UNREF(thr);
49064
49065 if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
49070 /* Must have array part and no conflicting exotic behaviors.
49071 * Doesn't need to have array special behavior, e.g. Arguments
49072 * object has array part.
49073 */
49074 return NULL;
49075 }
49076
49077 /* Arrays never have other exotic behaviors. */
49078
49079 DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
49080 "behavior, object has array part)"));
49081
49082#if defined(DUK_USE_FASTINT)
49083 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49084 idx = duk__tval_fastint_to_arr_idx(tv_key);
49085 } else
49086#endif
49087 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49088 idx = duk__tval_number_to_arr_idx(tv_key);
49089 } else {
49090 DUK_DDD(DUK_DDDPRINT("key is not a number"));
49091 return NULL;
49092 }
49093
49094 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49095 * is 0xffffffffUL. We don't need to check for that explicitly
49096 * because 0xffffffffUL will never be inside object 'a_size'.
49097 */
49098
49099 if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
49100 DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
49101 return NULL;
49102 }
49103 DUK_ASSERT(idx != 0xffffffffUL);
49105
49106 /* XXX: for array instances we could take a shortcut here and assume
49107 * Array.prototype doesn't contain an array index property.
49108 */
49109
49110 DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
49111 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
49112 if (!DUK_TVAL_IS_UNUSED(tv)) {
49113 DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
49114 return tv;
49115 }
49116
49117 DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
49118 return NULL;
49119}
49120
49122 duk_tval *tv;
49123 duk_uint32_t idx;
49124 duk_uint32_t old_len, new_len;
49125
49126 if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
49129 return 0;
49130 }
49131 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures */
49132
49133#if defined(DUK_USE_FASTINT)
49134 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49135 idx = duk__tval_fastint_to_arr_idx(tv_key);
49136 } else
49137#endif
49138 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49139 idx = duk__tval_number_to_arr_idx(tv_key);
49140 } else {
49141 DUK_DDD(DUK_DDDPRINT("key is not a number"));
49142 return 0;
49143 }
49144
49145 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49146 * is 0xffffffffUL. We don't need to check for that explicitly
49147 * because 0xffffffffUL will never be inside object 'a_size'.
49148 */
49149
49150 if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { /* for resizing of array part, use slow path */
49151 return 0;
49152 }
49153 DUK_ASSERT(idx != 0xffffffffUL);
49155
49156 old_len = duk__get_old_array_length(thr, obj, temp_desc);
49157
49158 if (idx >= old_len) {
49159 DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
49160 "(arr_idx=%ld, old_len=%ld)",
49161 (long) idx, (long) old_len));
49162 if (!(temp_desc->flags & DUK_PROPDESC_FLAG_WRITABLE)) {
49164 return 0; /* not reachable */
49165 }
49166 new_len = idx + 1;
49167
49168 /* No resize has occurred so temp_desc->e_idx is still OK */
49169 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
49171 DUK_TVAL_SET_FASTINT_U32(tv, new_len); /* no need for decref/incref because value is a number */
49172 } else {
49173 ;
49174 }
49175
49176 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
49177 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
49178
49179 DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
49180 return 1;
49181}
49182
49183/*
49184 * Fast path for bufferobject getprop/putprop
49185 */
49186
49188 duk_context *ctx;
49189 duk_uint32_t idx;
49190 duk_hbufferobject *h_bufobj;
49191 duk_uint_t byte_off;
49192 duk_small_uint_t elem_size;
49193 duk_uint8_t *data;
49194
49195 ctx = (duk_context *) thr;
49196
49197 if (!DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
49198 return 0;
49199 }
49200 h_bufobj = (duk_hbufferobject *) obj;
49201
49202#if defined(DUK_USE_FASTINT)
49203 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49204 idx = duk__tval_fastint_to_arr_idx(tv_key);
49205 } else
49206#endif
49207 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49208 idx = duk__tval_number_to_arr_idx(tv_key);
49209 } else {
49210 return 0;
49211 }
49212
49213 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49214 * is 0xffffffffUL. We don't need to check for that explicitly
49215 * because 0xffffffffUL will never be inside bufferobject length.
49216 */
49217
49218 /* Careful with wrapping (left shifting idx would be unsafe). */
49219 if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
49220 return 0;
49223
49224 byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
49225 elem_size = 1 << h_bufobj->shift;
49226
49227 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
49228 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
49229 duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
49230 } else {
49231 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
49232 duk_push_uint(ctx, 0);
49233 }
49234
49235 return 1;
49236}
49237
49239 duk_context *ctx;
49240 duk_uint32_t idx;
49241 duk_hbufferobject *h_bufobj;
49242 duk_uint_t byte_off;
49243 duk_small_uint_t elem_size;
49244 duk_uint8_t *data;
49245
49246 ctx = (duk_context *) thr;
49247
49248 if (!(DUK_HOBJECT_IS_BUFFEROBJECT(obj) &&
49249 DUK_TVAL_IS_NUMBER(tv_val))) {
49250 return 0;
49251 }
49252 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures; rom objects are never bufferobjects now */
49253
49254 h_bufobj = (duk_hbufferobject *) obj;
49255#if defined(DUK_USE_FASTINT)
49256 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49257 idx = duk__tval_fastint_to_arr_idx(tv_key);
49258 } else
49259#endif
49260 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49261 idx = duk__tval_number_to_arr_idx(tv_key);
49262 } else {
49263 return 0;
49264 }
49265
49266 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49267 * is 0xffffffffUL. We don't need to check for that explicitly
49268 * because 0xffffffffUL will never be inside bufferobject length.
49269 */
49270
49271 /* Careful with wrapping (left shifting idx would be unsafe). */
49272 if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
49273 return 0;
49274 }
49276
49277 byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
49278 elem_size = 1 << h_bufobj->shift;
49279
49280 /* Value is required to be a number in the fast path so there
49281 * are no side effects in write coercion.
49282 */
49283 duk_push_tval(ctx, tv_val);
49285
49286 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
49287 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
49288 duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
49289 } else {
49290 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
49291 }
49292
49293 duk_pop(ctx);
49294 return 1;
49295}
49296
49297/*
49298 * GETPROP: Ecmascript property read.
49299 */
49300
49302 duk_context *ctx = (duk_context *) thr;
49303 duk_tval tv_obj_copy;
49304 duk_tval tv_key_copy;
49305 duk_hobject *curr = NULL;
49306 duk_hstring *key = NULL;
49307 duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
49308 duk_propdesc desc;
49309 duk_uint_t sanity;
49310
49311 DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
49312 (void *) thr, (void *) tv_obj, (void *) tv_key,
49313 (duk_tval *) tv_obj, (duk_tval *) tv_key));
49314
49315 DUK_ASSERT(ctx != NULL);
49316 DUK_ASSERT(thr != NULL);
49317 DUK_ASSERT(thr->heap != NULL);
49318 DUK_ASSERT(tv_obj != NULL);
49319 DUK_ASSERT(tv_key != NULL);
49320
49322
49323 /*
49324 * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
49325 * them being invalidated by a valstack resize.
49326 *
49327 * XXX: this is now an overkill for many fast paths. Rework this
49328 * to be faster (although switching to a valstack discipline might
49329 * be a better solution overall).
49330 */
49331
49332 DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
49333 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
49334 tv_obj = &tv_obj_copy;
49335 tv_key = &tv_key_copy;
49336
49337 /*
49338 * Coercion and fast path processing
49339 */
49340
49341 switch (DUK_TVAL_GET_TAG(tv_obj)) {
49342 case DUK_TAG_UNDEFINED:
49343 case DUK_TAG_NULL: {
49344 /* Note: unconditional throw */
49345 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
49346#if defined(DUK_USE_PARANOID_ERRORS)
49348#else
49349 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
49351#endif
49352 return 0;
49353 }
49354
49355 case DUK_TAG_BOOLEAN: {
49356 DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
49357 curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
49358 break;
49359 }
49360
49361 case DUK_TAG_STRING: {
49362 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
49363 duk_int_t pop_count;
49364
49365#if defined(DUK_USE_FASTINT)
49366 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49367 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
49368 DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
49369 pop_count = 0;
49370 } else
49371#endif
49372 if (DUK_TVAL_IS_NUMBER(tv_key)) {
49373 arr_idx = duk__tval_number_to_arr_idx(tv_key);
49374 DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
49375 pop_count = 0;
49376 } else {
49377 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49378 DUK_ASSERT(key != NULL);
49379 DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
49380 "coercion key is %!T, arr_idx %ld",
49381 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49382 pop_count = 1;
49383 }
49384
49385 if (arr_idx != DUK__NO_ARRAY_INDEX &&
49386 arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
49387 duk_pop_n(ctx, pop_count);
49388 duk_push_hstring(ctx, h);
49389 duk_substring(ctx, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
49390
49391 DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
49392 "after coercion -> return char)",
49393 (duk_tval *) duk_get_tval(ctx, -1)));
49394 return 1;
49395 }
49396
49397 if (pop_count == 0) {
49398 /* This is a pretty awkward control flow, but we need to recheck the
49399 * key coercion here.
49400 */
49401 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49402 DUK_ASSERT(key != NULL);
49403 DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
49404 "coercion key is %!T, arr_idx %ld",
49405 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49406 }
49407
49408 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49409 duk_pop(ctx); /* [key] -> [] */
49410 duk_push_uint(ctx, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h)); /* [] -> [res] */
49411
49412 DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
49413 "return string length)",
49414 (duk_tval *) duk_get_tval(ctx, -1)));
49415 return 1;
49416 }
49417 DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
49418 curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
49419 goto lookup; /* avoid double coercion */
49420 }
49421
49422 case DUK_TAG_OBJECT: {
49423 duk_tval *tmp;
49424
49425 curr = DUK_TVAL_GET_OBJECT(tv_obj);
49426 DUK_ASSERT(curr != NULL);
49427
49428 tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
49429 if (tmp) {
49430 duk_push_tval(ctx, tmp);
49431
49432 DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
49433 "fast path)",
49434 (duk_tval *) duk_get_tval(ctx, -1)));
49435 return 1;
49436 }
49437
49438 if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
49439 /* Read value pushed on stack. */
49440 DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufferobject "
49441 "fast path)",
49442 (duk_tval *) duk_get_tval(ctx, -1)));
49443 return 1;
49444 }
49445
49446#if defined(DUK_USE_ES6_PROXY)
49448 duk_hobject *h_target;
49449
49450 if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
49451 /* -> [ ... trap handler ] */
49452 DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
49453 duk_push_hobject(ctx, h_target); /* target */
49454 duk_push_tval(ctx, tv_key); /* P */
49455 duk_push_tval(ctx, tv_obj); /* Receiver: Proxy object */
49456 duk_call_method(ctx, 3 /*nargs*/);
49457
49458 /* Target object must be checked for a conflicting
49459 * non-configurable property.
49460 */
49461 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49462 DUK_ASSERT(key != NULL);
49463
49464 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
49465 duk_tval *tv_hook = duk_require_tval(ctx, -3); /* value from hook */
49466 duk_tval *tv_targ = duk_require_tval(ctx, -1); /* value from target */
49467 duk_bool_t datadesc_reject;
49468 duk_bool_t accdesc_reject;
49469
49470 DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
49471 "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
49472 "desc.get=%p, desc.set=%p",
49473 (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
49474 (unsigned long) desc.flags,
49475 (void *) desc.get, (void *) desc.set));
49476
49477 datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
49480 !duk_js_samevalue(tv_hook, tv_targ);
49481 accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
49483 (desc.get == NULL) &&
49484 !DUK_TVAL_IS_UNDEFINED(tv_hook);
49485 if (datadesc_reject || accdesc_reject) {
49487 }
49488
49489 duk_pop_2(ctx);
49490 } else {
49491 duk_pop(ctx);
49492 }
49493 return 1; /* return value */
49494 }
49495
49496 curr = h_target; /* resume lookup from target */
49497 DUK_TVAL_SET_OBJECT(tv_obj, curr);
49498 }
49499#endif /* DUK_USE_ES6_PROXY */
49500
49502 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49503 DUK_ASSERT(key != NULL);
49504
49505 if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
49506 DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
49507 "key matches magically bound property -> skip standard "
49508 "Get with replacement value)",
49509 (duk_tval *) duk_get_tval(ctx, -1)));
49510
49511 /* no need for 'caller' post-check, because 'key' must be an array index */
49512
49513 duk_remove(ctx, -2); /* [key result] -> [result] */
49514 return 1;
49515 }
49516
49517 goto lookup; /* avoid double coercion */
49518 }
49519 break;
49520 }
49521
49522 /* Buffer has virtual properties similar to string, but indexed values
49523 * are numbers, not 1-byte buffers/strings which would perform badly.
49524 */
49525 case DUK_TAG_BUFFER: {
49526 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
49527 duk_int_t pop_count;
49528
49529 /*
49530 * Because buffer values are often looped over, a number fast path
49531 * is important.
49532 */
49533
49534#if defined(DUK_USE_FASTINT)
49535 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49536 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
49537 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
49538 pop_count = 0;
49539 }
49540 else
49541#endif
49542 if (DUK_TVAL_IS_NUMBER(tv_key)) {
49543 arr_idx = duk__tval_number_to_arr_idx(tv_key);
49544 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
49545 pop_count = 0;
49546 } else {
49547 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49548 DUK_ASSERT(key != NULL);
49549 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
49550 "coercion key is %!T, arr_idx %ld",
49551 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49552 pop_count = 1;
49553 }
49554
49555 if (arr_idx != DUK__NO_ARRAY_INDEX &&
49556 arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
49557 duk_pop_n(ctx, pop_count);
49558 duk_push_uint(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
49559
49560 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
49561 "after coercion -> return byte as number)",
49562 (duk_tval *) duk_get_tval(ctx, -1)));
49563 return 1;
49564 }
49565
49566 if (pop_count == 0) {
49567 /* This is a pretty awkward control flow, but we need to recheck the
49568 * key coercion here.
49569 */
49570 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49571 DUK_ASSERT(key != NULL);
49572 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
49573 "coercion key is %!T, arr_idx %ld",
49574 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49575 }
49576
49577 if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
49578 key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
49579 duk_pop(ctx); /* [key] -> [] */
49580 duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h)); /* [] -> [res] */
49581
49582 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' or 'byteLength' "
49583 "after coercion -> return buffer length)",
49584 (duk_tval *) duk_get_tval(ctx, -1)));
49585 return 1;
49586 } else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
49587 duk_pop(ctx); /* [key] -> [] */
49588 duk_push_uint(ctx, 0); /* [] -> [res] */
49589
49590 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'byteOffset' after coercion -> "
49591 "return 0 for consistency with Buffer objects)",
49592 (duk_tval *) duk_get_tval(ctx, -1)));
49593 return 1;
49594 } else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
49595 duk_pop(ctx); /* [key] -> [] */
49596 duk_push_uint(ctx, 1); /* [] -> [res] */
49597
49598 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'BYTES_PER_ELEMENT' after coercion -> "
49599 "return 1 for consistency with Buffer objects)",
49600 (duk_tval *) duk_get_tval(ctx, -1)));
49601 return 1;
49602 }
49603
49604 DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from buffer prototype"));
49605 curr = thr->builtins[DUK_BIDX_BUFFER_PROTOTYPE];
49606 goto lookup; /* avoid double coercion */
49607 }
49608
49609 case DUK_TAG_POINTER: {
49610 DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
49611 curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
49612 break;
49613 }
49614
49615 case DUK_TAG_LIGHTFUNC: {
49616 duk_int_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_obj);
49617
49618 /* Must coerce key: if key is an object, it may coerce to e.g. 'length'. */
49619 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49620
49621 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49622 duk_int_t lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
49623 duk_pop(ctx);
49624 duk_push_int(ctx, lf_len);
49625 return 1;
49626 } else if (key == DUK_HTHREAD_STRING_NAME(thr)) {
49627 duk_pop(ctx);
49628 duk_push_lightfunc_name(ctx, tv_obj);
49629 return 1;
49630 }
49631
49632 DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
49633 curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
49634 goto lookup; /* avoid double coercion */
49635 }
49636
49637#if defined(DUK_USE_FASTINT)
49638 case DUK_TAG_FASTINT:
49639#endif
49640 default: {
49641 /* number */
49642 DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
49645 curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
49646 break;
49647 }
49648 }
49649
49650 /* key coercion (unless already coerced above) */
49651 DUK_ASSERT(key == NULL);
49652 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49653 DUK_ASSERT(key != NULL);
49654
49655 /*
49656 * Property lookup
49657 */
49658
49659 lookup:
49660 /* [key] (coerced) */
49661 DUK_ASSERT(curr != NULL);
49662 DUK_ASSERT(key != NULL);
49663
49665 do {
49666 if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
49667 goto next_in_chain;
49668 }
49669
49670 if (desc.get != NULL) {
49671 /* accessor with defined getter */
49673
49674 duk_pop(ctx); /* [key undefined] -> [key] */
49675 duk_push_hobject(ctx, desc.get);
49676 duk_push_tval(ctx, tv_obj); /* note: original, uncoerced base */
49677#ifdef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
49678 duk_dup(ctx, -3);
49679 duk_call_method(ctx, 1); /* [key getter this key] -> [key retval] */
49680#else
49681 duk_call_method(ctx, 0); /* [key getter this] -> [key retval] */
49682#endif
49683 } else {
49684 /* [key value] or [key undefined] */
49685
49686 /* data property or accessor without getter */
49688 (desc.get == NULL));
49689
49690 /* if accessor without getter, return value is undefined */
49692 duk_is_undefined(ctx, -1));
49693
49694 /* Note: for an accessor without getter, falling through to
49695 * check for "caller" exotic behavior is unnecessary as
49696 * "undefined" will never activate the behavior. But it does
49697 * no harm, so we'll do it anyway.
49698 */
49699 }
49700
49701 goto found; /* [key result] */
49702
49703 next_in_chain:
49704 /* XXX: option to pretend property doesn't exist if sanity limit is
49705 * hit might be useful.
49706 */
49707 if (sanity-- == 0) {
49709 }
49710 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
49711 } while (curr);
49712
49713 /*
49714 * Not found
49715 */
49716
49717 duk_to_undefined(ctx, -1); /* [key] -> [undefined] (default value) */
49718
49719 DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(ctx, -1)));
49720 return 0;
49721
49722 /*
49723 * Found; post-processing (Function and arguments objects)
49724 */
49725
49726 found:
49727 /* [key result] */
49728
49729#if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
49730 /* Special behavior for 'caller' property of (non-bound) function objects
49731 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
49732 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
49733 * Quite interestingly, a non-strict function with no formal arguments
49734 * will get an arguments object -without- special 'caller' behavior!
49735 *
49736 * The E5.1 spec is a bit ambiguous if this special behavior applies when
49737 * a bound function is the base value (not the 'caller' value): Section
49738 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
49739 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
49740 * However, Section 13.3.5.4 has "NOTE: Function objects created using
49741 * Function.prototype.bind use the default [[Get]] internal method."
49742 * The current implementation assumes this means that bound functions
49743 * should not have the special [[Get]] behavior.
49744 *
49745 * The E5.1 spec is also a bit unclear if the TypeError throwing is
49746 * applied if the 'caller' value is a strict bound function. The
49747 * current implementation will throw even for both strict non-bound
49748 * and strict bound functions.
49749 *
49750 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
49751 * tests.
49752 *
49753 * This exotic behavior is disabled when the non-standard 'caller' property
49754 * is enabled, as it conflicts with the free use of 'caller'.
49755 */
49756 if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
49757 DUK_TVAL_IS_OBJECT(tv_obj)) {
49758 duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
49759 DUK_ASSERT(orig != NULL);
49760
49763 duk_hobject *h;
49764
49765 /* XXX: The TypeError is currently not applied to bound
49766 * functions because the 'strict' flag is not copied by
49767 * bind(). This may or may not be correct, the specification
49768 * only refers to the value being a "strict mode Function
49769 * object" which is ambiguous.
49770 */
49772
49773 h = duk_get_hobject(ctx, -1); /* NULL if not an object */
49774 if (h &&
49777 /* XXX: sufficient to check 'strict', assert for 'is function' */
49779 }
49781 }
49782#endif /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
49783
49784 duk_remove(ctx, -2); /* [key result] -> [result] */
49785
49786 DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(ctx, -1)));
49787 return 1;
49788}
49789
49790/*
49791 * HASPROP: Ecmascript property existence check ("in" operator).
49792 *
49793 * Interestingly, the 'in' operator does not do any coercion of
49794 * the target object.
49795 */
49796
49798 duk_context *ctx = (duk_context *) thr;
49799 duk_tval tv_key_copy;
49800 duk_hobject *obj;
49801 duk_hstring *key;
49802 duk_uint32_t arr_idx;
49803 duk_bool_t rc;
49804 duk_propdesc desc;
49805
49806 DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
49807 (void *) thr, (void *) tv_obj, (void *) tv_key,
49808 (duk_tval *) tv_obj, (duk_tval *) tv_key));
49809
49810 DUK_ASSERT(thr != NULL);
49811 DUK_ASSERT(thr->heap != NULL);
49812 DUK_ASSERT(tv_obj != NULL);
49813 DUK_ASSERT(tv_key != NULL);
49815
49816 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
49817 tv_key = &tv_key_copy;
49818
49819 /*
49820 * The 'in' operator requires an object as its right hand side,
49821 * throwing a TypeError unconditionally if this is not the case.
49822 *
49823 * However, lightfuncs need to behave like fully fledged objects
49824 * here to be maximally transparent, so we need to handle them
49825 * here.
49826 */
49827
49828 /* XXX: Refactor key coercion so that it's only called once. It can't
49829 * be trivially lifted here because the object must be type checked
49830 * first.
49831 */
49832
49833 if (DUK_TVAL_IS_OBJECT(tv_obj)) {
49834 obj = DUK_TVAL_GET_OBJECT(tv_obj);
49835 DUK_ASSERT(obj != NULL);
49836
49837 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49838 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
49839 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49840 if (duk__key_is_lightfunc_ownprop(thr, key)) {
49841 /* FOUND */
49842 rc = 1;
49843 goto pop_and_return;
49844 }
49845
49846 /* If not found, resume existence check from Function.prototype.
49847 * We can just substitute the value in this case; nothing will
49848 * need the original base value (as would be the case with e.g.
49849 * setters/getters.
49850 */
49851 obj = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
49852 } else {
49853 /* Note: unconditional throw */
49854 DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
49856 }
49857
49858 /* XXX: fast path for arrays? */
49859
49860 DUK_ASSERT(key != NULL);
49861 DUK_ASSERT(obj != NULL);
49862 DUK_UNREF(arr_idx);
49863
49864#if defined(DUK_USE_ES6_PROXY)
49866 duk_hobject *h_target;
49867 duk_bool_t tmp_bool;
49868
49869 /* XXX: the key in 'key in obj' is string coerced before we're called
49870 * (which is the required behavior in E5/E5.1/E6) so the key is a string
49871 * here already.
49872 */
49873
49874 if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
49875 /* [ ... key trap handler ] */
49876 DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
49877 duk_push_hobject(ctx, h_target); /* target */
49878 duk_push_tval(ctx, tv_key); /* P */
49879 duk_call_method(ctx, 2 /*nargs*/);
49880 tmp_bool = duk_to_boolean(ctx, -1);
49881 if (!tmp_bool) {
49882 /* Target object must be checked for a conflicting
49883 * non-configurable property.
49884 */
49885
49886 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
49887 DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
49888 "conflicting property; desc.flags=0x%08lx, "
49889 "desc.get=%p, desc.set=%p",
49890 (duk_heaphdr *) key, (unsigned long) desc.flags,
49891 (void *) desc.get, (void *) desc.set));
49892 /* XXX: Extensibility check for target uses IsExtensible(). If we
49893 * implemented the isExtensible trap and didn't reject proxies as
49894 * proxy targets, it should be respected here.
49895 */
49896 if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && /* property is configurable and */
49897 DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) { /* ... target is extensible */
49899 }
49900 }
49901 }
49902
49903 duk_pop_2(ctx); /* [ key trap_result ] -> [] */
49904 return tmp_bool;
49905 }
49906
49907 obj = h_target; /* resume check from proxy target */
49908 }
49909#endif /* DUK_USE_ES6_PROXY */
49910
49911 /* XXX: inline into a prototype walking loop? */
49912
49913 rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/); /* don't push value */
49914 /* fall through */
49915
49916 pop_and_return:
49917 duk_pop(ctx); /* [ key ] -> [] */
49918 return rc;
49919}
49920
49921/*
49922 * HASPROP variant used internally.
49923 *
49924 * This primitive must never throw an error, callers rely on this.
49925 * In particular, don't throw an error for prototype loops; instead,
49926 * pretend like the property doesn't exist if a prototype sanity limit
49927 * is reached.
49928 *
49929 * Does not implement proxy behavior: if applied to a proxy object,
49930 * returns key existence on the proxy object itself.
49931 */
49932
49935
49936 DUK_ASSERT(thr != NULL);
49938 DUK_ASSERT(obj != NULL);
49939 DUK_ASSERT(key != NULL);
49940
49942
49943 return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP); /* don't push value */
49944}
49945
49946/*
49947 * Helper: handle Array object 'length' write which automatically
49948 * deletes properties, see E5 Section 15.4.5.1, step 3. This is
49949 * quite tricky to get right.
49950 *
49951 * Used by duk_hobject_putprop().
49952 */
49953
49954DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc) {
49955 duk_bool_t rc;
49956 duk_tval *tv;
49957 duk_uint32_t res;
49958
49960
49961 /* This function is only called for objects with array exotic behavior.
49962 * The [[DefineOwnProperty]] algorithm for arrays requires that
49963 * 'length' can never have a value outside the unsigned 32-bit range,
49964 * attempt to write such a value is a RangeError. Here we can thus
49965 * assert for this. When Duktape internals go around the official
49966 * property write interface (doesn't happen often) this assumption is
49967 * easy to accidentally break, so such code must be written carefully.
49968 * See test-bi-array-push-maxlen.js.
49969 */
49970
49971 rc = duk__get_own_propdesc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, temp_desc, 0 /*flags*/); /* don't push value */
49972 DUK_UNREF(rc);
49973 DUK_ASSERT(rc != 0); /* arrays MUST have a 'length' property */
49974 DUK_ASSERT(temp_desc->e_idx >= 0);
49975
49976 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
49977 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* array 'length' is always a number, as we coerce it */
49978 DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) >= 0.0);
49979 DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (double) 0xffffffffUL);
49981#if defined(DUK_USE_FASTINT)
49982 /* Downgrade checks are not made everywhere, so 'length' is not always
49983 * a fastint (it is a number though). This can be removed once length
49984 * is always guaranteed to be a fastint.
49985 */
49986 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv) || DUK_TVAL_IS_DOUBLE(tv));
49987 if (DUK_TVAL_IS_FASTINT(tv)) {
49988 res = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv);
49989 } else {
49990 res = (duk_uint32_t) DUK_TVAL_GET_DOUBLE(tv);
49991 }
49992#else
49993 res = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
49994#endif /* DUK_USE_FASTINT */
49995
49996 return res;
49997}
49998
50000 duk_context *ctx = (duk_context *) thr;
50001 duk_uint32_t res;
50002 duk_double_t d;
50003
50004 /* Input value should be on stack top and will be coerced and
50005 * popped. Refuse to update an Array's 'length' to a value
50006 * outside the 32-bit range. Negative zero is accepted as zero.
50007 */
50008
50009 /* XXX: fastint */
50010
50011 d = duk_to_number(ctx, -1);
50012 res = (duk_uint32_t) d;
50013 if ((duk_double_t) res != d) {
50015 }
50016 duk_pop(ctx);
50017 return res;
50018}
50019
50020/* Delete elements required by a smaller length, taking into account
50021 * potentially non-configurable elements. Returns non-zero if all
50022 * elements could be deleted, and zero if all or some elements could
50023 * not be deleted. Also writes final "target length" to 'out_result_len'.
50024 * This is the length value that should go into the 'length' property
50025 * (must be set by the caller). Never throws an error.
50026 */
50029 duk_hobject *obj,
50030 duk_uint32_t old_len,
50031 duk_uint32_t new_len,
50032 duk_bool_t force_flag,
50033 duk_uint32_t *out_result_len) {
50034 duk_uint32_t target_len;
50036 duk_uint32_t arr_idx;
50037 duk_hstring *key;
50038 duk_tval *tv;
50039 duk_bool_t rc;
50040
50041 DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
50042 "probably need to remove elements",
50043 (long) old_len, (long) new_len));
50044
50045 /*
50046 * New length is smaller than old length, need to delete properties above
50047 * the new length.
50048 *
50049 * If array part exists, this is straightforward: array entries cannot
50050 * be non-configurable so this is guaranteed to work.
50051 *
50052 * If array part does not exist, array-indexed values are scattered
50053 * in the entry part, and some may not be configurable (preventing length
50054 * from becoming lower than their index + 1). To handle the algorithm
50055 * in E5 Section 15.4.5.1, step l correctly, we scan the entire property
50056 * set twice.
50057 */
50058
50059 DUK_ASSERT(thr != NULL);
50060 DUK_ASSERT(obj != NULL);
50061 DUK_ASSERT(new_len < old_len);
50062 DUK_ASSERT(out_result_len != NULL);
50064
50065 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
50066 /*
50067 * All defined array-indexed properties are in the array part
50068 * (we assume the array part is comprehensive), and all array
50069 * entries are writable, configurable, and enumerable. Thus,
50070 * nothing can prevent array entries from being deleted.
50071 */
50072
50073 DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
50074
50075 if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
50076 /* XXX: assertion that entries >= old_len are already unused */
50077 i = old_len;
50078 } else {
50079 i = DUK_HOBJECT_GET_ASIZE(obj);
50080 }
50082
50083 while (i > new_len) {
50084 i--;
50085 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
50086 DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
50087 }
50088
50089 *out_result_len = new_len;
50090 return 1;
50091 } else {
50092 /*
50093 * Entries part is a bit more complex
50094 */
50095
50096 /* Stage 1: find highest preventing non-configurable entry (if any).
50097 * When forcing, ignore non-configurability.
50098 */
50099
50100 DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
50101
50102 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
50103 "(highest preventing non-configurable entry (if any))"));
50104
50105 target_len = new_len;
50106 if (force_flag) {
50107 DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
50108 goto skip_stage1;
50109 }
50110 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50111 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
50112 if (!key) {
50113 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
50114 continue;
50115 }
50116 if (!DUK_HSTRING_HAS_ARRIDX(key)) {
50117 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
50118 continue;
50119 }
50120
50121 DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
50122 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
50123 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
50124 DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
50125
50126 if (arr_idx < new_len) {
50127 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
50128 (long) i, (long) arr_idx));
50129 continue;
50130 }
50131 if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
50132 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
50133 (long) i, (long) arr_idx));
50134 continue;
50135 }
50136
50137 /* relevant array index is non-configurable, blocks write */
50138 if (arr_idx >= target_len) {
50139 DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
50140 "update target_len %ld -> %ld",
50141 (long) i, (long) arr_idx, (long) target_len,
50142 (long) (arr_idx + 1)));
50143 target_len = arr_idx + 1;
50144 }
50145 }
50146 skip_stage1:
50147
50148 /* stage 2: delete configurable entries above target length */
50149
50150 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
50151 (long) old_len, (long) new_len, (long) target_len));
50152
50153 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
50154 "entries >= target_len"));
50155
50156 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50157 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
50158 if (!key) {
50159 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
50160 continue;
50161 }
50162 if (!DUK_HSTRING_HAS_ARRIDX(key)) {
50163 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
50164 continue;
50165 }
50166
50167 DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
50168 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
50169 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
50170 DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
50171
50172 if (arr_idx < target_len) {
50173 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
50174 (long) i, (long) arr_idx));
50175 continue;
50176 }
50177 DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)); /* stage 1 guarantees */
50178
50179 DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
50180 (long) i, (long) arr_idx));
50181
50182 /*
50183 * Slow delete, but we don't care as we're already in a very slow path.
50184 * The delete always succeeds: key has no exotic behavior, property
50185 * is configurable, and no resize occurs.
50186 */
50187 rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
50188 DUK_UNREF(rc);
50189 DUK_ASSERT(rc != 0);
50190 }
50191
50192 /* stage 3: update length (done by caller), decide return code */
50193
50194 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
50195
50196 *out_result_len = target_len;
50197
50198 if (target_len == new_len) {
50199 DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
50200 return 1;
50201 }
50202 DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
50203 "full length adjustment), return error"));
50204 return 0;
50205 }
50206
50208}
50209
50210/* XXX: is valstack top best place for argument? */
50212 duk_context *ctx = (duk_context *) thr;
50213 duk_propdesc desc;
50214 duk_uint32_t old_len;
50215 duk_uint32_t new_len;
50216 duk_uint32_t result_len;
50217 duk_tval *tv;
50218 duk_bool_t rc;
50219
50220 DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
50221 "new val: %!T",
50222 (duk_tval *) duk_get_tval(ctx, -1)));
50223
50224 DUK_ASSERT(thr != NULL);
50225 DUK_ASSERT(ctx != NULL);
50226 DUK_ASSERT(obj != NULL);
50227
50229
50231
50232 /*
50233 * Get old and new length
50234 */
50235
50236 old_len = duk__get_old_array_length(thr, obj, &desc);
50237 duk_dup(ctx, -1); /* [in_val in_val] */
50238 new_len = duk__to_new_array_length_checked(thr); /* -> [in_val] */
50239 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
50240
50241 /*
50242 * Writability check
50243 */
50244
50245 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50246 DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
50247 return 0;
50248 }
50249
50250 /*
50251 * New length not lower than old length => no changes needed
50252 * (not even array allocation).
50253 */
50254
50255 if (new_len >= old_len) {
50256 DUK_DDD(DUK_DDDPRINT("new length is higher than old length, just update length, no deletions"));
50257
50258 DUK_ASSERT(desc.e_idx >= 0);
50260 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
50262 /* no decref needed for a number */
50263 DUK_TVAL_SET_FASTINT_U32(tv, new_len);
50265 return 1;
50266 }
50267
50268 DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
50269
50270 /*
50271 * New length lower than old length => delete elements, then
50272 * update length.
50273 *
50274 * Note: even though a bunch of elements have been deleted, the 'desc' is
50275 * still valid as properties haven't been resized (and entries compacted).
50276 */
50277
50278 rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
50279 DUK_ASSERT(result_len >= new_len && result_len <= old_len);
50280
50281 DUK_ASSERT(desc.e_idx >= 0);
50283 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
50285 /* no decref needed for a number */
50286 DUK_TVAL_SET_FASTINT_U32(tv, result_len);
50288
50289 /* XXX: shrink array allocation or entries compaction here? */
50290
50291 return rc;
50292}
50293
50294/*
50295 * PUTPROP: Ecmascript property write.
50296 *
50297 * Unlike Ecmascript primitive which returns nothing, returns 1 to indicate
50298 * success and 0 to indicate failure (assuming throw is not set).
50299 *
50300 * This is an extremely tricky function. Some examples:
50301 *
50302 * * Currently a decref may trigger a GC, which may compact an object's
50303 * property allocation. Consequently, any entry indices (e_idx) will
50304 * be potentially invalidated by a decref.
50305 *
50306 * * Exotic behaviors (strings, arrays, arguments object) require,
50307 * among other things:
50308 *
50309 * - Preprocessing before and postprocessing after an actual property
50310 * write. For example, array index write requires pre-checking the
50311 * array 'length' property for access control, and may require an
50312 * array 'length' update after the actual write has succeeded (but
50313 * not if it fails).
50314 *
50315 * - Deletion of multiple entries, as a result of array 'length' write.
50316 *
50317 * * Input values are taken as pointers which may point to the valstack.
50318 * If valstack is resized because of the put (this may happen at least
50319 * when the array part is abandoned), the pointers can be invalidated.
50320 * (We currently make a copy of all of the input values to avoid issues.)
50321 */
50322
50323DUK_INTERNAL 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) {
50324 duk_context *ctx = (duk_context *) thr;
50325 duk_tval tv_obj_copy;
50326 duk_tval tv_key_copy;
50327 duk_tval tv_val_copy;
50328 duk_hobject *orig = NULL; /* NULL if tv_obj is primitive */
50329 duk_hobject *curr;
50330 duk_hstring *key = NULL;
50331 duk_propdesc desc;
50332 duk_tval *tv;
50333 duk_uint32_t arr_idx;
50334 duk_bool_t rc;
50335 duk_int_t e_idx;
50336 duk_uint_t sanity;
50337 duk_uint32_t new_array_length = 0; /* 0 = no update */
50338
50339 DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
50340 "(obj -> %!T, key -> %!T, val -> %!T)",
50341 (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
50342 (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
50343
50344 DUK_ASSERT(thr != NULL);
50345 DUK_ASSERT(thr->heap != NULL);
50346 DUK_ASSERT(ctx != NULL);
50347 DUK_ASSERT(tv_obj != NULL);
50348 DUK_ASSERT(tv_key != NULL);
50349 DUK_ASSERT(tv_val != NULL);
50350
50352
50353 /*
50354 * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
50355 * them being invalidated by a valstack resize.
50356 *
50357 * XXX: this is an overkill for some paths, so optimize this later
50358 * (or maybe switch to a stack arguments model entirely).
50359 */
50360
50361 DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
50362 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
50363 DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
50364 tv_obj = &tv_obj_copy;
50365 tv_key = &tv_key_copy;
50366 tv_val = &tv_val_copy;
50367
50368 /*
50369 * Coercion and fast path processing.
50370 */
50371
50372 switch (DUK_TVAL_GET_TAG(tv_obj)) {
50373 case DUK_TAG_UNDEFINED:
50374 case DUK_TAG_NULL: {
50375 /* Note: unconditional throw */
50376 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
50377 (duk_tval *) tv_obj));
50378#if defined(DUK_USE_PARANOID_ERRORS)
50380#else
50381 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
50383#endif
50384 return 0;
50385 }
50386
50387 case DUK_TAG_BOOLEAN: {
50388 DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
50390 break;
50391 }
50392
50393 case DUK_TAG_STRING: {
50394 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
50395
50396 /*
50397 * Note: currently no fast path for array index writes.
50398 * They won't be possible anyway as strings are immutable.
50399 */
50400
50401 DUK_ASSERT(key == NULL);
50402 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50403 DUK_ASSERT(key != NULL);
50404
50405 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
50406 goto fail_not_writable;
50407 }
50408
50409 if (arr_idx != DUK__NO_ARRAY_INDEX &&
50410 arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
50411 goto fail_not_writable;
50412 }
50413
50414 DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
50416 goto lookup; /* avoid double coercion */
50417 }
50418
50419 case DUK_TAG_OBJECT: {
50420 orig = DUK_TVAL_GET_OBJECT(tv_obj);
50421 DUK_ASSERT(orig != NULL);
50422
50423#if defined(DUK_USE_ROM_OBJECTS)
50424 /* With this check in place fast paths won't need read-only
50425 * object checks. This is technically incorrect if there are
50426 * setters that cause no writes to ROM objects, but current
50427 * built-ins don't have such setters.
50428 */
50429 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
50430 DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
50431 goto fail_not_writable_no_pop; /* Must avoid duk_pop() in exit path */
50432 }
50433#endif
50434
50435 /* The fast path for array property put is not fully compliant:
50436 * If one places conflicting number-indexed properties into
50437 * Array.prototype (for example, a non-writable Array.prototype[7])
50438 * the fast path will incorrectly ignore them.
50439 *
50440 * This fast path could be made compliant by falling through
50441 * to the slow path if the previous value was UNUSED. This would
50442 * also remove the need to check for extensibility. Right now a
50443 * non-extensible array is slower than an extensible one as far
50444 * as writes are concerned.
50445 *
50446 * The fast path behavior is documented in more detail here:
50447 * tests/ecmascript/test-misc-array-fast-write.js
50448 */
50449
50450 if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val, &desc) != 0) {
50451 DUK_DDD(DUK_DDDPRINT("array fast path success"));
50452 return 1;
50453 }
50454
50455 if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
50456 DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufferobject fast path"));
50457 return 1;
50458 }
50459
50460#if defined(DUK_USE_ES6_PROXY)
50462 duk_hobject *h_target;
50463 duk_bool_t tmp_bool;
50464
50465 if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
50466 /* -> [ ... trap handler ] */
50467 DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
50468 duk_push_hobject(ctx, h_target); /* target */
50469 duk_push_tval(ctx, tv_key); /* P */
50470 duk_push_tval(ctx, tv_val); /* V */
50471 duk_push_tval(ctx, tv_obj); /* Receiver: Proxy object */
50472 duk_call_method(ctx, 4 /*nargs*/);
50473 tmp_bool = duk_to_boolean(ctx, -1);
50474 duk_pop(ctx);
50475 if (!tmp_bool) {
50476 goto fail_proxy_rejected;
50477 }
50478
50479 /* Target object must be checked for a conflicting
50480 * non-configurable property.
50481 */
50482 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50483 DUK_ASSERT(key != NULL);
50484
50485 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
50486 duk_tval *tv_targ = duk_require_tval(ctx, -1);
50487 duk_bool_t datadesc_reject;
50488 duk_bool_t accdesc_reject;
50489
50490 DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
50491 "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
50492 "desc.get=%p, desc.set=%p",
50493 (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
50494 (unsigned long) desc.flags,
50495 (void *) desc.get, (void *) desc.set));
50496
50497 datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
50500 !duk_js_samevalue(tv_val, tv_targ);
50501 accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
50503 (desc.set == NULL);
50504 if (datadesc_reject || accdesc_reject) {
50506 }
50507
50508 duk_pop_2(ctx);
50509 } else {
50510 duk_pop(ctx);
50511 }
50512 return 1; /* success */
50513 }
50514
50515 orig = h_target; /* resume write to target */
50516 DUK_TVAL_SET_OBJECT(tv_obj, orig);
50517 }
50518#endif /* DUK_USE_ES6_PROXY */
50519
50520 curr = orig;
50521 break;
50522 }
50523
50524 case DUK_TAG_BUFFER: {
50525 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
50526 duk_int_t pop_count = 0;
50527
50528 /*
50529 * Because buffer values may be looped over and read/written
50530 * from, an array index fast path is important.
50531 */
50532
50533#if defined(DUK_USE_FASTINT)
50534 if (DUK_TVAL_IS_FASTINT(tv_key)) {
50535 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
50536 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
50537 pop_count = 0;
50538 } else
50539#endif
50540 if (DUK_TVAL_IS_NUMBER(tv_key)) {
50541 arr_idx = duk__tval_number_to_arr_idx(tv_key);
50542 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
50543 pop_count = 0;
50544 } else {
50545 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50546 DUK_ASSERT(key != NULL);
50547 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
50548 "coercion key is %!T, arr_idx %ld",
50549 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
50550 pop_count = 1;
50551 }
50552
50553 if (arr_idx != DUK__NO_ARRAY_INDEX &&
50554 arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
50555 duk_uint8_t *data;
50556 DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
50557 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
50558
50559 /* XXX: duk_to_int() ensures we'll get 8 lowest bits as
50560 * as input is within duk_int_t range (capped outside it).
50561 */
50562#if defined(DUK_USE_FASTINT)
50563 /* Buffer writes are often integers. */
50564 if (DUK_TVAL_IS_FASTINT(tv_val)) {
50565 data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
50566 }
50567 else
50568#endif
50569 {
50570 duk_push_tval(ctx, tv_val);
50571 data[arr_idx] = (duk_uint8_t) duk_to_uint32(ctx, -1);
50572 pop_count++;
50573 }
50574
50575 duk_pop_n(ctx, pop_count);
50576 DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
50577 return 1;
50578 }
50579
50580 if (pop_count == 0) {
50581 /* This is a pretty awkward control flow, but we need to recheck the
50582 * key coercion here.
50583 */
50584 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50585 DUK_ASSERT(key != NULL);
50586 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
50587 "coercion key is %!T, arr_idx %ld",
50588 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
50589 }
50590
50591 if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
50592 key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr) ||
50593 key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr) ||
50595 goto fail_not_writable;
50596 }
50597
50598 DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from buffer prototype"));
50600 goto lookup; /* avoid double coercion */
50601 }
50602
50603 case DUK_TAG_POINTER: {
50604 DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
50606 break;
50607 }
50608
50609 case DUK_TAG_LIGHTFUNC: {
50610 /* All lightfunc own properties are non-writable and the lightfunc
50611 * is considered non-extensible. However, the write may be captured
50612 * by an inherited setter which means we can't stop the lookup here.
50613 */
50614
50615 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50616
50617 if (duk__key_is_lightfunc_ownprop(thr, key)) {
50618 goto fail_not_writable;
50619 }
50620
50621 DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
50623 goto lookup; /* avoid double coercion */
50624 }
50625
50626#if defined(DUK_USE_FASTINT)
50627 case DUK_TAG_FASTINT:
50628#endif
50629 default: {
50630 /* number */
50631 DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
50634 break;
50635 }
50636 }
50637
50638 DUK_ASSERT(key == NULL);
50639 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50640 DUK_ASSERT(key != NULL);
50641
50642 lookup:
50643
50644 /*
50645 * Check whether the property already exists in the prototype chain.
50646 * Note that the actual write goes into the original base object
50647 * (except if an accessor property captures the write).
50648 */
50649
50650 /* [key] */
50651
50652 DUK_ASSERT(curr != NULL);
50654 do {
50655 if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
50656 goto next_in_chain;
50657 }
50658
50659 if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
50660 /*
50661 * Found existing accessor property (own or inherited).
50662 * Call setter with 'this' set to orig, and value as the only argument.
50663 * Setter calls are OK even for ROM objects.
50664 *
50665 * Note: no exotic arguments object behavior, because [[Put]] never
50666 * calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
50667 */
50668
50669 duk_hobject *setter;
50670
50671 DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
50672
50673 setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
50674 if (!setter) {
50675 goto fail_no_setter;
50676 }
50677 duk_push_hobject(ctx, setter);
50678 duk_push_tval(ctx, tv_obj); /* note: original, uncoerced base */
50679 duk_push_tval(ctx, tv_val); /* [key setter this val] */
50680#ifdef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
50681 duk_dup(ctx, -4);
50682 duk_call_method(ctx, 2); /* [key setter this val key] -> [key retval] */
50683#else
50684 duk_call_method(ctx, 1); /* [key setter this val] -> [key retval] */
50685#endif
50686 duk_pop(ctx); /* ignore retval -> [key] */
50687 goto success_no_arguments_exotic;
50688 }
50689
50690 if (orig == NULL) {
50691 /*
50692 * Found existing own or inherited plain property, but original
50693 * base is a primitive value.
50694 */
50695 DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
50696 goto fail_base_primitive;
50697 }
50698
50699 if (curr != orig) {
50700 /*
50701 * Found existing inherited plain property.
50702 * Do an access control check, and if OK, write
50703 * new property to 'orig'.
50704 */
50705 if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
50706 DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
50707 goto fail_not_extensible;
50708 }
50709 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50710 DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
50711 goto fail_not_writable;
50712 }
50713 DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
50714 goto create_new;
50715 } else {
50716 /*
50717 * Found existing own (non-inherited) plain property.
50718 * Do an access control check and update in place.
50719 */
50720
50721 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50722 DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
50723 goto fail_not_writable;
50724 }
50725 if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
50726 DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
50727 if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
50728 duk_hbufferobject *h_bufobj;
50729 duk_uint_t byte_off;
50730 duk_small_uint_t elem_size;
50731
50732 h_bufobj = (duk_hbufferobject *) curr;
50734
50735 DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
50736
50737 /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
50738 * length downshift won't.
50739 */
50740 if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
50741 duk_uint8_t *data;
50742 DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
50743
50744 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX); /* index/length check guarantees */
50745 byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
50746 elem_size = 1 << h_bufobj->shift;
50747
50748 /* Coerce to number before validating pointers etc so that the
50749 * number coercions in duk_hbufferobject_validated_write() are
50750 * guaranteed to be side effect free and not invalidate the
50751 * pointer checks we do here.
50752 */
50753 duk_push_tval(ctx, tv_val);
50754 duk_to_number(ctx, -1);
50755
50756 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
50757 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
50758 duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
50759 } else {
50760 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
50761 }
50762 duk_pop(ctx);
50763 goto success_no_arguments_exotic;
50764 }
50765 }
50766
50767 goto fail_internal; /* should not happen */
50768 }
50769 DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
50770 goto update_old;
50771 }
50773
50774 next_in_chain:
50775 /* XXX: option to pretend property doesn't exist if sanity limit is
50776 * hit might be useful.
50777 */
50778 if (sanity-- == 0) {
50780 }
50781 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
50782 } while (curr);
50783
50784 /*
50785 * Property not found in prototype chain.
50786 */
50787
50788 DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
50789
50790 if (orig == NULL) {
50791 DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
50792 goto fail_base_primitive;
50793 }
50794
50795 if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
50796 DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
50797 goto fail_not_extensible;
50798 }
50799
50800 goto create_new;
50801
50802 update_old:
50803
50804 /*
50805 * Update an existing property of the base object.
50806 */
50807
50808 /* [key] */
50809
50810 DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
50811
50812 DUK_ASSERT(orig != NULL);
50813#if defined(DUK_USE_ROM_OBJECTS)
50814 /* This should not happen because DUK_TAG_OBJECT case checks
50815 * for this already, but check just in case.
50816 */
50817 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
50818 goto fail_not_writable;
50819 }
50820#endif
50821
50822 /* Although there are writable virtual properties (e.g. plain buffer
50823 * and buffer object number indices), they are handled before we come
50824 * here.
50825 */
50827 DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
50828
50829 if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
50830 key == DUK_HTHREAD_STRING_LENGTH(thr)) {
50831 /*
50832 * Write to 'length' of an array is a very complex case
50833 * handled in a helper which updates both the array elements
50834 * and writes the new 'length'. The write may result in an
50835 * unconditional RangeError or a partial write (indicated
50836 * by a return code).
50837 *
50838 * Note: the helper has an unnecessary writability check
50839 * for 'length', we already know it is writable.
50840 */
50841
50842 DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
50843
50844 /* XXX: the helper currently assumes stack top contains new
50845 * 'length' value and the whole calling convention is not very
50846 * compatible with what we need.
50847 */
50848
50849 duk_push_tval(ctx, tv_val); /* [key val] */
50850 rc = duk__handle_put_array_length(thr, orig);
50851 duk_pop(ctx); /* [key val] -> [key] */
50852 if (!rc) {
50853 goto fail_array_length_partial;
50854 }
50855
50856 /* key is 'length', cannot match argument exotic behavior */
50857 goto success_no_arguments_exotic;
50858 }
50859
50860 if (desc.e_idx >= 0) {
50861 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
50862 DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
50863 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
50864 /* don't touch property attributes or hash part */
50865 DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
50866 (long) desc.e_idx, (duk_tval *) tv));
50867 } else {
50868 /* Note: array entries are always writable, so the writability check
50869 * above is pointless for them. The check could be avoided with some
50870 * refactoring but is probably not worth it.
50871 */
50872
50873 DUK_ASSERT(desc.a_idx >= 0);
50874 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
50875 DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
50876 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
50877 DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
50878 (long) desc.a_idx, (duk_tval *) tv));
50879 }
50880
50881 /* Regardless of whether property is found in entry or array part,
50882 * it may have arguments exotic behavior (array indices may reside
50883 * in entry part for abandoned / non-existent array parts).
50884 */
50885 goto success_with_arguments_exotic;
50886
50887 create_new:
50888
50889 /*
50890 * Create a new property in the original object.
50891 *
50892 * Exotic properties need to be reconsidered here from a write
50893 * perspective (not just property attributes perspective).
50894 * However, the property does not exist in the object already,
50895 * so this limits the kind of exotic properties that apply.
50896 */
50897
50898 /* [key] */
50899
50900 DUK_DDD(DUK_DDDPRINT("create new property to original object"));
50901
50902 DUK_ASSERT(orig != NULL);
50903
50904#if defined(DUK_USE_ROM_OBJECTS)
50905 /* This should not happen because DUK_TAG_OBJECT case checks
50906 * for this already, but check just in case.
50907 */
50908 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
50909 goto fail_not_writable;
50910 }
50911#endif
50912
50913 /* Not possible because array object 'length' is present
50914 * from its creation and cannot be deleted, and is thus
50915 * caught as an existing property above.
50916 */
50918 key == DUK_HTHREAD_STRING_LENGTH(thr)));
50919
50920 if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
50921 arr_idx != DUK__NO_ARRAY_INDEX) {
50922 /* automatic length update */
50923 duk_uint32_t old_len;
50924
50925 old_len = duk__get_old_array_length(thr, orig, &desc);
50926
50927 if (arr_idx >= old_len) {
50928 DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
50929 "(arr_idx=%ld, old_len=%ld)",
50930 (long) arr_idx, (long) old_len));
50931
50932 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50933 DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
50934 goto fail_not_writable;
50935 }
50936
50937 /* Note: actual update happens once write has been completed
50938 * without error below. The write should always succeed
50939 * from a specification viewpoint, but we may e.g. run out
50940 * of memory. It's safer in this order.
50941 */
50942
50943 DUK_ASSERT(arr_idx != 0xffffffffUL);
50944 new_array_length = arr_idx + 1; /* flag for later write */
50945 } else {
50946 DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
50947 "(arr_idx=%ld, old_len=%ld)",
50948 (long) arr_idx, (long) old_len));
50949 }
50950 }
50951
50952 /* write_to_array_part: */
50953
50954 /*
50955 * Write to array part?
50956 *
50957 * Note: array abandonding requires a property resize which uses
50958 * 'rechecks' valstack for temporaries and may cause any existing
50959 * valstack pointers to be invalidated. To protect against this,
50960 * tv_obj, tv_key, and tv_val are copies of the original inputs.
50961 */
50962
50963 if (arr_idx != DUK__NO_ARRAY_INDEX &&
50965 if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
50966 goto no_array_growth;
50967 }
50968
50969 /*
50970 * Array needs to grow, but we don't want it becoming too sparse.
50971 * If it were to become sparse, abandon array part, moving all
50972 * array entries into the entries part (for good).
50973 *
50974 * Since we don't keep track of actual density (used vs. size) of
50975 * the array part, we need to estimate somehow. The check is made
50976 * in two parts:
50977 *
50978 * - Check whether the resize need is small compared to the
50979 * current size (relatively); if so, resize without further
50980 * checking (essentially we assume that the original part is
50981 * "dense" so that the result would be dense enough).
50982 *
50983 * - Otherwise, compute the resize using an actual density
50984 * measurement based on counting the used array entries.
50985 */
50986
50987 DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
50988 "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
50989 (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
50990
50992 duk_uint32_t old_used;
50993 duk_uint32_t old_size;
50994
50995 DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
50996
50997 duk__compute_a_stats(thr, orig, &old_used, &old_size);
50998
50999 DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
51000 (long) old_used, (long) old_size, (long) arr_idx));
51001
51002 /* Note: intentionally use approximations to shave a few instructions:
51003 * a_used = old_used (accurate: old_used + 1)
51004 * a_size = arr_idx (accurate: arr_idx + 1)
51005 */
51006 if (duk__abandon_array_density_check(old_used, arr_idx)) {
51007 DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
51008 "decided to abandon array part (would become too sparse)"));
51009
51010 /* abandoning requires a props allocation resize and
51011 * 'rechecks' the valstack, invalidating any existing
51012 * valstack value pointers!
51013 */
51014 duk__abandon_array_checked(thr, orig);
51016
51017 goto write_to_entry_part;
51018 }
51019
51020 DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
51021 } else {
51022 DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
51023 }
51024
51025 DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
51026 "decided to extend current allocation"));
51027
51028 duk__grow_props_for_array_item(thr, orig, arr_idx);
51029
51030 no_array_growth:
51031
51032 /* Note: assume array part is comprehensive, so that either
51033 * the write goes to the array part, or we've abandoned the
51034 * array above (and will not come here).
51035 */
51036
51038 DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
51039
51040 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
51041 /* prev value must be unused, no decref */
51043 DUK_TVAL_SET_TVAL(tv, tv_val);
51044 DUK_TVAL_INCREF(thr, tv);
51045 DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
51046 (long) arr_idx, (duk_tval *) tv));
51047
51048 /* Note: array part values are [[Writable]], [[Enumerable]],
51049 * and [[Configurable]] which matches the required attributes
51050 * here.
51051 */
51052 goto entry_updated;
51053 }
51054
51055 write_to_entry_part:
51056
51057 /*
51058 * Write to entry part
51059 */
51060
51061 /* entry allocation updates hash part and increases the key
51062 * refcount; may need a props allocation resize but doesn't
51063 * 'recheck' the valstack.
51064 */
51065 e_idx = duk__alloc_entry_checked(thr, orig, key);
51066 DUK_ASSERT(e_idx >= 0);
51067
51068 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
51069 /* prev value can be garbage, no decref */
51070 DUK_TVAL_SET_TVAL(tv, tv_val);
51071 DUK_TVAL_INCREF(thr, tv);
51073 goto entry_updated;
51074
51075 entry_updated:
51076
51077 /*
51078 * Possible pending array length update, which must only be done
51079 * if the actual entry write succeeded.
51080 */
51081
51082 if (new_array_length > 0) {
51083 /*
51084 * Note: zero works as a "no update" marker because the new length
51085 * can never be zero after a new property is written.
51086 *
51087 * Note: must re-lookup because calls above (e.g. duk__alloc_entry_checked())
51088 * may realloc and compact properties and hence change e_idx.
51089 */
51090
51091 DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
51092 (long) new_array_length));
51093
51094 rc = duk__get_own_propdesc_raw(thr, orig, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &desc, 0 /*flags*/); /* don't push value */
51095 DUK_UNREF(rc);
51096 DUK_ASSERT(rc != 0);
51097 DUK_ASSERT(desc.e_idx >= 0);
51098
51099 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
51101 /* no need for decref/incref because value is a number */
51102 DUK_TVAL_SET_FASTINT_U32(tv, new_array_length);
51103 }
51104
51105 /*
51106 * Arguments exotic behavior not possible for new properties: all
51107 * magically bound properties are initially present in the arguments
51108 * object, and if they are deleted, the binding is also removed from
51109 * parameter map.
51110 */
51111
51112 goto success_no_arguments_exotic;
51113
51114 success_with_arguments_exotic:
51115
51116 /*
51117 * Arguments objects have exotic [[DefineOwnProperty]] which updates
51118 * the internal 'map' of arguments for writes to currently mapped
51119 * arguments. More conretely, writes to mapped arguments generate
51120 * a write to a bound variable.
51121 *
51122 * The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
51123 * data properties and new properties, but not for existing accessors.
51124 * Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
51125 * have a Desc with 'Value' (and possibly other properties too), and
51126 * we end up in step 5.b.i.
51127 */
51128
51129 if (arr_idx != DUK__NO_ARRAY_INDEX &&
51131 /* Note: only numbered indices are relevant, so arr_idx fast reject
51132 * is good (this is valid unless there are more than 4**32-1 arguments).
51133 */
51134
51135 DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
51136
51137 /* Note: we can reuse 'desc' here */
51138
51139 /* XXX: top of stack must contain value, which helper doesn't touch,
51140 * rework to use tv_val directly?
51141 */
51142
51143 duk_push_tval(ctx, tv_val);
51144 (void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
51145 duk_pop(ctx);
51146 }
51147 /* fall thru */
51148
51149 success_no_arguments_exotic:
51150 /* shared exit path now */
51151 DUK_DDD(DUK_DDDPRINT("result: success"));
51152 duk_pop(ctx); /* remove key */
51153 return 1;
51154
51155#if defined(DUK_USE_ES6_PROXY)
51156 fail_proxy_rejected:
51157 DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
51158 if (throw_flag) {
51160 }
51161 /* Note: no key on stack */
51162 return 0;
51163#endif
51164
51165 fail_base_primitive:
51166 DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
51167 if (throw_flag) {
51168#if defined(DUK_USE_PARANOID_ERRORS)
51170#else
51171 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
51173#endif
51174 }
51175 duk_pop(ctx); /* remove key */
51176 return 0;
51177
51178 fail_not_extensible:
51179 DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
51180 if (throw_flag) {
51182 }
51183 duk_pop(ctx); /* remove key */
51184 return 0;
51185
51186 fail_not_writable:
51187 DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
51188 if (throw_flag) {
51190 }
51191 duk_pop(ctx); /* remove key */
51192 return 0;
51193
51194#if defined(DUK_USE_ROM_OBJECTS)
51195 fail_not_writable_no_pop:
51196 DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
51197 if (throw_flag) {
51199 }
51200 return 0;
51201#endif
51202
51203 fail_array_length_partial:
51204 DUK_DDD(DUK_DDDPRINT("result: error, array length write only partially successful"));
51205 if (throw_flag) {
51207 }
51208 duk_pop(ctx); /* remove key */
51209 return 0;
51210
51211 fail_no_setter:
51212 DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
51213 if (throw_flag) {
51216 duk_pop(ctx); /* remove key */
51217 return 0;
51218
51219 fail_internal:
51220 DUK_DDD(DUK_DDDPRINT("result: error, internal"));
51221 if (throw_flag) {
51223 }
51224 duk_pop(ctx); /* remove key */
51225 return 0;
51226}
51227
51228/*
51229 * Ecmascript compliant [[Delete]](P, Throw).
51230 */
51231
51233 duk_propdesc desc;
51234 duk_tval *tv;
51235 duk_uint32_t arr_idx;
51236 duk_bool_t throw_flag;
51237 duk_bool_t force_flag;
51238
51239 throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
51240 force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
51241
51242 DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
51243 (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
51244 (duk_heaphdr *) obj, (duk_heaphdr *) key));
51245
51246 DUK_ASSERT(thr != NULL);
51247 DUK_ASSERT(thr->heap != NULL);
51248 DUK_ASSERT(obj != NULL);
51249 DUK_ASSERT(key != NULL);
51250
51252
51253 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51254
51255 /* 0 = don't push current value */
51256 if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
51257 DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
51258 goto success;
51259 }
51260
51261#if defined(DUK_USE_ROM_OBJECTS)
51263 DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
51264 goto fail_not_configurable;
51265 }
51266#endif
51267
51268 if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
51269 goto fail_not_configurable;
51270 }
51271 if (desc.a_idx < 0 && desc.e_idx < 0) {
51272 /* Currently there are no deletable virtual properties, but
51273 * with force_flag we might attempt to delete one.
51274 */
51275 goto fail_virtual;
51276 }
51277
51278 if (desc.a_idx >= 0) {
51279 DUK_ASSERT(desc.e_idx < 0);
51280
51281 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
51282 DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
51283 goto success;
51284 } else {
51285 duk_hobject *h_get = NULL;
51286 duk_hobject *h_set = NULL;
51287 duk_tval tv_tmp;
51288
51289 DUK_ASSERT(desc.a_idx < 0);
51290
51291 /* Set property slot to an empty state. Careful not to invoke
51292 * any side effects while using desc.e_idx so that it doesn't
51293 * get invalidated by a finalizer mutating our object.
51294 */
51295
51296 /* remove hash entry (no decref) */
51297#if defined(DUK_USE_HOBJECT_HASH_PART)
51298 if (desc.h_idx >= 0) {
51299 duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
51300
51301 DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
51303 DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
51304 h_base[desc.h_idx] = DUK__HASH_DELETED;
51305 } else {
51307 }
51308#else
51310#endif
51311
51312 /* remove value */
51313 DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
51314 (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
51315 DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
51316 DUK_MEMSET((void *) &tv_tmp, 0, sizeof(tv_tmp));
51317 DUK_TVAL_SET_UNDEFINED(&tv_tmp);
51318 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
51319 h_get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
51320 h_set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
51321 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
51322 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
51323 } else {
51324 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
51325 DUK_TVAL_SET_TVAL(&tv_tmp, tv);
51327 }
51328#if 0
51329 /* Not strictly necessary because if key == NULL, flag MUST be ignored. */
51330 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
51331#endif
51332
51333 /* remove key */
51334 DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
51335 (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
51336 DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
51337 DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
51338 DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
51339
51340 /* Do decrefs only with safe pointers to avoid side effects
51341 * disturbing e_idx.
51342 */
51343 DUK_TVAL_DECREF(thr, &tv_tmp);
51344 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_get);
51345 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_set);
51346 DUK_HSTRING_DECREF(thr, key);
51347 goto success;
51348 }
51349
51351
51352 success:
51353 /*
51354 * Argument exotic [[Delete]] behavior (E5 Section 10.6) is
51355 * a post-check, keeping arguments internal 'map' in sync with
51356 * any successful deletes (note that property does not need to
51357 * exist for delete to 'succeed').
51358 *
51359 * Delete key from 'map'. Since 'map' only contains array index
51360 * keys, we can use arr_idx for a fast skip.
51361 */
51362
51363 DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
51364
51366 /* Note: only numbered indices are relevant, so arr_idx fast reject
51367 * is good (this is valid unless there are more than 4**32-1 arguments).
51368 */
51369
51370 DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
51371
51372 /* Note: we can reuse 'desc' here */
51373 (void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
51374 }
51375
51376 DUK_DDD(DUK_DDDPRINT("delete successful"));
51377 return 1;
51378
51379 fail_virtual:
51380 DUK_DDD(DUK_DDDPRINT("delete failed: property found, force flag, but virtual"));
51381
51382 if (throw_flag) {
51384 }
51385 return 0;
51386
51387 fail_not_configurable:
51388 DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
51389
51390 if (throw_flag) {
51392 }
51393 return 0;
51394}
51395
51396/*
51397 * DELPROP: Ecmascript property deletion.
51398 */
51399
51401 duk_context *ctx = (duk_context *) thr;
51402 duk_hstring *key = NULL;
51403#if defined(DUK_USE_ES6_PROXY)
51404 duk_propdesc desc;
51405#endif
51406 duk_int_t entry_top;
51407 duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
51408 duk_bool_t rc;
51409
51410 DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
51411 (void *) thr, (void *) tv_obj, (void *) tv_key,
51412 (duk_tval *) tv_obj, (duk_tval *) tv_key));
51413
51414 DUK_ASSERT(ctx != NULL);
51415 DUK_ASSERT(thr != NULL);
51416 DUK_ASSERT(thr->heap != NULL);
51417 DUK_ASSERT(tv_obj != NULL);
51418 DUK_ASSERT(tv_key != NULL);
51419
51421
51422 /* Storing the entry top is cheaper here to ensure stack is correct at exit,
51423 * as there are several paths out.
51424 */
51425 entry_top = duk_get_top(ctx);
51426
51427 if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
51428 DUK_TVAL_IS_NULL(tv_obj)) {
51429 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
51430 goto fail_invalid_base_uncond;
51431 }
51432
51433 duk_push_tval(ctx, tv_obj);
51434 duk_push_tval(ctx, tv_key);
51435
51436 tv_obj = DUK_GET_TVAL_NEGIDX(ctx, -2);
51437 if (DUK_TVAL_IS_OBJECT(tv_obj)) {
51438 duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
51439 DUK_ASSERT(obj != NULL);
51440
51441#if defined(DUK_USE_ES6_PROXY)
51443 duk_hobject *h_target;
51444 duk_bool_t tmp_bool;
51445
51446 /* Note: proxy handling must happen before key is string coerced. */
51447
51448 if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
51449 /* -> [ ... trap handler ] */
51450 DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
51451 duk_push_hobject(ctx, h_target); /* target */
51452 duk_push_tval(ctx, tv_key); /* P */
51453 duk_call_method(ctx, 2 /*nargs*/);
51454 tmp_bool = duk_to_boolean(ctx, -1);
51455 duk_pop(ctx);
51456 if (!tmp_bool) {
51457 goto fail_proxy_rejected; /* retval indicates delete failed */
51458 }
51459
51460 /* Target object must be checked for a conflicting
51461 * non-configurable property.
51462 */
51463 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
51464 DUK_ASSERT(key != NULL);
51465
51466 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
51467 int desc_reject;
51468
51469 DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
51470 "conflicting property; desc.flags=0x%08lx, "
51471 "desc.get=%p, desc.set=%p",
51472 (duk_heaphdr *) key, (unsigned long) desc.flags,
51473 (void *) desc.get, (void *) desc.set));
51474
51475 desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
51476 if (desc_reject) {
51477 /* unconditional */
51479 }
51480 }
51481 rc = 1; /* success */
51482 goto done_rc;
51483 }
51484
51485 obj = h_target; /* resume delete to target */
51486 }
51487#endif /* DUK_USE_ES6_PROXY */
51488
51489 duk_to_string(ctx, -1);
51490 key = duk_get_hstring(ctx, -1);
51491 DUK_ASSERT(key != NULL);
51492
51493 rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
51494 goto done_rc;
51495 } else if (DUK_TVAL_IS_STRING(tv_obj)) {
51496 /* XXX: unnecessary string coercion for array indices,
51497 * intentional to keep small.
51498 */
51499 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
51500 DUK_ASSERT(h != NULL);
51501
51502 duk_to_string(ctx, -1);
51503 key = duk_get_hstring(ctx, -1);
51504 DUK_ASSERT(key != NULL);
51505
51506 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51507 goto fail_not_configurable;
51508 }
51509
51510 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51511
51512 if (arr_idx != DUK__NO_ARRAY_INDEX &&
51513 arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
51514 goto fail_not_configurable;
51515 }
51516 } else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
51517 /* XXX: unnecessary string coercion for array indices,
51518 * intentional to keep small; some overlap with string
51519 * handling.
51520 */
51521 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
51522 DUK_ASSERT(h != NULL);
51523
51524 duk_to_string(ctx, -1);
51525 key = duk_get_hstring(ctx, -1);
51526 DUK_ASSERT(key != NULL);
51527
51528 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51529 goto fail_not_configurable;
51530 }
51531
51532 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51533
51534 if (arr_idx != DUK__NO_ARRAY_INDEX &&
51535 arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
51536 goto fail_not_configurable;
51537 }
51538 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
51539 /* Lightfunc virtual properties are non-configurable, so
51540 * reject if match any of them.
51541 */
51542
51543 duk_to_string(ctx, -1);
51544 key = duk_get_hstring(ctx, -1);
51545 DUK_ASSERT(key != NULL);
51546
51547 if (duk__key_is_lightfunc_ownprop(thr, key)) {
51548 goto fail_not_configurable;
51549 }
51550 }
51551
51552 /* non-object base, no offending virtual property */
51553 rc = 1;
51554 goto done_rc;
51555
51556 done_rc:
51557 duk_set_top(ctx, entry_top);
51558 return rc;
51559
51560 fail_invalid_base_uncond:
51561 /* Note: unconditional throw */
51562 DUK_ASSERT(duk_get_top(ctx) == entry_top);
51563#if defined(DUK_USE_PARANOID_ERRORS)
51565#else
51566 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
51568#endif
51569 return 0;
51570
51571#if defined(DUK_USE_ES6_PROXY)
51572 fail_proxy_rejected:
51573 if (throw_flag) {
51575 }
51576 duk_set_top(ctx, entry_top);
51577 return 0;
51578#endif
51579
51580 fail_not_configurable:
51581 if (throw_flag) {
51583 }
51584 duk_set_top(ctx, entry_top);
51585 return 0;
51586}
51587
51588/*
51589 * Internal helper to define a property with specific flags, ignoring
51590 * normal semantics such as extensibility, write protection etc.
51591 * Overwrites any existing value and attributes unless caller requests
51592 * that value only be updated if it doesn't already exists.
51593 *
51594 * Does not support:
51595 * - virtual properties (error if write attempted)
51596 * - getter/setter properties (error if write attempted)
51597 * - non-default (!= WEC) attributes for array entries (error if attempted)
51598 * - array abandoning: if array part exists, it is always extended
51599 * - array 'length' updating
51600 *
51601 * Stack: [... in_val] -> []
51602 *
51603 * Used for e.g. built-in initialization and environment record
51604 * operations.
51605 */
51606
51608 duk_context *ctx = (duk_context *) thr;
51609 duk_propdesc desc;
51610 duk_uint32_t arr_idx;
51611 duk_int_t e_idx;
51612 duk_tval *tv1 = NULL;
51613 duk_tval *tv2 = NULL;
51614 duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK; /* mask out flags not actually stored */
51615
51616 DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
51617 (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
51618 (unsigned long) flags, (duk_tval *) duk_get_tval(ctx, -1)));
51619
51620 DUK_ASSERT(thr != NULL);
51621 DUK_ASSERT(thr->heap != NULL);
51622 DUK_ASSERT(obj != NULL);
51623 DUK_ASSERT(key != NULL);
51626 DUK_ASSERT(duk_is_valid_index(ctx, -1)); /* contains value */
51627
51628 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
51629
51630 if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
51631 if (desc.e_idx >= 0) {
51632 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51633 DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
51634 goto pop_exit;
51635 }
51636 DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
51637 if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
51638 DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
51639 goto error_internal;
51640 }
51641
51642 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
51643 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
51644 } else if (desc.a_idx >= 0) {
51645 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51646 DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
51647 goto pop_exit;
51648 }
51649 DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
51650 if (propflags != DUK_PROPDESC_FLAGS_WEC) {
51651 DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
51652 (unsigned long) propflags));
51653 goto error_internal;
51654 }
51655
51656 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
51657 } else {
51658 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51659 DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
51660 goto pop_exit;
51661 }
51662 DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> failure"));
51663 goto error_virtual;
51664 }
51665
51666 goto write_value;
51667 }
51668
51669 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
51670 if (arr_idx != DUK__NO_ARRAY_INDEX) {
51671 DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
51672 DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
51673
51674 /* always grow the array, no sparse / abandon support here */
51675 if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
51676 duk__grow_props_for_array_item(thr, obj, arr_idx);
51677 }
51678
51679 DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
51680 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
51681 goto write_value;
51682 }
51683 }
51684
51685 DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
51686 e_idx = duk__alloc_entry_checked(thr, obj, key); /* increases key refcount */
51687 DUK_ASSERT(e_idx >= 0);
51688 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
51689 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
51690 /* new entry: previous value is garbage; set to undefined to share write_value */
51692 goto write_value;
51693
51694 write_value:
51695 /* tv1 points to value storage */
51696
51697 tv2 = duk_require_tval(ctx, -1); /* late lookup, avoid side effects */
51698 DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
51699 (duk_tval *) tv1, (duk_tval *) tv2));
51700
51701 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
51702 goto pop_exit;
51703
51704 pop_exit:
51705 duk_pop(ctx); /* remove in_val */
51706 return;
51707
51708 error_internal:
51710 return;
51711
51712 error_virtual:
51714 return;
51715}
51716
51717/*
51718 * Fast path for defining array indexed values without interning the key.
51719 * This is used by e.g. code for Array prototype and traceback creation so
51720 * must avoid interning.
51721 */
51722
51724 duk_context *ctx = (duk_context *) thr;
51725 duk_hstring *key;
51726 duk_tval *tv1, *tv2;
51727
51728 DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
51729 "arr_idx=%ld, flags=0x%02lx, val=%!T",
51730 (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
51731 (duk_tval *) duk_get_tval(ctx, -1)));
51732
51733 DUK_ASSERT(thr != NULL);
51734 DUK_ASSERT(thr->heap != NULL);
51735 DUK_ASSERT(obj != NULL);
51737
51738 if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
51739 arr_idx != DUK__NO_ARRAY_INDEX &&
51740 flags == DUK_PROPDESC_FLAGS_WEC) {
51741 DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0); /* covered by comparison */
51742
51743 DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
51744
51745 /* always grow the array, no sparse / abandon support here */
51746 if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
51747 duk__grow_props_for_array_item(thr, obj, arr_idx);
51748 }
51749
51750 DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
51751 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
51752 tv2 = duk_require_tval(ctx, -1);
51753
51754 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
51755
51756 duk_pop(ctx); /* [ ...val ] -> [ ... ] */
51757 return;
51758 }
51759
51760 DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
51761
51762 duk_push_uint(ctx, (duk_uint_t) arr_idx);
51763 key = duk_to_hstring(ctx, -1);
51764 DUK_ASSERT(key != NULL);
51765 duk_insert(ctx, -2); /* [ ... val key ] -> [ ... key val ] */
51766
51767 duk_hobject_define_property_internal(thr, obj, key, flags);
51768
51769 duk_pop(ctx); /* [ ... key ] -> [ ... ] */
51770}
51771
51772/*
51773 * Internal helper for defining an accessor property, ignoring
51774 * normal semantics such as extensibility, write protection etc.
51775 * Overwrites any existing value and attributes. This is called
51776 * very rarely, so the implementation first sets a value to undefined
51777 * and then changes the entry to an accessor (this is to save code space).
51778 */
51779
51781 duk_context *ctx = (duk_context *) thr;
51782 duk_int_t e_idx;
51783 duk_int_t h_idx;
51784
51785 DUK_DDD(DUK_DDDPRINT("define new accessor (internal): thr=%p, obj=%!O, key=%!O, "
51786 "getter=%!O, setter=%!O, flags=0x%02lx",
51787 (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
51788 (duk_heaphdr *) getter, (duk_heaphdr *) setter,
51789 (unsigned long) propflags));
51790
51791 DUK_ASSERT(thr != NULL);
51792 DUK_ASSERT(thr->heap != NULL);
51793 DUK_ASSERT(obj != NULL);
51794 DUK_ASSERT(key != NULL);
51795 DUK_ASSERT((propflags & ~DUK_PROPDESC_FLAGS_MASK) == 0);
51796 /* setter and/or getter may be NULL */
51798
51800
51801 /* force the property to 'undefined' to create a slot for it */
51802 duk_push_undefined(ctx);
51803 duk_hobject_define_property_internal(thr, obj, key, propflags);
51804 duk_hobject_find_existing_entry(thr->heap, obj, key, &e_idx, &h_idx);
51805 DUK_DDD(DUK_DDDPRINT("accessor slot: e_idx=%ld, h_idx=%ld", (long) e_idx, (long) h_idx));
51806 DUK_ASSERT(e_idx >= 0);
51807 DUK_ASSERT((duk_uint32_t) e_idx < DUK_HOBJECT_GET_ENEXT(obj));
51808
51809 /* no need to decref, as previous value is 'undefined' */
51810 DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, e_idx);
51811 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, getter);
51812 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, setter);
51813 DUK_HOBJECT_INCREF_ALLOWNULL(thr, getter);
51814 DUK_HOBJECT_INCREF_ALLOWNULL(thr, setter);
51815}
51816
51817/*
51818 * Internal helpers for managing object 'length'
51820
51821/* XXX: awkward helpers */
51822
51823DUK_INTERNAL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length) {
51824 duk_context *ctx = (duk_context *) thr;
51825 duk_push_hobject(ctx, obj);
51827 duk_push_u32(ctx, length);
51828 (void) duk_hobject_putprop(thr,
51829 DUK_GET_TVAL_NEGIDX(ctx, -3),
51830 DUK_GET_TVAL_NEGIDX(ctx, -2),
51831 DUK_GET_TVAL_NEGIDX(ctx, -1),
51832 0);
51833 duk_pop_n(ctx, 3);
51834}
51835
51837 duk_hobject_set_length(thr, obj, 0);
51838}
51839
51841 duk_context *ctx = (duk_context *) thr;
51842 duk_double_t val;
51843 duk_push_hobject(ctx, obj);
51846 DUK_GET_TVAL_NEGIDX(ctx, -2),
51847 DUK_GET_TVAL_NEGIDX(ctx, -1));
51848 val = duk_to_number(ctx, -1);
51849 duk_pop_n(ctx, 3);
51850 if (val >= 0.0 && val < DUK_DOUBLE_2TO32) {
51851 return (duk_uint32_t) val;
51852 }
51853 return 0;
51854}
51855
51856/*
51857 * Object.getOwnPropertyDescriptor() (E5 Sections 15.2.3.3, 8.10.4)
51858 *
51859 * This is an actual function call.
51860 */
51861
51863 duk_hthread *thr = (duk_hthread *) ctx;
51864 duk_hobject *obj;
51865 duk_hstring *key;
51866 duk_propdesc pd;
51867 duk_bool_t rc;
51868
51869 DUK_ASSERT(ctx != NULL);
51870 DUK_ASSERT(thr != NULL);
51871 DUK_ASSERT(thr->heap != NULL);
51872
51874 (void) duk_to_string(ctx, 1);
51875 key = duk_require_hstring(ctx, 1);
51876
51877 DUK_ASSERT(obj != NULL);
51878 DUK_ASSERT(key != NULL);
51879
51881
51883 if (!rc) {
51884 duk_push_undefined(ctx);
51885
51886 /* [obj key undefined] */
51887 return 1;
51888 }
51889
51890 duk_push_object(ctx);
51891
51892 /* [obj key value desc] */
51893
51894 if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
51895 /* If a setter/getter is missing (undefined), the descriptor must
51896 * still have the property present with the value 'undefined'.
51897 */
51898 if (pd.get) {
51899 duk_push_hobject(ctx, pd.get);
51900 } else {
51901 duk_push_undefined(ctx);
51902 }
51904 if (pd.set) {
51905 duk_push_hobject(ctx, pd.set);
51906 } else {
51907 duk_push_undefined(ctx);
51908 }
51910 } else {
51911 duk_dup(ctx, -2); /* [obj key value desc value] */
51915
51916 /* [obj key value desc] */
51917 }
51922
51923 /* [obj key value desc] */
51924 return 1;
51925}
51927/*
51928 * NormalizePropertyDescriptor() related helper.
51929 *
51930 * Internal helper which validates and normalizes a property descriptor
51931 * represented as an Ecmascript object (e.g. argument to defineProperty()).
51932 * The output of this conversion is a set of defprop_flags and possibly
51933 * some values pushed on the value stack; some subset of: property value,
51934 * getter, setter. Caller must manage stack top carefully because the
51935 * number of values pushed depends on the input property descriptor.
51936 *
51937 * The original descriptor object must not be altered in the process.
51938 */
51939
51940/* XXX: very basic optimization -> duk_get_prop_stridx_top */
51941
51944 duk_idx_t idx_in,
51945 duk_uint_t *out_defprop_flags,
51946 duk_idx_t *out_idx_value,
51947 duk_hobject **out_getter,
51948 duk_hobject **out_setter) {
51949 duk_hthread *thr = (duk_hthread *) ctx;
51950 duk_idx_t idx_value = -1;
51951 duk_hobject *getter = NULL;
51952 duk_hobject *setter = NULL;
51953 duk_bool_t is_data_desc = 0;
51954 duk_bool_t is_acc_desc = 0;
51955 duk_uint_t defprop_flags = 0;
51956
51957 DUK_ASSERT(ctx != NULL);
51958 DUK_ASSERT(out_defprop_flags != NULL);
51959 DUK_ASSERT(out_idx_value != NULL);
51960 DUK_ASSERT(out_getter != NULL);
51961 DUK_ASSERT(out_setter != NULL);
51962
51963 /* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
51964 idx_in = duk_require_normalize_index(ctx, idx_in);
51965 (void) duk_require_hobject(ctx, idx_in);
51966
51967 /* The coercion order must match the ToPropertyDescriptor() algorithm
51968 * so that side effects in coercion happen in the correct order.
51969 * (This order also happens to be compatible with duk_def_prop(),
51970 * although it doesn't matter in practice.)
51971 */
51972
51973 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_VALUE)) {
51974 is_data_desc = 1;
51975 defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
51976 idx_value = duk_get_top_index(ctx);
51977 /* Leave 'value' on stack */
51978 } else {
51979 duk_pop(ctx);
51980 }
51981
51982 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_WRITABLE)) {
51983 is_data_desc = 1;
51984 if (duk_to_boolean(ctx, -1)) {
51986 } else {
51987 defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
51988 }
51989 }
51990 duk_pop(ctx);
51991
51992 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_GET)) {
51993 duk_tval *tv = duk_require_tval(ctx, -1);
51994 duk_hobject *h_get;
51995
51996 if (DUK_TVAL_IS_UNDEFINED(tv)) {
51997 /* undefined is accepted */
51998 DUK_ASSERT(getter == NULL);
51999 } else {
52000 /* NOTE: lightfuncs are coerced to full functions because
52001 * lightfuncs don't fit into a property value slot. This
52002 * has some side effects, see test-dev-lightfunc-accessor.js.
52003 */
52004 h_get = duk_get_hobject_or_lfunc_coerce(ctx, -1);
52005 if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
52006 goto type_error;
52007 }
52008 getter = h_get;
52009 }
52010 is_acc_desc = 1;
52011 defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
52012 /* Leave 'getter' on stack */
52013 } else {
52014 duk_pop(ctx);
52015 }
52016
52017 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_SET)) {
52018 duk_tval *tv = duk_require_tval(ctx, -1);
52019 duk_hobject *h_set;
52020
52021 if (DUK_TVAL_IS_UNDEFINED(tv)) {
52022 /* undefined is accepted */
52023 DUK_ASSERT(setter == NULL);
52024 } else {
52025 /* NOTE: lightfuncs are coerced to full functions because
52026 * lightfuncs don't fit into a property value slot. This
52027 * has some side effects, see test-dev-lightfunc-accessor.js.
52028 */
52029 h_set = duk_get_hobject_or_lfunc_coerce(ctx, -1);
52030 if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
52031 goto type_error;
52032 }
52033 setter = h_set;
52034 }
52035 is_acc_desc = 1;
52036 defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
52037 /* Leave 'setter' on stack */
52038 } else {
52039 duk_pop(ctx);
52040 }
52041
52042 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_ENUMERABLE)) {
52043 if (duk_to_boolean(ctx, -1)) {
52045 } else {
52046 defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
52047 }
52048 }
52049 duk_pop(ctx);
52050
52051 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_CONFIGURABLE)) {
52052 if (duk_to_boolean(ctx, -1)) {
52054 } else {
52055 defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
52056 }
52057 }
52058 duk_pop(ctx);
52059
52060 if (is_data_desc && is_acc_desc) {
52061 goto type_error;
52062 }
52063
52064 *out_defprop_flags = defprop_flags;
52065 *out_idx_value = idx_value;
52066 *out_getter = getter;
52067 *out_setter = setter;
52068
52069 /* [ ... value? getter? setter? ] */
52070 return;
52071
52072 type_error:
52074}
52075
52076/*
52077 * Object.defineProperty() related helper (E5 Section 15.2.3.6)
52078 *
52079 * Inlines all [[DefineOwnProperty]] exotic behaviors.
52080 *
52081 * Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
52082 * implemented directly, but Object.defineProperty() serves its purpose.
52083 * We don't need the [[DefineOwnProperty]] internally and we don't have a
52084 * property descriptor with 'missing values' so it's easier to avoid it
52085 * entirely.
52086 *
52087 * Note: this is only called for actual objects, not primitive values.
52088 * This must support virtual properties for full objects (e.g. Strings)
52089 * but not for plain values (e.g. strings). Lightfuncs, even though
52090 * primitive in a sense, are treated like objects and accepted as target
52091 * values.
52092 */
52093
52094/* XXX: this is a major target for size optimization */
52097 duk_uint_t defprop_flags,
52098 duk_hobject *obj,
52099 duk_hstring *key,
52100 duk_idx_t idx_value,
52101 duk_hobject *get,
52102 duk_hobject *set) {
52103 duk_hthread *thr = (duk_hthread *) ctx;
52104 duk_uint32_t arr_idx;
52105 duk_tval tv;
52106 duk_bool_t has_enumerable;
52107 duk_bool_t has_configurable;
52108 duk_bool_t has_writable;
52109 duk_bool_t has_value;
52110 duk_bool_t has_get;
52111 duk_bool_t has_set;
52112 duk_bool_t is_enumerable;
52113 duk_bool_t is_configurable;
52114 duk_bool_t is_writable;
52115 duk_bool_t throw_flag;
52116 duk_bool_t force_flag;
52117 duk_small_uint_t new_flags;
52118 duk_propdesc curr;
52119 duk_uint32_t arridx_new_array_length; /* != 0 => post-update for array 'length' (used when key is an array index) */
52120 duk_uint32_t arrlen_old_len;
52121 duk_uint32_t arrlen_new_len;
52122 duk_bool_t pending_write_protect;
52123
52124 DUK_ASSERT(thr != NULL);
52125 DUK_ASSERT(thr->heap != NULL);
52126 DUK_ASSERT(ctx != NULL);
52127 DUK_ASSERT(obj != NULL);
52128 DUK_ASSERT(key != NULL);
52129 /* idx_value may be < 0 (no value), set and get may be NULL */
52130
52132
52133 /* All the flags fit in 16 bits, so will fit into duk_bool_t. */
52134
52135 has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
52136 has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
52137 has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
52138 has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
52139 has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
52140 has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
52141 is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
52142 is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
52143 is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
52144 throw_flag = 1; /* Object.defineProperty() calls [[DefineOwnProperty]] with Throw=true */
52145 force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
52146
52147 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
52148
52149 arridx_new_array_length = 0;
52150 pending_write_protect = 0;
52151 arrlen_old_len = 0;
52152 arrlen_new_len = 0;
52153
52154 DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
52155 "has_configurable=%ld is_configurable=%ld "
52156 "has_writable=%ld is_writable=%ld "
52157 "has_value=%ld value=%!T "
52158 "has_get=%ld get=%p=%!O "
52159 "has_set=%ld set=%p=%!O "
52160 "arr_idx=%ld",
52161 (long) has_enumerable, (long) is_enumerable,
52162 (long) has_configurable, (long) is_configurable,
52163 (long) has_writable, (long) is_writable,
52164 (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(ctx, idx_value) : NULL),
52165 (long) has_get, (void *) get, (duk_heaphdr *) get,
52166 (long) has_set, (void *) set, (duk_heaphdr *) set,
52167 (long) arr_idx));
52168
52169 /*
52170 * Array exotic behaviors can be implemented at this point. The local variables
52171 * are essentially a 'value copy' of the input descriptor (Desc), which is modified
52172 * by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
52173 */
52174
52175 if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
52176 goto skip_array_exotic;
52177 }
52178
52179 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
52180 /* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
52181 if (!has_value) {
52182 DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
52183 goto skip_array_exotic;
52184 }
52185
52186 DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
52187
52188 /*
52189 * Get old and new length
52190 */
52191
52192 /* Note: reuse 'curr' as a temp propdesc */
52193 arrlen_old_len = duk__get_old_array_length(thr, obj, &curr);
52194
52195 duk_dup(ctx, idx_value);
52196 arrlen_new_len = duk__to_new_array_length_checked(thr);
52197 duk_push_u32(ctx, arrlen_new_len);
52198 duk_replace(ctx, idx_value); /* step 3.e: replace 'Desc.[[Value]]' */
52199
52200 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
52201
52202 if (arrlen_new_len >= arrlen_old_len) {
52203 /* standard behavior, step 3.f.i */
52204 DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
52205 goto skip_array_exotic;
52206 }
52207 DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
52208
52209 /* XXX: consolidated algorithm step 15.f -> redundant? */
52210 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && !force_flag) {
52211 /* Note: 'curr' refers to 'length' propdesc */
52212 goto fail_not_writable_array_length;
52213 }
52214
52215 /* steps 3.h and 3.i */
52216 if (has_writable && !is_writable) {
52217 DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
52218 is_writable = 1;
52219 pending_write_protect = 1;
52220 }
52221
52222 /* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
52223 } else if (arr_idx != DUK__NO_ARRAY_INDEX) {
52224 /* XXX: any chance of unifying this with the 'length' key handling? */
52225
52226 /* E5 Section 15.4.5.1, step 4 */
52227 duk_uint32_t old_len;
52228
52229 /* Note: use 'curr' as a temp propdesc */
52230 old_len = duk__get_old_array_length(thr, obj, &curr);
52231
52232 if (arr_idx >= old_len) {
52233 DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
52234 "(arr_idx=%ld, old_len=%ld)",
52235 (long) arr_idx, (long) old_len));
52236
52237 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
52238 /* Note: 'curr' refers to 'length' propdesc */
52239 goto fail_not_writable_array_length;
52240 }
52241
52242 /* actual update happens once write has been completed without
52243 * error below.
52244 */
52245 DUK_ASSERT(arr_idx != 0xffffffffUL);
52246 arridx_new_array_length = arr_idx + 1;
52247 } else {
52248 DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
52249 "(arr_idx=%ld, old_len=%ld) -> standard behavior",
52250 (long) arr_idx, (long) old_len));
52251 }
52252 }
52253 skip_array_exotic:
52254
52255 /* XXX: There is currently no support for writing buffer object
52256 * indexed elements here. Attempt to do so will succeed and
52257 * write a concrete property into the buffer object. This should
52258 * be fixed at some point but because buffers are a custom feature
52259 * anyway, this is relatively unimportant.
52260 */
52261
52262 /*
52263 * Actual Object.defineProperty() default algorithm.
52264 */
52265
52266 /*
52267 * First check whether property exists; if not, simple case. This covers
52268 * steps 1-4.
52269 */
52270
52271 if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
52272 DUK_DDD(DUK_DDDPRINT("property does not exist"));
52273
52274 if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
52275 goto fail_not_extensible;
52276 }
52277
52278 /* XXX: share final setting code for value and flags? difficult because
52279 * refcount code is different. Share entry allocation? But can't allocate
52280 * until array index checked.
52281 */
52282
52283 /* steps 4.a and 4.b are tricky */
52284 if (has_set || has_get) {
52285 duk_int_t e_idx;
52286
52287 DUK_DDD(DUK_DDDPRINT("create new accessor property"));
52288
52289 DUK_ASSERT(has_set || set == NULL);
52290 DUK_ASSERT(has_get || get == NULL);
52291 DUK_ASSERT(!has_value);
52292 DUK_ASSERT(!has_writable);
52293
52294 new_flags = DUK_PROPDESC_FLAG_ACCESSOR; /* defaults, E5 Section 8.6.1, Table 7 */
52295 if (has_enumerable && is_enumerable) {
52296 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52297 }
52298 if (has_configurable && is_configurable) {
52299 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52300 }
52301
52302 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
52303 DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
52305 }
52306
52307 /* write to entry part */
52308 e_idx = duk__alloc_entry_checked(thr, obj, key);
52309 DUK_ASSERT(e_idx >= 0);
52310
52311 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
52312 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
52315
52316 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
52317 goto success_exotics;
52318 } else {
52319 duk_int_t e_idx;
52320 duk_tval *tv2;
52321
52322 DUK_DDD(DUK_DDDPRINT("create new data property"));
52323
52324 DUK_ASSERT(!has_set);
52325 DUK_ASSERT(!has_get);
52326
52327 new_flags = 0; /* defaults, E5 Section 8.6.1, Table 7 */
52328 if (has_writable && is_writable) {
52329 new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
52330 }
52331 if (has_enumerable && is_enumerable) {
52332 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52333 }
52334 if (has_configurable && is_configurable) {
52335 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52336 }
52337 if (has_value) {
52338 duk_tval *tv_tmp = duk_require_tval(ctx, idx_value);
52339 DUK_TVAL_SET_TVAL(&tv, tv_tmp);
52340 } else {
52341 DUK_TVAL_SET_UNDEFINED(&tv); /* default value */
52342 }
52343
52344 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
52345 if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
52346#if 0
52347 DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
52348 /* may become sparse...*/
52349#endif
52350 /* XXX: handling for array part missing now; this doesn't affect
52351 * compliance but causes array entry writes using defineProperty()
52352 * to always abandon array part.
52353 */
52354 }
52355 DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
52357 /* fall through */
52358 }
52359
52360 /* write to entry part */
52361 e_idx = duk__alloc_entry_checked(thr, obj, key);
52362 DUK_ASSERT(e_idx >= 0);
52363 tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
52364 DUK_TVAL_SET_TVAL(tv2, &tv);
52365 DUK_TVAL_INCREF(thr, tv2);
52366
52367 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
52368 goto success_exotics;
52369 }
52371 }
52372
52373 /* we currently assume virtual properties are not configurable (as none of them are) */
52374 DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
52375
52376 /* [obj key desc value get set curr_value] */
52377
52378 /*
52379 * Property already exists. Steps 5-6 detect whether any changes need
52380 * to be made.
52381 */
52382
52383 if (has_enumerable) {
52384 if (is_enumerable) {
52385 if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
52386 goto need_check;
52387 }
52388 } else {
52390 goto need_check;
52391 }
52392 }
52393 }
52394 if (has_configurable) {
52395 if (is_configurable) {
52396 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
52397 goto need_check;
52398 }
52399 } else {
52401 goto need_check;
52402 }
52403 }
52404 }
52405 if (has_value) {
52406 duk_tval *tmp1;
52407 duk_tval *tmp2;
52408
52409 /* attempt to change from accessor to data property */
52410 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52411 goto need_check;
52412 }
52413
52414 tmp1 = duk_require_tval(ctx, -1); /* curr value */
52415 tmp2 = duk_require_tval(ctx, idx_value); /* new value */
52416 if (!duk_js_samevalue(tmp1, tmp2)) {
52417 goto need_check;
52418 }
52419 }
52420 if (has_writable) {
52421 /* attempt to change from accessor to data property */
52422 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52423 goto need_check;
52424 }
52425
52426 if (is_writable) {
52427 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
52428 goto need_check;
52429 }
52430 } else {
52431 if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
52432 goto need_check;
52433 }
52434 }
52435 }
52436 if (has_set) {
52437 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52438 if (set != curr.set) {
52439 goto need_check;
52440 }
52441 } else {
52442 goto need_check;
52443 }
52444 }
52445 if (has_get) {
52446 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52447 if (get != curr.get) {
52448 goto need_check;
52449 }
52450 } else {
52451 goto need_check;
52452 }
52453 }
52454
52455 /* property exists, either 'desc' is empty, or all values
52456 * match (SameValue)
52457 */
52458 goto success_no_exotics;
52459
52460 need_check:
52461
52462 /*
52463 * Some change(s) need to be made. Steps 7-11.
52464 */
52465
52466 /* shared checks for all descriptor types */
52467 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52468 if (has_configurable && is_configurable) {
52469 goto fail_not_configurable;
52470 }
52471 if (has_enumerable) {
52473 if (!is_enumerable) {
52474 goto fail_not_configurable;
52475 }
52476 } else {
52477 if (is_enumerable) {
52478 goto fail_not_configurable;
52479 }
52480 }
52481 }
52482 }
52483
52484 /* Reject attempt to change virtual properties: not part of the
52485 * standard algorithm, applies currently to e.g. virtual index
52486 * properties of buffer objects (which are virtual but writable).
52487 * (Cannot "force" modification of a virtual property.)
52488 */
52489 if (curr.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
52490 goto fail_virtual;
52491 }
52492
52493 /* Reject attempt to change a read-only object. */
52494#if defined(DUK_USE_ROM_OBJECTS)
52496 DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
52497 goto fail_not_configurable;
52498 }
52499#endif
52500
52501 /* descriptor type specific checks */
52502 if (has_set || has_get) {
52503 /* IsAccessorDescriptor(desc) == true */
52504 DUK_ASSERT(!has_writable);
52505 DUK_ASSERT(!has_value);
52506
52507 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52508 /* curr and desc are accessors */
52509 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52510 if (has_set && set != curr.set) {
52511 goto fail_not_configurable;
52512 }
52513 if (has_get && get != curr.get) {
52514 goto fail_not_configurable;
52515 }
52516 }
52517 } else {
52518 duk_bool_t rc;
52519 duk_tval *tv1;
52520 duk_tval tv_tmp;
52521
52522 /* curr is data, desc is accessor */
52523 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52524 goto fail_not_configurable;
52525 }
52526
52527 DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
52528 if (curr.a_idx >= 0) {
52529 DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
52531 duk_pop(ctx); /* remove old value */
52532 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52533 DUK_UNREF(rc);
52534 DUK_ASSERT(rc != 0);
52535 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52536 }
52537
52539
52540 /* Avoid side effects that might disturb curr.e_idx until
52541 * we're done editing the slot.
52542 */
52543 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52544 DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
52546
52551
52552 DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
52553 (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
52554
52555 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
52556
52557 /* re-lookup to update curr.flags
52558 * XXX: would be faster to update directly
52559 */
52560 duk_pop(ctx); /* remove old value */
52561 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52562 DUK_UNREF(rc);
52563 DUK_ASSERT(rc != 0);
52564 }
52565 } else if (has_value || has_writable) {
52566 /* IsDataDescriptor(desc) == true */
52567 DUK_ASSERT(!has_set);
52568 DUK_ASSERT(!has_get);
52569
52570 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52571 duk_bool_t rc;
52572 duk_hobject *h_get;
52573 duk_hobject *h_set;
52574
52575 /* curr is accessor, desc is data */
52576 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52577 goto fail_not_configurable;
52578 }
52579
52580 /* curr is accessor -> cannot be in array part */
52581 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52582
52583 DUK_DDD(DUK_DDDPRINT("convert property to data property"));
52584
52585 /* Avoid side effects that might disturb curr.e_idx until
52586 * we're done editing the slot.
52587 */
52589 h_get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
52591 h_set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
52593
52597
52598 DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
52599 (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
52600
52601 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_get); /* side effects */
52602 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_set); /* side effects */
52603
52604 /* re-lookup to update curr.flags
52605 * XXX: would be faster to update directly
52606 */
52607 duk_pop(ctx); /* remove old value */
52608 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52609 DUK_UNREF(rc);
52610 DUK_ASSERT(rc != 0);
52611 } else {
52612 /* curr and desc are data */
52613 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52614 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
52615 goto fail_not_configurable;
52616 }
52617 /* Note: changing from writable to non-writable is OK */
52618 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
52619 duk_tval *tmp1 = duk_require_tval(ctx, -1); /* curr value */
52620 duk_tval *tmp2 = duk_require_tval(ctx, idx_value); /* new value */
52621 if (!duk_js_samevalue(tmp1, tmp2)) {
52622 goto fail_not_configurable;
52623 }
52624 }
52625 }
52626 }
52627 } else {
52628 /* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
52629 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
52630 * allowed at this point.
52631 */
52632
52633 DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
52634 }
52635
52636 /*
52637 * Start doing property attributes updates. Steps 12-13.
52638 *
52639 * Start by computing new attribute flags without writing yet.
52640 * Property type conversion is done above if necessary.
52641 */
52642
52643 new_flags = curr.flags;
52644
52645 if (has_enumerable) {
52646 if (is_enumerable) {
52647 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52648 } else {
52649 new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
52650 }
52651 }
52652 if (has_configurable) {
52653 if (is_configurable) {
52654 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52655 } else {
52656 new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
52657 }
52658 }
52659 if (has_writable) {
52660 if (is_writable) {
52661 new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
52662 } else {
52663 new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
52664 }
52665 }
52666
52667 /* XXX: write protect after flag? -> any chance of handling it here? */
52668
52669 DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
52670 (unsigned long) new_flags));
52671
52672 /*
52673 * Check whether we need to abandon an array part (if it exists)
52674 */
52675
52676 if (curr.a_idx >= 0) {
52677 duk_bool_t rc;
52678
52679 DUK_ASSERT(curr.e_idx < 0);
52680
52681 if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
52682 duk_tval *tv1, *tv2;
52683
52684 DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
52685
52686 DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC); /* must have been, since in array part */
52687 DUK_ASSERT(!has_set);
52688 DUK_ASSERT(!has_get);
52689
52690 tv2 = duk_require_tval(ctx, idx_value);
52691 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
52692 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
52693 goto success_exotics;
52694 }
52695
52696 DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
52698 duk_pop(ctx); /* remove old value */
52699 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52700 DUK_UNREF(rc);
52701 DUK_ASSERT(rc != 0);
52702 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52703 }
52704
52705 DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
52706
52707 /* array case is handled comprehensively above */
52708 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52709
52710 DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
52711 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
52712
52713 if (has_set) {
52714 duk_hobject *tmp;
52715
52716 DUK_DDD(DUK_DDDPRINT("update existing property setter"));
52718
52719 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
52720 DUK_UNREF(tmp);
52721 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
52723 DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects */
52724 }
52725 if (has_get) {
52726 duk_hobject *tmp;
52727
52728 DUK_DDD(DUK_DDDPRINT("update existing property getter"));
52730
52731 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
52732 DUK_UNREF(tmp);
52733 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
52735 DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects */
52736 }
52737 if (has_value) {
52738 duk_tval *tv1, *tv2;
52739
52740 DUK_DDD(DUK_DDDPRINT("update existing property value"));
52742
52743 tv2 = duk_require_tval(ctx, idx_value);
52744 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52745 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
52746 }
52747
52748 /*
52749 * Standard algorithm succeeded without errors, check for exotic post-behaviors.
52750 *
52751 * Arguments exotic behavior in E5 Section 10.6 occurs after the standard
52752 * [[DefineOwnProperty]] has completed successfully.
52753 *
52754 * Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
52755 * prior to the default [[DefineOwnProperty]], but:
52756 * - for an array index key (e.g. "10") the final 'length' update occurs here
52757 * - for 'length' key the element deletion and 'length' update occurs here
52758 */
52759
52760 success_exotics:
52761
52762 /* [obj key desc value get set curr_value] */
52763
52765 if (arridx_new_array_length > 0) {
52766 duk_tval *tmp;
52767 duk_bool_t rc;
52768
52769 /*
52770 * Note: zero works as a "no update" marker because the new length
52771 * can never be zero after a new property is written.
52772 */
52773
52774 /* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
52775
52776 DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
52777 (long) arridx_new_array_length));
52778
52779 /* Note: reuse 'curr' */
52780 rc = duk__get_own_propdesc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &curr, 0 /*flags*/); /* don't push value */
52781 DUK_UNREF(rc);
52782 DUK_ASSERT(rc != 0);
52783 DUK_ASSERT(curr.e_idx >= 0);
52784
52785 tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52787 /* no need for decref/incref because value is a number */
52788 DUK_TVAL_SET_FASTINT_U32(tmp, arridx_new_array_length);
52789 }
52790 if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
52791 /*
52792 * E5 Section 15.4.5.1, steps 3.k - 3.n. The order at the end combines
52793 * the error case 3.l.iii and the success case 3.m-3.n.
52794 *
52795 * Note: 'length' is always in entries part, so no array abandon issues for
52796 * 'writable' update.
52797 */
52798
52799 /* XXX: investigate whether write protect can be handled above, if we
52800 * just update length here while ignoring its protected status
52801 */
52802
52803 duk_tval *tmp;
52804 duk_uint32_t result_len;
52805 duk_bool_t rc;
52806
52807 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
52808 "doing array element deletion and length update"));
52809
52810 rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
52811
52812 /* update length (curr points to length, and we assume it's still valid) */
52813 DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
52814
52815 DUK_ASSERT(curr.e_idx >= 0);
52817 tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52819 /* no decref needed for a number */
52820 DUK_TVAL_SET_FASTINT_U32(tmp, result_len);
52822
52823 if (pending_write_protect) {
52824 DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
52826 }
52827
52828 /*
52829 * XXX: shrink array allocation or entries compaction here?
52830 */
52831
52832 if (!rc) {
52833 goto fail_array_length_partial;
52834 }
52835 }
52836 } else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
52837 duk_hobject *map;
52838 duk_hobject *varenv;
52839
52840 DUK_ASSERT(arridx_new_array_length == 0);
52841 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)); /* traits are separate; in particular, arguments not an array */
52842
52843 map = NULL;
52844 varenv = NULL;
52845 if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
52846 goto success_no_exotics;
52847 }
52848 DUK_ASSERT(map != NULL);
52849 DUK_ASSERT(varenv != NULL);
52850
52851 /* [obj key desc value get set curr_value varname] */
52852
52853 if (has_set || has_get) {
52854 /* = IsAccessorDescriptor(Desc) */
52855 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
52856 "changed to an accessor, delete arguments binding"));
52857
52858 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
52859 } else {
52860 /* Note: this order matters (final value before deleting map entry must be done) */
52861 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
52862 "check for value update / binding deletion"));
52863
52864 if (has_value) {
52865 duk_hstring *varname;
52866
52867 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
52868 "update bound value (variable/argument)"));
52869
52870 varname = duk_require_hstring(ctx, -1);
52871 DUK_ASSERT(varname != NULL);
52872
52873 DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
52874 "key=%!O, varname=%!O, value=%!T",
52875 (duk_heaphdr *) key,
52876 (duk_heaphdr *) varname,
52877 (duk_tval *) duk_require_tval(ctx, idx_value)));
52878
52879 /* strict flag for putvar comes from our caller (currently: fixed) */
52880 duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, idx_value), throw_flag);
52881 }
52882 if (has_writable && !is_writable) {
52883 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
52884 "changed to non-writable, delete arguments binding"));
52885
52886 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
52887 }
52888 }
52889
52890 /* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
52891 * but this doesn't matter now.
52892 */
52893 }
52894
52895 success_no_exotics:
52896 return;
52897
52898 fail_virtual:
52900 return;
52901
52902 fail_not_writable_array_length:
52904 return;
52905
52906 fail_not_extensible:
52908 return;
52909
52910 fail_not_configurable:
52912 return;
52913
52914 fail_array_length_partial:
52916 return;
52917}
52918
52919/*
52920 * Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
52921 */
52922
52924 duk_hthread *thr = (duk_hthread *) ctx;
52925 duk_hstring *h_v;
52926 duk_hobject *h_obj;
52927 duk_propdesc desc;
52928 duk_bool_t ret;
52929
52930 /* coercion order matters */
52931 h_v = duk_to_hstring(ctx, 0);
52932 DUK_ASSERT(h_v != NULL);
52933
52935 DUK_ASSERT(h_obj != NULL);
52936
52937 ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/); /* don't push value */
52938
52939 duk_push_boolean(ctx, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
52940 return 1;
52942
52943/*
52944 * Object.seal() and Object.freeze() (E5 Sections 15.2.3.8 and 15.2.3.9)
52945 *
52946 * Since the algorithms are similar, a helper provides both functions.
52947 * Freezing is essentially sealing + making plain properties non-writable.
52948 *
52949 * Note: virtual (non-concrete) properties which are non-configurable but
52950 * writable would pose some problems, but such properties do not currently
52951 * exist (all virtual properties are non-configurable and non-writable).
52952 * If they did exist, the non-configurability does NOT prevent them from
52953 * becoming non-writable. However, this change should be recorded somehow
52954 * so that it would turn up (e.g. when getting the property descriptor),
52955 * requiring some additional flags in the object.
52956 */
52957
52960
52961 DUK_ASSERT(thr != NULL);
52962 DUK_ASSERT(thr->heap != NULL);
52963 DUK_ASSERT(obj != NULL);
52964
52966
52967#if defined(DUK_USE_ROM_OBJECTS)
52969 DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
52971 }
52972#endif
52973
52974 /*
52975 * Abandon array part because all properties must become non-configurable.
52976 * Note that this is now done regardless of whether this is always the case
52977 * (skips check, but performance problem if caller would do this many times
52978 * for the same object; not likely).
52979 */
52980
52983
52984 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
52985 duk_uint8_t *fp;
52986
52987 /* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
52988 DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
52989
52990 /* avoid multiple computations of flags address; bypasses macros */
52991 fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
52992 if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
52994 } else {
52995 *fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
52996 }
52997 }
52998
53000
53001 /* no need to compact since we already did that in duk__abandon_array_checked()
53002 * (regardless of whether an array part existed or not.
53003 */
53004
53005 return;
53006}
53007
53008/*
53009 * Object.isSealed() and Object.isFrozen() (E5 Sections 15.2.3.11, 15.2.3.13)
53010 *
53011 * Since the algorithms are similar, a helper provides both functions.
53012 * Freezing is essentially sealing + making plain properties non-writable.
53013 *
53014 * Note: all virtual (non-concrete) properties are currently non-configurable
53015 * and non-writable (and there are no accessor virtual properties), so they don't
53016 * need to be considered here now.
53017 */
53018
53021
53022 DUK_ASSERT(obj != NULL);
53023 DUK_UNREF(thr);
53024
53025 /* Note: no allocation pressure, no need to check refcounts etc */
53026
53027 /* must not be extensible */
53028 if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
53029 return 0;
53030 }
53031
53032 /* all virtual properties are non-configurable and non-writable */
53033
53034 /* entry part must not contain any configurable properties, or
53035 * writable properties (if is_frozen).
53036 */
53037 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
53038 duk_small_uint_t flags;
53039
53040 if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
53041 continue;
53042 }
53043
53044 /* avoid multiple computations of flags address; bypasses macros */
53045 flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
53046
53047 if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
53048 return 0;
53049 }
53050 if (is_frozen &&
53051 !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
53052 (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
53053 return 0;
53054 }
53055 }
53056
53057 /* array part must not contain any non-unused properties, as they would
53058 * be configurable and writable.
53059 */
53060 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
53061 duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
53062 if (!DUK_TVAL_IS_UNUSED(tv)) {
53063 return 0;
53064 }
53065 }
53066
53067 return 1;
53068}
53069
53070/*
53071 * Object.preventExtensions() and Object.isExtensible() (E5 Sections 15.2.3.10, 15.2.3.13)
53072 *
53073 * Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
53074 * and the Object built-in bindings.
53075 */
53076
53077/* Undefine local defines */
53078
53079#undef DUK__NO_ARRAY_INDEX
53080#undef DUK__HASH_INITIAL
53081#undef DUK__HASH_PROBE_STEP
53082#undef DUK__HASH_UNUSED
53083#undef DUK__HASH_DELETED
53084#undef DUK__VALSTACK_SPACE
53085/*
53086 * Misc support functions
53087 */
53088
53089/* include removed: duk_internal.h */
53090
53092 duk_uint32_t boff;
53093 const duk_uint8_t *p, *p_start, *p_end;
53095
53096 /* Caller must check character offset to be inside the string. */
53097 DUK_ASSERT(thr != NULL);
53098 DUK_ASSERT(h != NULL);
53099 DUK_ASSERT_DISABLE(pos >= 0); /* unsigned */
53101
53102 boff = duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
53103 DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
53104 (long) pos, (long) boff, (duk_heaphdr *) h));
53105 DUK_ASSERT_DISABLE(boff >= 0);
53107
53108 p_start = DUK_HSTRING_GET_DATA(h);
53109 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
53110 p = p_start + boff;
53111 DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
53112 (const void *) p_start, (const void *) p_end,
53113 (const void *) p));
53114
53115 /* This may throw an error though not for valid E5 strings. */
53116 cp = duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
53117 return cp;
53118}
53119
53120#if !defined(DUK_USE_HSTRING_CLEN)
53122 if (DUK_HSTRING_HAS_ASCII(h)) {
53123 /* Most practical strings will go here. */
53124 return DUK_HSTRING_GET_BYTELEN(h);
53125 } else {
53127 }
53128}
53129#endif /* !DUK_USE_HSTRING_CLEN */
53130/*
53131 * duk_hthread allocation and freeing.
53132 */
53133
53134/* include removed: duk_internal.h */
53135
53136/*
53137 * Allocate initial stacks for a thread. Note that 'thr' must be reachable
53138 * as a garbage collection may be triggered by the allocation attempts.
53139 * Returns zero (without leaking memory) if init fails.
53140 */
53141
53143 duk_size_t alloc_size;
53144 duk_size_t i;
53145
53146 DUK_ASSERT(heap != NULL);
53147 DUK_ASSERT(thr != NULL);
53148 DUK_ASSERT(thr->valstack == NULL);
53149 DUK_ASSERT(thr->valstack_end == NULL);
53151 DUK_ASSERT(thr->valstack_top == NULL);
53152 DUK_ASSERT(thr->callstack == NULL);
53153 DUK_ASSERT(thr->catchstack == NULL);
53154
53155 /* valstack */
53156 alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
53157 thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
53158 if (!thr->valstack) {
53159 goto fail;
53160 }
53161 DUK_MEMZERO(thr->valstack, alloc_size);
53163#if !defined(DUK_USE_PREFER_SIZE)
53165#endif
53166 thr->valstack_bottom = thr->valstack;
53167 thr->valstack_top = thr->valstack;
53168
53169 for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
53171 }
53172
53173 /* callstack */
53174 alloc_size = sizeof(duk_activation) * DUK_CALLSTACK_INITIAL_SIZE;
53175 thr->callstack = (duk_activation *) DUK_ALLOC(heap, alloc_size);
53176 if (!thr->callstack) {
53177 goto fail;
53178 }
53179 DUK_MEMZERO(thr->callstack, alloc_size);
53181 DUK_ASSERT(thr->callstack_top == 0);
53182
53183 /* catchstack */
53184 alloc_size = sizeof(duk_catcher) * DUK_CATCHSTACK_INITIAL_SIZE;
53185 thr->catchstack = (duk_catcher *) DUK_ALLOC(heap, alloc_size);
53186 if (!thr->catchstack) {
53187 goto fail;
53188 }
53189 DUK_MEMZERO(thr->catchstack, alloc_size);
53192
53193 return 1;
53194
53195 fail:
53196 DUK_FREE(heap, thr->valstack);
53197 DUK_FREE(heap, thr->callstack);
53198 DUK_FREE(heap, thr->catchstack);
53199
53200 thr->valstack = NULL;
53201 thr->callstack = NULL;
53202 thr->catchstack = NULL;
53203 return 0;
53204}
53205
53206/* For indirect allocs. */
53207
53208DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
53209 duk_hthread *thr = (duk_hthread *) ud;
53210 DUK_UNREF(heap);
53211 return (void *) thr->valstack;
53212}
53213
53215 duk_hthread *thr = (duk_hthread *) ud;
53216 DUK_UNREF(heap);
53217 return (void *) thr->callstack;
53218}
53219
53223 return (void *) thr->catchstack;
53226 * Initialize built-in objects. Current thread must have a valstack
53227 * and initialization errors may longjmp, so a setjmp() catch point
53228 * must exist.
53231/* include removed: duk_internal.h */
53233/*
53234 * Encoding constants, must match genbuiltins.py
53237#define DUK__CLASS_BITS 5
53238#define DUK__BIDX_BITS 7
53239#define DUK__STRIDX_BITS 9 /* XXX: try to optimize to 8 (would now be possible, <200 used) */
53240#define DUK__NATIDX_BITS 8
53241#define DUK__NUM_NORMAL_PROPS_BITS 6
53242#define DUK__NUM_FUNC_PROPS_BITS 6
53243#define DUK__PROP_FLAGS_BITS 3
53244#define DUK__STRING_LENGTH_BITS 8
53245#define DUK__STRING_CHAR_BITS 7
53246#define DUK__LENGTH_PROP_BITS 3
53247#define DUK__NARGS_BITS 3
53248#define DUK__PROP_TYPE_BITS 3
53249#define DUK__MAGIC_BITS 16
53250
53251#define DUK__NARGS_VARARGS_MARKER 0x07
53252#define DUK__NO_CLASS_MARKER 0x00 /* 0 = DUK_HOBJECT_CLASS_UNUSED */
53253#define DUK__NO_BIDX_MARKER 0x7f
53254#define DUK__NO_STRIDX_MARKER 0xff
53255
53256#define DUK__PROP_TYPE_DOUBLE 0
53257#define DUK__PROP_TYPE_STRING 1
53258#define DUK__PROP_TYPE_STRIDX 2
53259#define DUK__PROP_TYPE_BUILTIN 3
53260#define DUK__PROP_TYPE_UNDEFINED 4
53261#define DUK__PROP_TYPE_BOOLEAN_TRUE 5
53262#define DUK__PROP_TYPE_BOOLEAN_FALSE 6
53263#define DUK__PROP_TYPE_ACCESSOR 7
53264
53265/*
53266 * Create built-in objects by parsing an init bitstream generated
53267 * by genbuiltins.py.
53268 */
53269
53270#if defined(DUK_USE_ROM_OBJECTS)
53271#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
53272DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
53273 duk_context *ctx;
53274 duk_hobject *h1;
53275#if defined(DUK_USE_ROM_GLOBAL_CLONE)
53276 duk_hobject *h2;
53277 duk_uint8_t *props;
53278 duk_size_t alloc_size;
53279#endif
53280
53281 ctx = (duk_context *) thr;
53282
53283 /* XXX: refactor into internal helper, duk_clone_hobject() */
53284
53285#if defined(DUK_USE_ROM_GLOBAL_INHERIT)
53286 /* Inherit from ROM-based global object: less RAM usage, less transparent. */
53291 h1 = duk_get_hobject(ctx, -1);
53292 DUK_ASSERT(h1 != NULL);
53293#elif defined(DUK_USE_ROM_GLOBAL_CLONE)
53294 /* Clone the properties of the ROM-based global object to create a
53295 * fully RAM-based global object. Uses more memory than the inherit
53296 * model but more compliant.
53297 */
53302 h1 = duk_get_hobject(ctx, -1);
53303 DUK_ASSERT(h1 != NULL);
53304 h2 = thr->builtins[DUK_BIDX_GLOBAL];
53305 DUK_ASSERT(h2 != NULL);
53306
53307 /* Copy the property table verbatim; this handles attributes etc.
53308 * For ROM objects it's not necessary (or possible) to update
53309 * refcounts so leave them as is.
53310 */
53311 alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h2);
53312 DUK_ASSERT(alloc_size > 0);
53313 props = DUK_ALLOC(thr->heap, alloc_size);
53314 if (!props) {
53316 return;
53317 }
53319 DUK_MEMCPY((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h2), alloc_size);
53320
53321 /* XXX: keep property attributes or tweak them here?
53322 * Properties will now be non-configurable even when they're
53323 * normally configurable for the global object.
53324 */
53325
53327 DUK_HOBJECT_SET_PROPS(thr->heap, h1, props);
53332#else
53333#error internal error in defines
53334#endif
53335
53339 thr->builtins[DUK_BIDX_GLOBAL] = h1;
53340 DUK_HOBJECT_INCREF(thr, h1);
53341 DUK_D(DUK_DPRINT("duplicated global object: %!O", h1));
53342
53343
53344 /* Create a fresh object environment for the global scope. This is
53345 * needed so that the global scope points to the newly created RAM-based
53346 * global object.
53347 */
53351 -1); /* no prototype */
53352 h1 = duk_get_hobject(ctx, -1);
53353 DUK_ASSERT(h1 != NULL);
53354 duk_dup(ctx, -2);
53355 duk_dup(ctx, -1); /* -> [ ... new_global new_globalenv new_global new_global ] */
53357 duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); /* always provideThis=true */
53358
53362 thr->builtins[DUK_BIDX_GLOBAL_ENV] = h1;
53363 DUK_HOBJECT_INCREF(thr, h1);
53364 DUK_D(DUK_DPRINT("duplicated global env: %!O", h1));
53365
53366 duk_pop_2(ctx);
53367}
53368#endif /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
53369
53371 /* Setup builtins from ROM objects. All heaps/threads will share
53372 * the same readonly objects.
53373 */
53375
53376 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53377 duk_hobject *h;
53378 h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
53379 DUK_ASSERT(h != NULL);
53380 thr->builtins[i] = h;
53381 }
53382
53383#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
53384 /* By default the global object is read-only which is often much
53385 * more of an issue than having read-only built-in objects (like
53386 * RegExp, Date, etc). Use a RAM-based copy of the global object
53387 * and the global environment object for convenience.
53388 */
53389 duk__duplicate_ram_global_object(thr);
53390#endif
53391}
53392#else /* DUK_USE_ROM_OBJECTS */
53395
53404 duk_uint8_t *p;
53405
53407 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, n);
53408 for (i = 0; i < n; i++) {
53409 *p++ = (duk_uint8_t) duk_bd_decode(bd, DUK__STRING_CHAR_BITS);
53410 }
53411 duk_to_string(ctx, -1);
53412}
53414 if (duk_bd_decode_flag(bd)) {
53415 duk__push_string(ctx, bd);
53416 } else {
53418 }
53419}
53423
53424 for (i = 0; i < 8; i++) {
53425 /* Encoding endianness must match target memory layout,
53426 * build scripts and genbuiltins.py must ensure this.
53427 */
53428 du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
53429 }
53430
53431 duk_push_number(ctx, du.d); /* push operation normalizes NaNs */
53432}
53433
53435 duk_context *ctx = (duk_context *) thr;
53436 duk_bitdecoder_ctx bd_ctx;
53437 duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
53438 duk_hobject *h;
53439 duk_small_uint_t i, j;
53440
53441 DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
53442
53443 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
53444 bd->data = (const duk_uint8_t *) duk_builtins_data;
53445 bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
53446
53447 /*
53448 * First create all built-in bare objects on the empty valstack.
53449 *
53450 * Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
53451 * stack indices matching their eventual thr->builtins[] index.
53452 *
53453 * Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
53454 * will exist on the value stack during init but won't be placed
53455 * into thr->builtins[]. These are objects referenced in some way
53456 * from thr->builtins[] roots but which don't need to be indexed by
53457 * Duktape through thr->builtins[] (e.g. user custom objects).
53458 */
53459
53461
53462 DUK_DD(DUK_DDPRINT("create empty built-ins"));
53463 DUK_ASSERT_TOP(ctx, 0);
53464 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
53465 duk_small_uint_t class_num;
53466 duk_small_int_t len = -1; /* must be signed */
53467
53469 len = (duk_small_int_t) duk_bd_decode_flagged(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
53470
53471 if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
53472 duk_small_uint_t natidx;
53473 duk_int_t c_nargs; /* must hold DUK_VARARGS */
53474 duk_c_function c_func;
53475 duk_int16_t magic;
53476
53477 DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
53478 DUK_ASSERT(len >= 0);
53479
53481 c_func = duk_bi_native_functions[natidx];
53482
53483 c_nargs = (duk_small_uint_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, len /*def_value*/);
53484 if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
53485 c_nargs = DUK_VARARGS;
53486 }
53487
53488 /* XXX: set magic directly here? (it could share the c_nargs arg) */
53489 duk_push_c_function_noexotic(ctx, c_func, c_nargs);
53490
53491 h = duk_require_hobject(ctx, -1);
53492 DUK_ASSERT(h != NULL);
53493
53494 /* Currently all built-in native functions are strict.
53495 * duk_push_c_function() now sets strict flag, so
53496 * assert for it.
53497 */
53499
53500 /* XXX: function properties */
53501
53502 /* Built-in 'name' is not writable by default. Function '.name'
53503 * is writable to allow user code to set a '.name' on a native
53504 * function.
53505 */
53508 -2,
53512
53513 /* Almost all global level Function objects are constructable
53514 * but not all: Function.prototype is a non-constructable,
53515 * callable Function.
53516 */
53517 if (duk_bd_decode_flag(bd)) {
53519 } else {
53521 }
53522
53523 /* Cast converts magic to 16-bit signed value */
53524 magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0 /*def_value*/);
53525 ((duk_hnativefunction *) h)->magic = magic;
53526 } else {
53527 /* XXX: ARRAY_PART for Array prototype? */
53528
53531 -1); /* no prototype or class yet */
53532
53533 h = duk_require_hobject(ctx, -1);
53534 DUK_ASSERT(h != NULL);
53535 }
53536
53537 DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
53538
53539 if (i < DUK_NUM_BUILTINS) {
53540 thr->builtins[i] = h;
53541 DUK_HOBJECT_INCREF(thr, &h->hdr);
53542 }
53543
53544 if (len >= 0) {
53545 /*
53546 * For top-level objects, 'length' property has the following
53547 * default attributes: non-writable, non-enumerable, non-configurable
53548 * (E5 Section 15).
53549 *
53550 * However, 'length' property for Array.prototype has attributes
53551 * expected of an Array instance which are different: writable,
53552 * non-enumerable, non-configurable (E5 Section 15.4.5.2).
53553 *
53554 * This is currently determined implicitly based on class; there are
53555 * no attribute flags in the init data.
53556 */
53557
53558 duk_push_int(ctx, len);
53560 -2,
53562 (class_num == DUK_HOBJECT_CLASS_ARRAY ? /* only Array.prototype matches */
53564 }
53565
53566 /* enable exotic behaviors last */
53567
53568 if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
53570 }
53571 if (class_num == DUK_HOBJECT_CLASS_STRING) {
53573 }
53574
53575 /* some assertions */
53576
53578 /* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
53581 /* DUK_HOBJECT_FLAG_NATIVEFUNCTION varies */
53583 DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h)); /* currently, even for Array.prototype */
53584 /* DUK_HOBJECT_FLAG_STRICT varies */
53585 DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(h) || /* all native functions have NEWENV */
53590 /* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
53591 /* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
53593
53594 DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
53595 }
53596
53597 /*
53598 * Then decode the builtins init data (see genbuiltins.py) to
53599 * init objects
53600 */
53601
53602 DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
53603 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
53605 duk_small_uint_t num;
53606
53607 DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
53608 h = duk_require_hobject(ctx, i);
53609 DUK_ASSERT(h != NULL);
53610
53612 if (t != DUK__NO_BIDX_MARKER) {
53613 DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
53615 }
53616
53618 if (t != DUK__NO_BIDX_MARKER) {
53619 /* 'prototype' property for all built-in objects (which have it) has attributes:
53620 * [[Writable]] = false,
53621 * [[Enumerable]] = false,
53622 * [[Configurable]] = false
53623 */
53624 DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
53626 }
53627
53629 if (t != DUK__NO_BIDX_MARKER) {
53630 /* 'constructor' property for all built-in objects (which have it) has attributes:
53631 * [[Writable]] = true,
53632 * [[Enumerable]] = false,
53633 * [[Configurable]] = true
53634 */
53635 DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
53637 }
53638
53639 /* normal valued properties */
53641 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
53642 for (j = 0; j < num; j++) {
53643 duk_small_uint_t prop_flags;
53644
53646
53647 /*
53648 * Property attribute defaults are defined in E5 Section 15 (first
53649 * few pages); there is a default for all properties and a special
53650 * default for 'length' properties. Variation from the defaults is
53651 * signaled using a single flag bit in the bitstream.
53652 */
53653
53654 if (duk_bd_decode_flag(bd)) {
53656 } else {
53657 prop_flags = DUK_PROPDESC_FLAGS_WC;
53658 }
53659
53661
53662 DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
53663 (long) i, (long) j, duk_get_tval(ctx, -1), (unsigned long) prop_flags, (long) t));
53664
53665 switch (t) {
53666 case DUK__PROP_TYPE_DOUBLE: {
53667 duk__push_double(ctx, bd);
53668 break;
53669 }
53670 case DUK__PROP_TYPE_STRING: {
53671 duk__push_string(ctx, bd);
53672 break;
53673 }
53674 case DUK__PROP_TYPE_STRIDX: {
53675 duk__push_stridx(ctx, bd);
53676 break;
53677 }
53679 duk_small_uint_t bidx;
53680
53683 duk_dup(ctx, (duk_idx_t) bidx);
53684 break;
53685 }
53687 duk_push_undefined(ctx);
53688 break;
53689 }
53691 duk_push_true(ctx);
53692 break;
53693 }
53695 duk_push_false(ctx);
53696 break;
53697 }
53701 duk_c_function c_func_getter;
53702 duk_c_function c_func_setter;
53703
53704 /* XXX: this is a bit awkward because there is no exposed helper
53705 * in the API style, only this internal helper.
53706 */
53707 DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
53708 (long) i, duk_get_tval(ctx, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) prop_flags));
53709
53710 c_func_getter = duk_bi_native_functions[natidx_getter];
53711 c_func_setter = duk_bi_native_functions[natidx_setter];
53712 duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0); /* always 0 args */
53713 duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1); /* always 1 arg */
53714
53715 /* XXX: magic for getter/setter? use duk_def_prop()? */
53716
53717 DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0); /* genbuiltins.py ensures */
53718
53719 prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR; /* accessor flag not encoded explicitly */
53721 duk_require_hobject(ctx, i),
53722 duk_get_hstring(ctx, -3),
53723 duk_require_hobject(ctx, -2),
53724 duk_require_hobject(ctx, -1),
53725 prop_flags);
53726 duk_pop_3(ctx); /* key, getter and setter, now reachable through object */
53727 goto skip_value;
53728 }
53729 default: {
53730 /* exhaustive */
53732 }
53733 }
53734
53735 DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0);
53736 duk_xdef_prop(ctx, i, prop_flags);
53737
53738 skip_value:
53739 continue; /* avoid empty label at the end of a compound statement */
53740 }
53741
53742 /* native function properties */
53744 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
53745 for (j = 0; j < num; j++) {
53746 duk_hstring *h_key;
53747 duk_small_uint_t natidx;
53748 duk_int_t c_nargs; /* must hold DUK_VARARGS */
53749 duk_small_uint_t c_length;
53750 duk_int16_t magic;
53751 duk_c_function c_func;
53752 duk_hnativefunction *h_func;
53753#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
53754 duk_small_int_t lightfunc_eligible;
53755#endif
53756
53758 h_key = duk_get_hstring(ctx, -1);
53759 DUK_ASSERT(h_key != NULL);
53760 DUK_UNREF(h_key);
53762
53764 c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_int32_t) c_length /*def_value*/);
53765 if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
53766 c_nargs = DUK_VARARGS;
53767 }
53768
53769 c_func = duk_bi_native_functions[natidx];
53770
53771 DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
53772 (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
53773 (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
53774
53775 /* Cast converts magic to 16-bit signed value */
53776 magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0);
53777
53778#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
53779 lightfunc_eligible =
53780 ((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
53781 (c_length <= DUK_LFUNC_LENGTH_MAX) &&
53782 (magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
53783
53784 if (h_key == DUK_HTHREAD_STRING_EVAL(thr) ||
53785 h_key == DUK_HTHREAD_STRING_YIELD(thr) ||
53786 h_key == DUK_HTHREAD_STRING_RESUME(thr) ||
53787 h_key == DUK_HTHREAD_STRING_REQUIRE(thr)) {
53788 /* These functions have trouble working as lightfuncs.
53789 * Some of them have specific asserts and some may have
53790 * additional properties (e.g. 'require.id' may be written).
53791 */
53792 DUK_D(DUK_DPRINT("reject as lightfunc: key=%!O, i=%d, j=%d", (duk_heaphdr *) h_key, (int) i, (int) j));
53793 lightfunc_eligible = 0;
53794 }
53795
53796 if (lightfunc_eligible) {
53797 duk_tval tv_lfunc;
53798 duk_small_uint_t lf_nargs = (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
53799 duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
53800 DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
53801 duk_push_tval(ctx, &tv_lfunc);
53802 DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(ctx, -1)));
53803 goto lightfunc_skip;
53804 }
53805
53806 DUK_D(DUK_DPRINT("built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic));
53807#endif /* DUK_USE_LIGHTFUNC_BUILTINS */
53808
53809 /* [ (builtin objects) name ] */
53810
53811 duk_push_c_function_noconstruct_noexotic(ctx, c_func, c_nargs);
53812 h_func = duk_require_hnativefunction(ctx, -1);
53813 DUK_UNREF(h_func);
53814
53815 /* Currently all built-in native functions are strict.
53816 * This doesn't matter for many functions, but e.g.
53817 * String.prototype.charAt (and other string functions)
53818 * rely on being strict so that their 'this' binding is
53819 * not automatically coerced.
53820 */
53822
53823 /* No built-in functions are constructable except the top
53824 * level ones (Number, etc).
53825 */
53827
53828 /* XXX: any way to avoid decoding magic bit; there are quite
53829 * many function properties and relatively few with magic values.
53830 */
53831 h_func->magic = magic;
53832
53833 /* [ (builtin objects) name func ] */
53834
53835 duk_push_int(ctx, c_length);
53837
53838 duk_dup(ctx, -2);
53840
53841 /* XXX: other properties of function instances; 'arguments', 'caller'. */
53842
53843 DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
53844 (long) i, (long) j, (duk_tval *) duk_get_tval(ctx, -1)));
53845
53846 /* [ (builtin objects) name func ] */
53847
53848 /*
53849 * The default property attributes are correct for all
53850 * function valued properties of built-in objects now.
53851 */
53852
53853#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
53854 lightfunc_skip:
53855#endif
53856
53858
53859 /* [ (builtin objects) ] */
53860 }
53861 }
53862
53863 /*
53864 * Special post-tweaks, for cases not covered by the init data format.
53865 *
53866 * - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
53867 * toGMTString is required to have the same Function object as
53868 * toUTCString in E5 Section B.2.6. Note that while Smjs respects
53869 * this, V8 does not (the Function objects are distinct).
53870 *
53871 * - Make DoubleError non-extensible.
53872 *
53873 * - Add info about most important effective compile options to Duktape.
53874 *
53875 * - Possibly remove some properties (values or methods) which are not
53876 * desirable with current feature options but are not currently
53877 * conditional in init data.
53878 */
53879
53882
53884 DUK_ASSERT(h != NULL);
53886
53887#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
53888 DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
53890#endif
53891
53892#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
53893 DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
53895#endif
53896
53897 /* XXX: relocate */
53898 duk_push_string(ctx,
53899 /* Endianness indicator */
53900#if defined(DUK_USE_INTEGER_LE)
53901 "l"
53902#elif defined(DUK_USE_INTEGER_BE)
53903 "b"
53904#elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */
53905 "m"
53906#else
53907 "?"
53908#endif
53909#if defined(DUK_USE_DOUBLE_LE)
53910 "l"
53911#elif defined(DUK_USE_DOUBLE_BE)
53912 "b"
53913#elif defined(DUK_USE_DOUBLE_ME)
53914 "m"
53915#else
53916 "?"
53917#endif
53918 " "
53919 /* Packed or unpacked tval */
53920#if defined(DUK_USE_PACKED_TVAL)
53921 "p"
53922#else
53923 "u"
53924#endif
53925#if defined(DUK_USE_FASTINT)
53926 "f"
53927#endif
53928 " "
53929 /* Low memory options */
53930#if defined(DUK_USE_STRTAB_CHAIN)
53931 "c" /* chain */
53932#elif defined(DUK_USE_STRTAB_PROBE)
53933 "p" /* probe */
53934#else
53935 "?"
53936#endif
53937#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
53938 "n"
53939#endif
53940#if defined(DUK_USE_HEAPPTR16)
53941 "h"
53942#endif
53943#if defined(DUK_USE_DATAPTR16)
53944 "d"
53945#endif
53946#if defined(DUK_USE_FUNCPTR16)
53947 "f"
53948#endif
53949#if defined(DUK_USE_REFCOUNT16)
53950 "R"
53951#endif
53952#if defined(DUK_USE_STRHASH16)
53953 "H"
53954#endif
53955#if defined(DUK_USE_STRLEN16)
53956 "S"
53957#endif
53958#if defined(DUK_USE_BUFLEN16)
53959 "B"
53960#endif
53961#if defined(DUK_USE_OBJSIZES16)
53962 "O"
53963#endif
53964#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
53965 "L"
53966#endif
53967#if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
53968 /* XXX: This won't be shown in practice now
53969 * because this code is not run when builtins
53970 * are in ROM.
53971 */
53972 "Z"
53973#endif
53974 " "
53975 /* Object property allocation layout */
53976#if defined(DUK_USE_HOBJECT_LAYOUT_1)
53977 "p1"
53978#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
53979 "p2"
53980#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
53981 "p3"
53982#else
53983 "p?"
53984#endif
53985 " "
53986 /* Alignment guarantee */
53987#if (DUK_USE_ALIGN_BY == 4)
53988 "a4"
53989#elif (DUK_USE_ALIGN_BY == 8)
53990 "a8"
53991#elif (DUK_USE_ALIGN_BY == 1)
53992 "a1"
53993#else
53994#error invalid DUK_USE_ALIGN_BY
53995#endif
53996 " "
53997 /* Architecture, OS, and compiler strings */
53999 " "
54001 " "
54004
54005 /*
54006 * InitJS code - Ecmascript code evaluated from a built-in source
54007 * which provides e.g. backward compatibility. User can also provide
54008 * JS code to be evaluated at startup.
54009 */
54010
54011#ifdef DUK_USE_BUILTIN_INITJS
54012 /* XXX: compression */
54013 DUK_DD(DUK_DDPRINT("running built-in initjs"));
54014 duk_eval_string(ctx, (const char *) duk_initjs_data); /* initjs data is NUL terminated */
54015 duk_pop(ctx);
54016#endif /* DUK_USE_BUILTIN_INITJS */
54017
54018#ifdef DUK_USE_USER_INITJS
54019 /* XXX: compression (as an option) */
54020 DUK_DD(DUK_DDPRINT("running user initjs"));
54021 duk_eval_string_noresult(ctx, (const char *) DUK_USE_USER_INITJS);
54022#endif /* DUK_USE_USER_INITJS */
54023
54024 /*
54025 * Since built-ins are not often extended, compact them.
54026 */
54027
54028 DUK_DD(DUK_DDPRINT("compact built-ins"));
54029 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
54031 }
54032
54033 DUK_D(DUK_DPRINT("INITBUILTINS END"));
54034
54035#ifdef DUK_USE_DDPRINT
54036 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
54037 DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
54038 (long) i, (duk_heaphdr *) duk_require_hobject(ctx, i)));
54039 }
54040#endif
54041
54042 /*
54043 * Pop built-ins from stack: they are now INCREF'd and
54044 * reachable from the builtins[] array or indirectly
54045 * through builtins[].
54046 */
54047
54048 duk_set_top(ctx, 0);
54049 DUK_ASSERT_TOP(ctx, 0);
54051#endif /* DUK_USE_ROM_OBJECTS */
54052
54055
54056 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
54057 thr_to->builtins[i] = thr_from->builtins[i];
54058 DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]); /* side effect free */
54059 }
54060}
54061/*
54062 * Thread support.
54063 */
54064
54065/* include removed: duk_internal.h */
54066
54068 DUK_ASSERT(thr != NULL);
54069
54070 /* Order of unwinding is important */
54071
54073
54074 duk_hthread_callstack_unwind(thr, 0); /* side effects, possibly errors */
54075
54076 thr->valstack_bottom = thr->valstack;
54077 duk_set_top((duk_context *) thr, 0); /* unwinds valstack, updating refcounts */
54078
54080
54081 /* Here we could remove references to built-ins, but it may not be
54082 * worth the effort because built-ins are quite likely to be shared
54083 * with another (unterminated) thread, and terminated threads are also
54084 * usually garbage collected quite quickly. Also, doing DECREFs
54085 * could trigger finalization, which would run on the current thread
54086 * and have access to only some of the built-ins. Garbage collection
54087 * deals with this correctly already.
54088 */
54089
54090 /* XXX: Shrink the stacks to minimize memory usage? May not
54091 * be worth the effort because terminated threads are usually
54092 * garbage collected quite soon.
54093 */
54094}
54095
54097 DUK_ASSERT(thr != NULL);
54098
54099 if (thr->callstack_top > 0) {
54100 return thr->callstack + thr->callstack_top - 1;
54101 } else {
54102 return NULL;
54103 }
54104}
54105
54106#if defined(DUK_USE_DEBUGGER_SUPPORT)
54107DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
54108 duk_instr_t *bcode;
54109
54110 DUK_ASSERT(thr != NULL);
54111 DUK_ASSERT(act != NULL);
54112 DUK_UNREF(thr);
54113
54114 /* XXX: store 'bcode' pointer to activation for faster lookup? */
54115 if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
54117 return (duk_uint_fast32_t) (act->curr_pc - bcode);
54118 }
54119 return 0;
54120}
54121#endif /* DUK_USE_DEBUGGER_SUPPORT */
54122
54124 duk_instr_t *bcode;
54127 DUK_ASSERT(thr != NULL);
54128 DUK_ASSERT(act != NULL);
54129 DUK_UNREF(thr);
54130
54131 if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
54133 ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
54134 if (ret > 0) {
54135 ret--;
54136 }
54137 return ret;
54138 }
54139 return 0;
54140}
54141
54142/* Write bytecode executor's curr_pc back to topmost activation (if any). */
54144 duk_activation *act;
54145
54146 DUK_ASSERT(thr != NULL);
54147
54148 if (thr->ptr_curr_pc != NULL) {
54149 /* ptr_curr_pc != NULL only when bytecode executor is active. */
54150 DUK_ASSERT(thr->callstack_top > 0);
54151 act = thr->callstack + thr->callstack_top - 1;
54152 act->curr_pc = *thr->ptr_curr_pc;
54153 }
54154}
54155
54157 duk_activation *act;
54158
54159 DUK_ASSERT(thr != NULL);
54160
54161 if (thr->ptr_curr_pc != NULL) {
54162 /* ptr_curr_pc != NULL only when bytecode executor is active. */
54163 DUK_ASSERT(thr->callstack_top > 0);
54164 act = thr->callstack + thr->callstack_top - 1;
54165 act->curr_pc = *thr->ptr_curr_pc;
54166 thr->ptr_curr_pc = NULL;
54167 }
54168}
54169/*
54170 * Manipulation of thread stacks (valstack, callstack, catchstack).
54171 *
54172 * Ideally unwinding of stacks should have no side effects, which would
54173 * then favor separate unwinding and shrink check primitives for each
54174 * stack type. A shrink check may realloc and thus have side effects.
54175 *
54176 * However, currently callstack unwinding itself has side effects, as it
54177 * needs to DECREF multiple objects, close environment records, etc.
54178 * Stacks must thus be unwound in the correct order by the caller.
54179 *
54180 * (XXX: This should be probably reworked so that there is a shared
54181 * unwind primitive which handles all stacks as requested, and knows
54182 * the proper order for unwinding.)
54183 *
54184 * Valstack entries above 'top' are always kept initialized to
54185 * "undefined unused". Callstack and catchstack entries above 'top'
54186 * are not zeroed and are left as garbage.
54187 *
54188 * Value stack handling is mostly a part of the API implementation.
54189 */
54190
54191/* include removed: duk_internal.h */
54192
54193/* check that there is space for at least one new entry */
54195 duk_activation *new_ptr;
54196 duk_size_t old_size;
54197 duk_size_t new_size;
54198
54199 DUK_ASSERT(thr != NULL);
54200 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
54202
54203 if (thr->callstack_top < thr->callstack_size) {
54204 return;
54205 }
54206
54207 old_size = thr->callstack_size;
54208 new_size = old_size + DUK_CALLSTACK_GROW_STEP;
54209
54210 /* this is a bit approximate (errors out before max is reached); this is OK */
54211 if (new_size >= thr->callstack_max) {
54213 }
54214
54215 DUK_DD(DUK_DDPRINT("growing callstack %ld -> %ld", (long) old_size, (long) new_size));
54216
54218 * Note: must use indirect variant of DUK_REALLOC() because underlying
54219 * pointer may be changed by mark-and-sweep.
54220 */
54221
54222 DUK_ASSERT(new_size > 0);
54223 new_ptr = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
54224 if (!new_ptr) {
54225 /* No need for a NULL/zero-size check because new_size > 0) */
54227 }
54228 thr->callstack = new_ptr;
54229 thr->callstack_size = new_size;
54230
54231 /* note: any entries above the callstack top are garbage and not zeroed */
54232}
54233
54235 duk_size_t new_size;
54236 duk_activation *p;
54237
54238 DUK_ASSERT(thr != NULL);
54239 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
54241
54243 return;
54244 }
54245
54246 new_size = thr->callstack_top + DUK_CALLSTACK_SHRINK_SPARE;
54247 DUK_ASSERT(new_size >= thr->callstack_top);
54248
54249 DUK_DD(DUK_DDPRINT("shrinking callstack %ld -> %ld", (long) thr->callstack_size, (long) new_size));
54250
54251 /*
54252 * Note: must use indirect variant of DUK_REALLOC() because underlying
54253 * pointer may be changed by mark-and-sweep.
54254 */
54256 /* shrink failure is not fatal */
54257 p = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
54258 if (p) {
54259 thr->callstack = p;
54260 thr->callstack_size = new_size;
54261 } else {
54262 /* Because new_size != 0, if condition doesn't need to be
54263 * (p != NULL || new_size == 0).
54264 */
54265 DUK_ASSERT(new_size != 0);
54266 DUK_D(DUK_DPRINT("callstack shrink failed, ignoring"));
54267 }
54268
54269 /* note: any entries above the callstack top are garbage and not zeroed */
54270}
54271
54273 duk_size_t idx;
54274
54275 DUK_DDD(DUK_DDDPRINT("unwind callstack top of thread %p from %ld to %ld",
54276 (void *) thr,
54277 (thr != NULL ? (long) thr->callstack_top : (long) -1),
54278 (long) new_top));
54279
54280 DUK_ASSERT(thr);
54281 DUK_ASSERT(thr->heap);
54282 DUK_ASSERT_DISABLE(new_top >= 0); /* unsigned */
54283 DUK_ASSERT((duk_size_t) new_top <= thr->callstack_top); /* cannot grow */
54284
54285 /*
54286 * The loop below must avoid issues with potential callstack
54287 * reallocations. A resize (and other side effects) may happen
54288 * e.g. due to finalizer/errhandler calls caused by a refzero or
54289 * mark-and-sweep. Arbitrary finalizers may run, because when
54290 * an environment record is refzero'd, it may refer to arbitrary
54291 * values which also become refzero'd.
54292 *
54293 * So, the pointer 'p' is re-looked-up below whenever a side effect
54294 * might have changed it.
54295 */
54296
54297 idx = thr->callstack_top;
54298 while (idx > new_top) {
54299 duk_activation *act;
54300 duk_hobject *func;
54301#ifdef DUK_USE_REFERENCE_COUNTING
54302 duk_hobject *tmp;
54303#endif
54304#ifdef DUK_USE_DEBUGGER_SUPPORT
54305 duk_heap *heap;
54306#endif
54307
54308 idx--;
54309 DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
54310 DUK_ASSERT((duk_size_t) idx < thr->callstack_size); /* true, despite side effect resizes */
54311
54312 act = thr->callstack + idx;
54313 /* With lightfuncs, act 'func' may be NULL */
54314
54315#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
54316 /*
54317 * Restore 'caller' property for non-strict callee functions.
54318 */
54319
54320 func = DUK_ACT_GET_FUNC(act);
54321 if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
54322 duk_tval *tv_caller;
54323 duk_tval tv_tmp;
54324 duk_hobject *h_tmp;
54325
54327
54328 /* The act->prev_caller should only be set if the entry for 'caller'
54329 * exists (as it is only set in that case, and the property is not
54330 * configurable), but handle all the cases anyway.
54331 */
54332
54333 if (tv_caller) {
54334 DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
54335 if (act->prev_caller) {
54336 /* Just transfer the refcount from act->prev_caller to tv_caller,
54337 * so no need for a refcount update. This is the expected case.
54338 */
54339 DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
54340 act->prev_caller = NULL;
54341 } else {
54342 DUK_TVAL_SET_NULL(tv_caller); /* no incref needed */
54343 DUK_ASSERT(act->prev_caller == NULL);
54344 }
54345 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
54346 } else {
54347 h_tmp = act->prev_caller;
54348 if (h_tmp) {
54349 act->prev_caller = NULL;
54350 DUK_HOBJECT_DECREF(thr, h_tmp); /* side effects */
54351 }
54352 }
54353 act = thr->callstack + idx; /* avoid side effects */
54354 DUK_ASSERT(act->prev_caller == NULL);
54355 }
54356#endif
54357
54358 /*
54359 * Unwind debugger state. If we unwind while stepping
54360 * (either step over or step into), pause execution.
54361 */
54362
54363#if defined(DUK_USE_DEBUGGER_SUPPORT)
54364 heap = thr->heap;
54365 if (heap->dbg_step_thread == thr &&
54366 heap->dbg_step_csindex == idx) {
54367 /* Pause for all step types: step into, step over, step out.
54368 * This is the only place explicitly handling a step out.
54369 */
54370 DUK_HEAP_SET_PAUSED(heap);
54371 DUK_ASSERT(heap->dbg_step_thread == NULL);
54372 }
54373#endif
54374
54375 /*
54376 * Close environment record(s) if they exist.
54377 *
54378 * Only variable environments are closed. If lex_env != var_env, it
54379 * cannot currently contain any register bound declarations.
54380 *
54381 * Only environments created for a NEWENV function are closed. If an
54382 * environment is created for e.g. an eval call, it must not be closed.
54383 */
54384
54385 func = DUK_ACT_GET_FUNC(act);
54386 if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
54387 DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
54388 goto skip_env_close;
54389 }
54390 /* func is NULL for lightfunc */
54391
54392 DUK_ASSERT(act->lex_env == act->var_env);
54393 if (act->var_env != NULL) {
54394 DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
54395 (void *) act->var_env, (duk_heaphdr *) act->var_env));
54396 duk_js_close_environment_record(thr, act->var_env, func, act->idx_bottom);
54397 act = thr->callstack + idx; /* avoid side effect issues */
54398 }
54399
54400#if 0
54401 if (act->lex_env != NULL) {
54402 if (act->lex_env == act->var_env) {
54403 /* common case, already closed, so skip */
54404 DUK_DD(DUK_DDPRINT("lex_env and var_env are the same and lex_env "
54405 "already closed -> skip closing lex_env"));
54406 ;
54407 } else {
54408 DUK_DD(DUK_DDPRINT("closing lex_env record %p -> %!O",
54409 (void *) act->lex_env, (duk_heaphdr *) act->lex_env));
54411 act = thr->callstack + idx; /* avoid side effect issues */
54412 }
54413 }
54414#endif
54415
54416 DUK_ASSERT((act->lex_env == NULL) ||
54421
54422 DUK_ASSERT((act->var_env == NULL) ||
54427
54428 skip_env_close:
54429
54430 /*
54431 * Update preventcount
54432 */
54433
54434 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
54435 DUK_ASSERT(thr->callstack_preventcount >= 1);
54436 thr->callstack_preventcount--;
54437 }
54438
54439 /*
54440 * Reference count updates
54441 *
54442 * Note: careful manipulation of refcounts. The top is
54443 * not updated yet, so all the activations are reachable
54444 * for mark-and-sweep (which may be triggered by decref).
54445 * However, the pointers are NULL so this is not an issue.
54446 */
54447
54448#ifdef DUK_USE_REFERENCE_COUNTING
54449 tmp = act->var_env;
54450#endif
54451 act->var_env = NULL;
54452#ifdef DUK_USE_REFERENCE_COUNTING
54454 act = thr->callstack + idx; /* avoid side effect issues */
54455#endif
54456
54457#ifdef DUK_USE_REFERENCE_COUNTING
54458 tmp = act->lex_env;
54459#endif
54460 act->lex_env = NULL;
54461#ifdef DUK_USE_REFERENCE_COUNTING
54463 act = thr->callstack + idx; /* avoid side effect issues */
54464#endif
54465
54466 /* Note: this may cause a corner case situation where a finalizer
54467 * may see a currently reachable activation whose 'func' is NULL.
54468 */
54469#ifdef DUK_USE_REFERENCE_COUNTING
54470 tmp = DUK_ACT_GET_FUNC(act);
54471#endif
54472 act->func = NULL;
54473#ifdef DUK_USE_REFERENCE_COUNTING
54475 act = thr->callstack + idx; /* avoid side effect issues */
54476 DUK_UNREF(act);
54477#endif
54478 }
54479
54480 thr->callstack_top = new_top;
54481
54483 * We could clear the book-keeping variables for the topmost activation,
54484 * but don't do so now.
54485 */
54486#if 0
54487 if (thr->callstack_top > 0) {
54488 duk_activation *act = thr->callstack + thr->callstack_top - 1;
54489 act->idx_retval = 0;
54490 }
54491#endif
54492
54493 /* Note: any entries above the callstack top are garbage and not zeroed.
54494 * Also topmost activation idx_retval is garbage (not zeroed), and must
54495 * be ignored.
54496 */
54497}
54498
54500 duk_catcher *new_ptr;
54501 duk_size_t old_size;
54502 duk_size_t new_size;
54503
54504 DUK_ASSERT(thr != NULL);
54505 DUK_ASSERT_DISABLE(thr->catchstack_top); /* avoid warning (unsigned) */
54507
54508 if (thr->catchstack_top < thr->catchstack_size) {
54509 return;
54510 }
54511
54512 old_size = thr->catchstack_size;
54513 new_size = old_size + DUK_CATCHSTACK_GROW_STEP;
54514
54515 /* this is a bit approximate (errors out before max is reached); this is OK */
54516 if (new_size >= thr->catchstack_max) {
54518 }
54519
54520 DUK_DD(DUK_DDPRINT("growing catchstack %ld -> %ld", (long) old_size, (long) new_size));
54521
54523 * Note: must use indirect variant of DUK_REALLOC() because underlying
54524 * pointer may be changed by mark-and-sweep.
54525 */
54526
54527 DUK_ASSERT(new_size > 0);
54528 new_ptr = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
54529 if (!new_ptr) {
54530 /* No need for a NULL/zero-size check because new_size > 0) */
54532 }
54533 thr->catchstack = new_ptr;
54534 thr->catchstack_size = new_size;
54535
54536 /* note: any entries above the catchstack top are garbage and not zeroed */
54537}
54538
54540 duk_size_t new_size;
54541 duk_catcher *p;
54542
54543 DUK_ASSERT(thr != NULL);
54544 DUK_ASSERT_DISABLE(thr->catchstack_top >= 0); /* avoid warning (unsigned) */
54546
54548 return;
54549 }
54550
54552 DUK_ASSERT(new_size >= thr->catchstack_top);
54553
54554 DUK_DD(DUK_DDPRINT("shrinking catchstack %ld -> %ld", (long) thr->catchstack_size, (long) new_size));
54555
54556 /*
54557 * Note: must use indirect variant of DUK_REALLOC() because underlying
54558 * pointer may be changed by mark-and-sweep.
54559 */
54561 /* shrink failure is not fatal */
54562 p = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
54563 if (p) {
54564 thr->catchstack = p;
54565 thr->catchstack_size = new_size;
54566 } else {
54567 /* Because new_size != 0, if condition doesn't need to be
54568 * (p != NULL || new_size == 0).
54569 */
54570 DUK_ASSERT(new_size != 0);
54571 DUK_D(DUK_DPRINT("catchstack shrink failed, ignoring"));
54572 }
54573
54574 /* note: any entries above the catchstack top are garbage and not zeroed */
54575}
54576
54578 duk_size_t idx;
54579
54580 DUK_DDD(DUK_DDDPRINT("unwind catchstack top of thread %p from %ld to %ld",
54581 (void *) thr,
54582 (thr != NULL ? (long) thr->catchstack_top : (long) -1),
54583 (long) new_top));
54584
54585 DUK_ASSERT(thr);
54586 DUK_ASSERT(thr->heap);
54587 DUK_ASSERT_DISABLE(new_top >= 0); /* unsigned */
54588 DUK_ASSERT((duk_size_t) new_top <= thr->catchstack_top); /* cannot grow */
54589
54590 /*
54591 * Since there are no references in the catcher structure,
54592 * unwinding is quite simple. The only thing we need to
54593 * look out for is popping a possible lexical environment
54594 * established for an active catch clause.
54595 */
54596
54597 idx = thr->catchstack_top;
54598 while (idx > new_top) {
54599 duk_catcher *p;
54600 duk_activation *act;
54601 duk_hobject *env;
54602
54603 idx--;
54604 DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
54605 DUK_ASSERT((duk_size_t) idx < thr->catchstack_size);
54606
54607 p = thr->catchstack + idx;
54608
54610 DUK_DDD(DUK_DDDPRINT("unwinding catchstack idx %ld, callstack idx %ld, callstack top %ld: lexical environment active",
54611 (long) idx, (long) p->callstack_index, (long) thr->callstack_top));
54612
54613 /* XXX: Here we have a nasty dependency: the need to manipulate
54614 * the callstack means that catchstack must always be unwound by
54615 * the caller before unwinding the callstack. This should be fixed
54616 * later.
54617 */
54618
54619 /* Note that multiple catchstack entries may refer to the same
54620 * callstack entry.
54621 */
54622 act = thr->callstack + p->callstack_index;
54623 DUK_ASSERT(act >= thr->callstack);
54624 DUK_ASSERT(act < thr->callstack + thr->callstack_top);
54625
54626 DUK_DDD(DUK_DDDPRINT("catchstack_index=%ld, callstack_index=%ld, lex_env=%!iO",
54627 (long) idx, (long) p->callstack_index,
54628 (duk_heaphdr *) act->lex_env));
54629
54630 env = act->lex_env; /* current lex_env of the activation (created for catcher) */
54631 DUK_ASSERT(env != NULL); /* must be, since env was created when catcher was created */
54632 act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env); /* prototype is lex_env before catcher created */
54633 DUK_HOBJECT_DECREF(thr, env);
54634
54635 /* There is no need to decref anything else than 'env': if 'env'
54636 * becomes unreachable, refzero will handle decref'ing its prototype.
54637 */
54638 }
54639 }
54640
54641 thr->catchstack_top = new_top;
54642
54643 /* note: any entries above the catchstack top are garbage and not zeroed */
54644}
54645/*
54646 * Call handling.
54647 *
54648 * Main functions are:
54649 *
54650 * - duk_handle_call_unprotected(): unprotected call to Ecmascript or
54651 * Duktape/C function
54652 * - duk_handle_call_protected(): protected call to Ecmascript or
54653 * Duktape/C function
54654 * - duk_handle_safe_call(): make a protected C call within current
54655 * activation
54656 * - duk_handle_ecma_call_setup(): Ecmascript-to-Ecmascript calls
54657 * (not always possible), including tail calls and coroutine resume
54658 *
54659 * See 'execution.rst'.
54660 *
54661 * Note: setjmp() and local variables have a nasty interaction,
54662 * see execution.rst; non-volatile locals modified after setjmp()
54663 * call are not guaranteed to keep their value.
54664 */
54665
54666/* include removed: duk_internal.h */
54667
54668/*
54669 * Forward declarations.
54670 */
54671
54673 duk_idx_t num_stack_args,
54674 duk_small_uint_t call_flags,
54675 duk_idx_t idx_func);
54677 duk_size_t entry_valstack_bottom_index,
54678 duk_size_t entry_valstack_end,
54679 duk_size_t entry_catchstack_top,
54680 duk_size_t entry_callstack_top,
54681 duk_int_t entry_call_recursion_depth,
54682 duk_hthread *entry_curr_thread,
54683 duk_uint_fast8_t entry_thread_state,
54684 duk_instr_t **entry_ptr_curr_pc,
54685 duk_idx_t idx_func,
54686 duk_jmpbuf *old_jmpbuf_ptr);
54689 duk_idx_t idx_retbase,
54690 duk_idx_t num_stack_rets,
54691 duk_size_t entry_valstack_bottom_index,
54692 duk_size_t entry_callstack_top,
54693 duk_size_t entry_catchstack_top);
54695 duk_idx_t idx_retbase,
54696 duk_idx_t num_stack_rets,
54697 duk_size_t entry_valstack_bottom_index,
54698 duk_size_t entry_callstack_top,
54699 duk_size_t entry_catchstack_top,
54700 duk_jmpbuf *old_jmpbuf_ptr);
54702 duk_idx_t idx_retbase,
54703 duk_idx_t num_stack_rets,
54704 duk_int_t entry_call_recursion_depth,
54705 duk_hthread *entry_curr_thread,
54706 duk_uint_fast8_t entry_thread_state,
54707 duk_instr_t **entry_ptr_curr_pc);
54708
54709/*
54710 * Interrupt counter fixup (for development only).
54711 */
54712
54713#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
54714DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
54715 /* Currently the bytecode executor and executor interrupt
54716 * instruction counts are off because we don't execute the
54717 * interrupt handler when we're about to exit from the initial
54718 * user call into Duktape.
54719 *
54720 * If we were to execute the interrupt handler here, the counts
54721 * would match. You can enable this block manually to check
54722 * that this is the case.
54723 */
54724
54725 DUK_ASSERT(thr != NULL);
54726 DUK_ASSERT(thr->heap != NULL);
54727
54728#if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
54729 if (entry_curr_thread == NULL) {
54730 thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
54731 thr->heap->inst_count_interrupt += thr->interrupt_init;
54732 DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
54733 "user code, instruction counts: executor=%ld, interrupt=%ld",
54734 (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
54735 DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
54737#else
54738 DUK_UNREF(thr);
54739 DUK_UNREF(entry_curr_thread);
54740#endif
54741}
54742#endif
54743
54744/*
54745 * Arguments object creation.
54746 *
54747 * Creating arguments objects involves many small details, see E5 Section
54748 * 10.6 for the specific requirements. Much of the arguments object exotic
54749 * behavior is implemented in duk_hobject_props.c, and is enabled by the
54750 * object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
54751 */
54752
54754 duk_hobject *func,
54755 duk_hobject *varenv,
54756 duk_idx_t idx_argbase, /* idx of first argument on stack */
54757 duk_idx_t num_stack_args) { /* num args starting from idx_argbase */
54758 duk_context *ctx = (duk_context *) thr;
54759 duk_hobject *arg; /* 'arguments' */
54760 duk_hobject *formals; /* formals for 'func' (may be NULL if func is a C function) */
54761 duk_idx_t i_arg;
54762 duk_idx_t i_map;
54763 duk_idx_t i_mappednames;
54764 duk_idx_t i_formals;
54765 duk_idx_t i_argbase;
54766 duk_idx_t n_formals;
54767 duk_idx_t idx;
54768 duk_bool_t need_map;
54769
54770 DUK_DDD(DUK_DDDPRINT("creating arguments object for func=%!iO, varenv=%!iO, "
54771 "idx_argbase=%ld, num_stack_args=%ld",
54772 (duk_heaphdr *) func, (duk_heaphdr *) varenv,
54773 (long) idx_argbase, (long) num_stack_args));
54774
54775 DUK_ASSERT(thr != NULL);
54776 DUK_ASSERT(func != NULL);
54778 DUK_ASSERT(varenv != NULL);
54779 DUK_ASSERT(idx_argbase >= 0); /* assumed to bottom relative */
54780 DUK_ASSERT(num_stack_args >= 0);
54781
54782 need_map = 0;
54783
54784 i_argbase = idx_argbase;
54785 DUK_ASSERT(i_argbase >= 0);
54786
54787 duk_push_hobject(ctx, func);
54789 formals = duk_get_hobject(ctx, -1);
54790 n_formals = 0;
54791 if (formals) {
54793 n_formals = (duk_idx_t) duk_require_int(ctx, -1);
54794 duk_pop(ctx);
54795 }
54796 duk_remove(ctx, -2); /* leave formals on stack for later use */
54797 i_formals = duk_require_top_index(ctx);
54798
54799 DUK_ASSERT(n_formals >= 0);
54800 DUK_ASSERT(formals != NULL || n_formals == 0);
54801
54802 DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
54803 (duk_heaphdr *) func, (duk_heaphdr *) formals,
54804 (long) n_formals));
54805
54806 /* [ ... formals ] */
54807
54808 /*
54809 * Create required objects:
54810 * - 'arguments' object: array-like, but not an array
54811 * - 'map' object: internal object, tied to 'arguments'
54812 * - 'mappedNames' object: temporary value used during construction
54813 */
54814
54815 i_arg = duk_push_object_helper(ctx,
54820 DUK_ASSERT(i_arg >= 0);
54821 arg = duk_require_hobject(ctx, -1);
54822 DUK_ASSERT(arg != NULL);
54823
54824 i_map = duk_push_object_helper(ctx,
54827 -1); /* no prototype */
54828 DUK_ASSERT(i_map >= 0);
54829
54830 i_mappednames = duk_push_object_helper(ctx,
54833 -1); /* no prototype */
54834 DUK_ASSERT(i_mappednames >= 0);
54835
54836 /* [ ... formals arguments map mappedNames ] */
54837
54838 DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
54839 "arguments at index %ld -> %!O "
54840 "map at index %ld -> %!O "
54841 "mappednames at index %ld -> %!O",
54842 (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
54843 (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
54844 (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
54845
54846 /*
54847 * Init arguments properties, map, etc.
54848 */
54849
54850 duk_push_int(ctx, num_stack_args);
54852
54853 /*
54854 * Init argument related properties
54855 */
54856
54857 /* step 11 */
54858 idx = num_stack_args - 1;
54859 while (idx >= 0) {
54860 DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
54861 (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
54862
54863 DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
54864 duk_dup(ctx, i_argbase + idx);
54865 duk_xdef_prop_index_wec(ctx, i_arg, (duk_uarridx_t) idx);
54866 DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
54867
54868 /* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
54869 if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
54870 DUK_ASSERT(formals != NULL);
54871
54872 DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
54873 (long) idx, (long) n_formals));
54874
54875 duk_get_prop_index(ctx, i_formals, idx);
54876 DUK_ASSERT(duk_is_string(ctx, -1));
54877
54878 duk_dup(ctx, -1); /* [ ... name name ] */
54879
54880 if (!duk_has_prop(ctx, i_mappednames)) {
54881 /* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
54882 * differs from the reference model
54883 */
54884
54885 /* [ ... name ] */
54886
54887 need_map = 1;
54888
54889 DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
54890 (const char *) duk_get_string(ctx, -1),
54891 (long) idx));
54892 duk_dup(ctx, -1); /* name */
54893 duk_push_uint(ctx, (duk_uint_t) idx); /* index */
54894 duk_to_string(ctx, -1);
54895 duk_xdef_prop_wec(ctx, i_mappednames); /* out of spec, must be configurable */
54896
54897 DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
54898 (long) idx,
54899 duk_get_string(ctx, -1)));
54900 duk_dup(ctx, -1); /* name */
54901 duk_xdef_prop_index_wec(ctx, i_map, (duk_uarridx_t) idx); /* out of spec, must be configurable */
54902 } else {
54903 /* duk_has_prop() popped the second 'name' */
54904 }
54905
54906 /* [ ... name ] */
54907 duk_pop(ctx); /* pop 'name' */
54908 }
54909
54910 idx--;
54911 }
54912
54913 DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
54914
54915 /* step 12 */
54916 if (need_map) {
54917 DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
54918
54919 /* should never happen for a strict callee */
54921
54922 duk_dup(ctx, i_map);
54923 duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
54924
54925 /* The variable environment for magic variable bindings needs to be
54926 * given by the caller and recorded in the arguments object.
54927 *
54928 * See E5 Section 10.6, the creation of setters/getters.
54929 *
54930 * The variable environment also provides access to the callee, so
54931 * an explicit (internal) callee property is not needed.
54932 */
54933
54934 duk_push_hobject(ctx, varenv);
54935 duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
54936 }
54937
54938 /* steps 13-14 */
54939 if (DUK_HOBJECT_HAS_STRICT(func)) {
54940 /* Callee/caller are throwers and are not deletable etc. They
54941 * could be implemented as virtual properties, but currently
54942 * there is no support for virtual properties which are accessors
54943 * (only plain virtual properties). This would not be difficult
54944 * to change in duk_hobject_props, but we can make the throwers
54945 * normal, concrete properties just as easily.
54946 *
54947 * Note that the specification requires that the *same* thrower
54948 * built-in object is used here! See E5 Section 10.6 main
54949 * algoritm, step 14, and Section 13.2.3 which describes the
54950 * thrower. See test case test-arguments-throwers.js.
54951 */
54952
54953 DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
54954
54957 } else {
54958 DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
54959 duk_push_hobject(ctx, func);
54961 }
54962
54963 /* set exotic behavior only after we're done */
54964 if (need_map) {
54965 /* Exotic behaviors are only enabled for arguments objects
54966 * which have a parameter map (see E5 Section 10.6 main
54967 * algorithm, step 12).
54968 *
54969 * In particular, a non-strict arguments object with no
54970 * mapped formals does *NOT* get exotic behavior, even
54971 * for e.g. "caller" property. This seems counterintuitive
54972 * but seems to be the case.
54973 */
54974
54975 /* cannot be strict (never mapped variables) */
54977
54978 DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
54980 } else {
54981 DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
54982 }
54983
54984 DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
54985 "arguments at index %ld -> %!O "
54986 "map at index %ld -> %!O "
54987 "mappednames at index %ld -> %!O",
54988 (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
54989 (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
54990 (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
54991
54992 /* [ args(n) [crud] formals arguments map mappednames ] */
54993
54994 duk_pop_2(ctx);
54995 duk_remove(ctx, -2);
54996
54997 /* [ args [crud] arguments ] */
54998}
54999
55000/* Helper for creating the arguments object and adding it to the env record
55001 * on top of the value stack. This helper has a very strict dependency on
55002 * the shape of the input stack.
55003 */
55005 duk_hobject *func,
55006 duk_hobject *env,
55007 duk_idx_t num_stack_args) {
55008 duk_context *ctx = (duk_context *) thr;
55009
55010 DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
55011
55012 DUK_ASSERT(thr != NULL);
55013 DUK_ASSERT(func != NULL);
55014 DUK_ASSERT(env != NULL);
55016 DUK_ASSERT(duk_get_top(ctx) >= num_stack_args + 1);
55017
55018 /* [ ... arg1 ... argN envobj ] */
55019
55021 func,
55022 env,
55023 duk_get_top(ctx) - num_stack_args - 1, /* idx_argbase */
55024 num_stack_args);
55025
55026 /* [ ... arg1 ... argN envobj argobj ] */
55027
55029 -2,
55031 DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E : /* strict: non-deletable, non-writable */
55032 DUK_PROPDESC_FLAGS_WE); /* non-strict: non-deletable, writable */
55033 /* [ ... arg1 ... argN envobj ] */
55034}
55035
55036/*
55037 * Helper for handling a "bound function" chain when a call is being made.
55038 *
55039 * Follows the bound function chain until a non-bound function is found.
55040 * Prepends the bound arguments to the value stack (at idx_func + 2),
55041 * updating 'num_stack_args' in the process. The 'this' binding is also
55042 * updated if necessary (at idx_func + 1). Note that for constructor calls
55043 * the 'this' binding is never updated by [[BoundThis]].
55044 *
55045 * XXX: bound function chains could be collapsed at bound function creation
55046 * time so that each bound function would point directly to a non-bound
55047 * function. This would make call time handling much easier.
55048 */
55049
55051 duk_idx_t idx_func,
55052 duk_idx_t *p_num_stack_args, /* may be changed by call */
55053 duk_bool_t is_constructor_call) {
55054 duk_context *ctx = (duk_context *) thr;
55055 duk_idx_t num_stack_args;
55056 duk_tval *tv_func;
55057 duk_hobject *func;
55058 duk_uint_t sanity;
55059
55060 DUK_ASSERT(thr != NULL);
55061 DUK_ASSERT(p_num_stack_args != NULL);
55062
55063 /* On entry, item at idx_func is a bound, non-lightweight function,
55064 * but we don't rely on that below.
55065 */
55066
55067 num_stack_args = *p_num_stack_args;
55068
55070 do {
55071 duk_idx_t i, len;
55072
55073 tv_func = duk_require_tval(ctx, idx_func);
55074 DUK_ASSERT(tv_func != NULL);
55075
55076 if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
55077 /* Lightweight function: never bound, so terminate. */
55078 break;
55079 } else if (DUK_TVAL_IS_OBJECT(tv_func)) {
55080 func = DUK_TVAL_GET_OBJECT(tv_func);
55081 if (!DUK_HOBJECT_HAS_BOUND(func)) {
55082 /* Normal non-bound function. */
55083 break;
55084 }
55085 } else {
55086 /* Function.prototype.bind() should never let this happen,
55087 * ugly error message is enough.
55088 */
55090 }
55091 DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv_func) != NULL);
55092
55093 /* XXX: this could be more compact by accessing the internal properties
55094 * directly as own properties (they cannot be inherited, and are not
55095 * externally visible).
55096 */
55097
55098 DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p, num_stack_args=%ld: %!T",
55099 (void *) DUK_TVAL_GET_OBJECT(tv_func), (long) num_stack_args, tv_func));
55100
55101 /* [ ... func this arg1 ... argN ] */
55102
55103 if (is_constructor_call) {
55104 /* See: tests/ecmascript/test-spec-bound-constructor.js */
55105 DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
55106 } else {
55108 duk_replace(ctx, idx_func + 1); /* idx_this = idx_func + 1 */
55109 }
55110
55111 /* [ ... func this arg1 ... argN ] */
55112
55113 /* XXX: duk_get_length? */
55114 duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_ARGS); /* -> [ ... func this arg1 ... argN _Args ] */
55115 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH); /* -> [ ... func this arg1 ... argN _Args length ] */
55116 len = (duk_idx_t) duk_require_int(ctx, -1);
55117 duk_pop(ctx);
55118 for (i = 0; i < len; i++) {
55119 /* XXX: very slow - better to bulk allocate a gap, and copy
55120 * from args_array directly (we know it has a compact array
55121 * part, etc).
55122 */
55123
55124 /* [ ... func this <some bound args> arg1 ... argN _Args ] */
55125 duk_get_prop_index(ctx, -1, i);
55126 duk_insert(ctx, idx_func + 2 + i); /* idx_args = idx_func + 2 */
55127 }
55128 num_stack_args += len; /* must be updated to work properly (e.g. creation of 'arguments') */
55129 duk_pop(ctx);
55130
55131 /* [ ... func this <bound args> arg1 ... argN ] */
55132
55134 duk_replace(ctx, idx_func); /* replace in stack */
55135
55136 DUK_DDD(DUK_DDDPRINT("bound function handled, num_stack_args=%ld, idx_func=%ld, curr func=%!T",
55137 (long) num_stack_args, (long) idx_func, duk_get_tval(ctx, idx_func)));
55138 } while (--sanity > 0);
55139
55140 if (sanity == 0) {
55142 }
55143
55144 DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(ctx, idx_func)));
55145
55146#if defined(DUK_USE_ASSERTIONS)
55147 tv_func = duk_require_tval(ctx, idx_func);
55149 if (DUK_TVAL_IS_OBJECT(tv_func)) {
55150 func = DUK_TVAL_GET_OBJECT(tv_func);
55151 DUK_ASSERT(func != NULL);
55155 }
55156#endif
55157
55158 /* write back */
55159 *p_num_stack_args = num_stack_args;
55160}
55161
55162/*
55163 * Helper for setting up var_env and lex_env of an activation,
55164 * assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
55165 */
55166
55168 duk_hobject *func,
55169 duk_activation *act) {
55170 duk_tval *tv;
55171
55172 DUK_ASSERT(thr != NULL);
55173 DUK_ASSERT(func != NULL);
55174 DUK_ASSERT(act != NULL);
55177
55179 if (tv) {
55182 act->lex_env = DUK_TVAL_GET_OBJECT(tv);
55183
55185 if (tv) {
55188 act->var_env = DUK_TVAL_GET_OBJECT(tv);
55189 } else {
55190 act->var_env = act->lex_env;
55191 }
55192 } else {
55194 act->var_env = act->lex_env;
55195 }
55196
55199}
55200
55201/*
55202 * Helper for updating callee 'caller' property.
55203 */
55204
55205#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
55206DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
55207 duk_tval *tv_caller;
55208 duk_hobject *h_tmp;
55209 duk_activation *act_callee;
55210 duk_activation *act_caller;
55211
55212 DUK_ASSERT(thr != NULL);
55213 DUK_ASSERT(func != NULL);
55214 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func)); /* bound chain resolved */
55215 DUK_ASSERT(thr->callstack_top >= 1);
55216
55217 if (DUK_HOBJECT_HAS_STRICT(func)) {
55218 /* Strict functions don't get their 'caller' updated. */
55219 return;
55220 }
55221
55222 act_callee = thr->callstack + thr->callstack_top - 1;
55223 act_caller = (thr->callstack_top >= 2 ? act_callee - 1 : NULL);
55224
55225 /* XXX: check .caller writability? */
55226
55227 /* Backup 'caller' property and update its value. */
55229 if (tv_caller) {
55230 /* If caller is global/eval code, 'caller' should be set to
55231 * 'null'.
55232 *
55233 * XXX: there is no exotic flag to infer this correctly now.
55234 * The NEWENV flag is used now which works as intended for
55235 * everything (global code, non-strict eval code, and functions)
55236 * except strict eval code. Bound functions are never an issue
55237 * because 'func' has been resolved to a non-bound function.
55238 */
55239
55240 if (act_caller) {
55241 /* act_caller->func may be NULL in some finalization cases,
55242 * just treat like we don't know the caller.
55243 */
55244 if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
55245 /* Setting to NULL causes 'caller' to be set to
55246 * 'null' as desired.
55247 */
55248 act_caller = NULL;
55249 }
55250 }
55251
55252 if (DUK_TVAL_IS_OBJECT(tv_caller)) {
55253 h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
55254 DUK_ASSERT(h_tmp != NULL);
55255 act_callee->prev_caller = h_tmp;
55256
55257 /* Previous value doesn't need refcount changes because its ownership
55258 * is transferred to prev_caller.
55259 */
55260
55261 if (act_caller) {
55262 DUK_ASSERT(act_caller->func != NULL);
55263 DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
55264 DUK_TVAL_INCREF(thr, tv_caller);
55265 } else {
55266 DUK_TVAL_SET_NULL(tv_caller); /* no incref */
55267 }
55268 } else {
55269 /* 'caller' must only take on 'null' or function value */
55271 DUK_ASSERT(act_callee->prev_caller == NULL);
55272 if (act_caller && act_caller->func) {
55273 /* Tolerate act_caller->func == NULL which happens in
55274 * some finalization cases; treat like unknown caller.
55275 */
55276 DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
55277 DUK_TVAL_INCREF(thr, tv_caller);
55278 } else {
55279 DUK_TVAL_SET_NULL(tv_caller); /* no incref */
55280 }
55281 }
55282 }
55283}
55284#endif /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
55285
55286/*
55287 * Determine the effective 'this' binding and coerce the current value
55288 * on the valstack to the effective one (in-place, at idx_this).
55289 *
55290 * The current this value in the valstack (at idx_this) represents either:
55291 * - the caller's requested 'this' binding; or
55292 * - a 'this' binding accumulated from the bound function chain
55293 *
55294 * The final 'this' binding for the target function may still be
55295 * different, and is determined as described in E5 Section 10.4.3.
55296 *
55297 * For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
55298 * that the caller has provided the correct 'this' binding explicitly
55299 * when calling, i.e.:
55300 *
55301 * - global code: this=global object
55302 * - direct eval: this=copy from eval() caller's this binding
55303 * - other eval: this=global object
55304 *
55305 * Note: this function may cause a recursive function call with arbitrary
55306 * side effects, because ToObject() may be called.
55307 */
55308
55310 duk_hobject *func,
55311 duk_idx_t idx_this) {
55312 duk_context *ctx = (duk_context *) thr;
55313 duk_tval *tv_this;
55314 duk_hobject *obj_global;
55315
55316 if (func == NULL || DUK_HOBJECT_HAS_STRICT(func)) {
55317 /* Lightfuncs are always considered strict. */
55318 DUK_DDD(DUK_DDDPRINT("this binding: strict -> use directly"));
55319 return;
55320 }
55321
55322 /* XXX: byte offset */
55323 tv_this = thr->valstack_bottom + idx_this;
55324 switch (DUK_TVAL_GET_TAG(tv_this)) {
55325 case DUK_TAG_OBJECT:
55326 case DUK_TAG_LIGHTFUNC: /* lightfuncs are treated like objects and not coerced */
55327 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
55328 break;
55329 case DUK_TAG_UNDEFINED:
55330 case DUK_TAG_NULL:
55331 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
55332 obj_global = thr->builtins[DUK_BIDX_GLOBAL];
55333 /* XXX: avoid this check somehow */
55334 if (DUK_LIKELY(obj_global != NULL)) {
55335 DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
55336 DUK_TVAL_SET_OBJECT(tv_this, obj_global);
55337 DUK_HOBJECT_INCREF(thr, obj_global);
55338 } else {
55339 /* This may only happen if built-ins are being "torn down".
55340 * This behavior is out of specification scope.
55341 */
55342 DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
55343 DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
55344 DUK_TVAL_SET_UNDEFINED(tv_this); /* nothing to incref */
55345 }
55346 break;
55347 default:
55348 DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
55349 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
55350 duk_to_object(ctx, idx_this); /* may have side effects */
55351 break;
55352 }
55353}
55354
55355/*
55356 * Shared helper for non-bound func lookup.
55357 *
55358 * Returns duk_hobject * to the final non-bound function (NULL for lightfunc).
55359 */
55360
55362 duk_idx_t idx_func,
55363 duk_idx_t *out_num_stack_args,
55364 duk_tval **out_tv_func,
55365 duk_small_uint_t call_flags) {
55366 duk_hthread *thr = (duk_hthread *) ctx;
55367 duk_tval *tv_func;
55368 duk_hobject *func;
55369
55370 for (;;) {
55371 /* Use loop to minimize code size of relookup after bound function case */
55372 tv_func = DUK_GET_TVAL_POSIDX(ctx, idx_func);
55373 DUK_ASSERT(tv_func != NULL);
55374
55375 if (DUK_TVAL_IS_OBJECT(tv_func)) {
55376 func = DUK_TVAL_GET_OBJECT(tv_func);
55377 if (!DUK_HOBJECT_IS_CALLABLE(func)) {
55378 goto not_callable_error;
55379 }
55380 if (DUK_HOBJECT_HAS_BOUND(func)) {
55381 duk__handle_bound_chain_for_call(thr, idx_func, out_num_stack_args, call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL);
55382
55383 /* The final object may be a normal function or a lightfunc.
55384 * We need to re-lookup tv_func because it may have changed
55385 * (also value stack may have been resized). Loop again to
55386 * do that; we're guaranteed not to come here again.
55387 */
55389 DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(ctx, idx_func)));
55390 continue;
55391 }
55392 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
55393 func = NULL;
55394 } else {
55395 goto not_callable_error;
55396 }
55397 break;
55398 }
55399
55401 DUK_TVAL_IS_LIGHTFUNC(tv_func));
55402 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
55405
55406 *out_tv_func = tv_func;
55407 return func;
55408
55409 not_callable_error:
55410 DUK_ASSERT(tv_func != NULL);
55411#if defined(DUK_USE_PARANOID_ERRORS)
55413#else
55414 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(ctx, tv_func));
55415#endif
55417 return NULL; /* never executed */
55418}
55419
55420/*
55421 * Value stack resize and stack top adjustment helper.
55422 *
55423 * XXX: This should all be merged to duk_valstack_resize_raw().
55424 */
55425
55427 duk_idx_t num_stack_args,
55428 duk_idx_t idx_args,
55429 duk_idx_t nregs,
55430 duk_idx_t nargs,
55431 duk_hobject *func) {
55432 duk_context *ctx = (duk_context *) thr;
55433 duk_size_t vs_min_size;
55434 duk_bool_t adjusted_top = 0;
55435
55436 vs_min_size = (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
55437 idx_args; /* bottom of new func */
55438
55439 if (nregs >= 0) {
55440 DUK_ASSERT(nargs >= 0);
55441 DUK_ASSERT(nregs >= nargs);
55442 vs_min_size += nregs;
55443 } else {
55444 /* 'func' wants stack "as is" */
55445 vs_min_size += num_stack_args; /* num entries of new func at entry */
55446 }
55447 if (func == NULL || DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
55448 vs_min_size += DUK_VALSTACK_API_ENTRY_MINIMUM; /* Duktape/C API guaranteed entries (on top of args) */
55449 }
55450 vs_min_size += DUK_VALSTACK_INTERNAL_EXTRA; /* + spare */
55451
55452 /* XXX: We can't resize the value stack to a size smaller than the
55453 * current top, so the order of the resize and adjusting the stack
55454 * top depends on the current vs. final size of the value stack.
55455 * The operations could be combined to avoid this, but the proper
55456 * fix is to only grow the value stack on a function call, and only
55457 * shrink it (without throwing if the shrink fails) on function
55458 * return.
55459 */
55460
55461 if (vs_min_size < (duk_size_t) (thr->valstack_top - thr->valstack)) {
55462 DUK_DDD(DUK_DDDPRINT(("final size smaller, set top before resize")));
55463
55464 DUK_ASSERT(nregs >= 0); /* can't happen when keeping current stack size */
55465 duk_set_top(ctx, idx_args + nargs); /* clamp anything above nargs */
55466 duk_set_top(ctx, idx_args + nregs); /* extend with undefined */
55467 adjusted_top = 1;
55468 }
55469
55470 (void) duk_valstack_resize_raw((duk_context *) thr,
55471 vs_min_size,
55472 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
55473 0 /* no compact */ |
55475
55476 if (!adjusted_top) {
55477 if (nregs >= 0) {
55478 DUK_ASSERT(nregs >= nargs);
55479 duk_set_top(ctx, idx_args + nargs); /* clamp anything above nargs */
55480 duk_set_top(ctx, idx_args + nregs); /* extend with undefined */
55481 }
55482 }
55483}
55484
55485/*
55486 * Manipulate value stack so that exactly 'num_stack_rets' return
55487 * values are at 'idx_retbase' in every case, assuming there are
55488 * 'rc' return values on top of stack.
55489 *
55490 * This is a bit tricky, because the called C function operates in
55491 * the same activation record and may have e.g. popped the stack
55492 * empty (below idx_retbase).
55493 */
55494
55495DUK_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) {
55496 duk_context *ctx = (duk_context *) thr;
55497 duk_idx_t idx_rcbase;
55498
55499 DUK_ASSERT(thr != NULL);
55500 DUK_ASSERT(idx_retbase >= 0);
55501 DUK_ASSERT(num_stack_rets >= 0);
55502 DUK_ASSERT(num_actual_rets >= 0);
55503
55504 idx_rcbase = duk_get_top(ctx) - num_actual_rets; /* base of known return values */
55505
55506 DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
55507 "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
55508 (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(ctx),
55509 (long) idx_retbase, (long) idx_rcbase));
55510
55511 DUK_ASSERT(idx_rcbase >= 0); /* caller must check */
55512
55513 /* Ensure space for final configuration (idx_retbase + num_stack_rets)
55514 * and intermediate configurations.
55515 */
55517 (idx_rcbase > idx_retbase ? idx_rcbase : idx_retbase) +
55518 num_stack_rets);
55519
55520 /* Chop extra retvals away / extend with undefined. */
55521 duk_set_top(ctx, idx_rcbase + num_stack_rets);
55522
55523 if (idx_rcbase >= idx_retbase) {
55524 duk_idx_t count = idx_rcbase - idx_retbase;
55525 duk_idx_t i;
55526
55527 DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
55528 "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
55529
55530 /* nuke values at idx_retbase to get the first retval (initially
55531 * at idx_rcbase) to idx_retbase
55532 */
55533
55534 DUK_ASSERT(count >= 0);
55535
55536 for (i = 0; i < count; i++) {
55537 /* XXX: inefficient; block remove primitive */
55538 duk_remove(ctx, idx_retbase);
55539 }
55540 } else {
55541 duk_idx_t count = idx_retbase - idx_rcbase;
55542 duk_idx_t i;
55543
55544 DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
55545 "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
55546
55547 /* insert 'undefined' values at idx_rcbase to get the
55548 * return values to idx_retbase
55550
55551 DUK_ASSERT(count > 0);
55552
55553 for (i = 0; i < count; i++) {
55554 /* XXX: inefficient; block insert primitive */
55555 duk_push_undefined(ctx);
55556 duk_insert(ctx, idx_rcbase);
55557 }
55558 }
55559}
55560
55561/*
55562 * Misc shared helpers.
55563 */
55564
55565/* Get valstack index for the func argument or throw if insane stack. */
55567 duk_size_t off_stack_top;
55568 duk_size_t off_stack_args;
55569 duk_size_t off_stack_all;
55570 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55571
55572 /* Argument validation and func/args offset. */
55573 off_stack_top = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack_bottom);
55574 off_stack_args = (duk_size_t) ((duk_size_t) num_stack_args * sizeof(duk_tval));
55575 off_stack_all = off_stack_args + 2 * sizeof(duk_tval);
55576 if (DUK_UNLIKELY(off_stack_all > off_stack_top)) {
55577 /* Since stack indices are not reliable, we can't do anything useful
55578 * here. Invoke the existing setjmp catcher, or if it doesn't exist,
55579 * call the fatal error handler.
55580 */
55582 return 0;
55583 }
55584 idx_func = (duk_idx_t) ((off_stack_top - off_stack_all) / sizeof(duk_tval));
55585 return idx_func;
55586}
55587
55588/*
55589 * duk_handle_call_protected() and duk_handle_call_unprotected():
55590 * call into a Duktape/C or an Ecmascript function from any state.
55591 *
55592 * Input stack (thr):
55594 * [ func this arg1 ... argN ]
55595 *
55596 * Output stack (thr):
55597 *
55598 * [ retval ] (DUK_EXEC_SUCCESS)
55599 * [ errobj ] (DUK_EXEC_ERROR (normal error), protected call)
55600 *
55601 * Even when executing a protected call an error may be thrown in rare cases
55602 * such as an insane num_stack_args argument. If there is no catchpoint for
55603 * such errors, the fatal error handler is called.
55604 *
55605 * The error handling path should be error free, even for out-of-memory
55606 * errors, to ensure safe sandboxing. (As of Duktape 1.4.0 this is not
55607 * yet the case, see XXX notes below.)
55608 */
55609
55611 duk_idx_t num_stack_args,
55612 duk_small_uint_t call_flags) {
55613 duk_context *ctx;
55614 duk_size_t entry_valstack_bottom_index;
55615 duk_size_t entry_valstack_end;
55616 duk_size_t entry_callstack_top;
55617 duk_size_t entry_catchstack_top;
55618 duk_int_t entry_call_recursion_depth;
55619 duk_hthread *entry_curr_thread;
55620 duk_uint_fast8_t entry_thread_state;
55621 duk_instr_t **entry_ptr_curr_pc;
55622 duk_jmpbuf *old_jmpbuf_ptr = NULL;
55623 duk_jmpbuf our_jmpbuf;
55624 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55625
55626 /* XXX: Multiple tv_func lookups are now avoided by making a local
55627 * copy of tv_func. Another approach would be to compute an offset
55628 * for tv_func from valstack bottom and recomputing the tv_func
55629 * pointer quickly as valstack + offset instead of calling duk_get_tval().
55630 */
55631
55632 ctx = (duk_context *) thr;
55633 DUK_UNREF(ctx);
55634 DUK_ASSERT(thr != NULL);
55636 DUK_ASSERT(num_stack_args >= 0);
55637 /* XXX: currently NULL allocations are not supported; remove if later allowed */
55638 DUK_ASSERT(thr->valstack != NULL);
55639 DUK_ASSERT(thr->callstack != NULL);
55640 DUK_ASSERT(thr->catchstack != NULL);
55641
55642 /* Argument validation and func/args offset. */
55643 idx_func = duk__get_idx_func(thr, num_stack_args);
55644
55645 /* Preliminaries, required by setjmp() handler. Must be careful not
55646 * to throw an unintended error here.
55647 */
55648
55649 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
55650#if defined(DUK_USE_PREFER_SIZE)
55651 entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
55652#else
55653 DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
55654 entry_valstack_end = thr->valstack_size;
55655#endif
55656 entry_callstack_top = thr->callstack_top;
55657 entry_catchstack_top = thr->catchstack_top;
55658 entry_call_recursion_depth = thr->heap->call_recursion_depth;
55659 entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
55660 entry_thread_state = thr->state;
55661 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
55662
55663 DUK_DD(DUK_DDPRINT("duk_handle_call_protected: thr=%p, num_stack_args=%ld, "
55664 "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
55665 "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
55666 "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
55667 "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
55668 (void *) thr,
55669 (long) num_stack_args,
55670 (unsigned long) call_flags,
55671 (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
55672 (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
55673 (long) duk_get_top(ctx),
55674 (long) idx_func,
55675 (long) (idx_func + 2),
55676 (long) thr->heap->call_recursion_depth,
55677 (long) thr->heap->call_recursion_limit,
55678 (long) entry_valstack_bottom_index,
55679 (long) entry_callstack_top,
55680 (long) entry_catchstack_top,
55681 (long) entry_call_recursion_depth,
55682 (void *) entry_curr_thread,
55683 (long) entry_thread_state));
55684
55685 old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
55686 thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
55687
55688#if defined(DUK_USE_CPP_EXCEPTIONS)
55689 try {
55690#else
55691 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
55692 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
55693#endif
55694 /* Call handling and success path. Success path exit cleans
55695 * up almost all state.
55696 */
55697 duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
55698
55699 /* Success path handles */
55700 DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
55701 DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
55702
55703 /* Longjmp state is kept clean in success path */
55705 DUK_ASSERT(thr->heap->lj.iserror == 0);
55708
55709 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
55710
55711 return DUK_EXEC_SUCCESS;
55712#if defined(DUK_USE_CPP_EXCEPTIONS)
55713 } catch (duk_internal_exception &exc) {
55714#else
55715 } else {
55716#endif
55717 /* Error; error value is in heap->lj.value1. */
55718
55719#if defined(DUK_USE_CPP_EXCEPTIONS)
55720 DUK_UNREF(exc);
55721#endif
55722
55724 entry_valstack_bottom_index,
55725 entry_valstack_end,
55726 entry_catchstack_top,
55727 entry_callstack_top,
55728 entry_call_recursion_depth,
55729 entry_curr_thread,
55730 entry_thread_state,
55731 entry_ptr_curr_pc,
55732 idx_func,
55733 old_jmpbuf_ptr);
55734
55735 /* Longjmp state is cleaned up by error handling */
55737 DUK_ASSERT(thr->heap->lj.iserror == 0);
55740 return DUK_EXEC_ERROR;
55741 }
55742#if defined(DUK_USE_CPP_EXCEPTIONS)
55743 catch (std::exception &exc) {
55744 const char *what = exc.what();
55745 if (!what) {
55746 what = "unknown";
55747 }
55748 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
55749 try {
55750 DUK_ERROR_FMT1(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
55751 } catch (duk_internal_exception exc) {
55752 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
55753 DUK_UNREF(exc);
55755 entry_valstack_bottom_index,
55756 entry_valstack_end,
55757 entry_catchstack_top,
55758 entry_callstack_top,
55759 entry_call_recursion_depth,
55760 entry_curr_thread,
55761 entry_thread_state,
55762 entry_ptr_curr_pc,
55763 idx_func,
55764 old_jmpbuf_ptr);
55765 return DUK_EXEC_ERROR;
55766 }
55767 } catch (...) {
55768 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
55769 try {
55770 DUK_ERROR_API(thr, "caught invalid c++ exception (perhaps thrown by user code)");
55771 } catch (duk_internal_exception exc) {
55772 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
55773 DUK_UNREF(exc);
55775 entry_valstack_bottom_index,
55776 entry_valstack_end,
55777 entry_catchstack_top,
55778 entry_callstack_top,
55779 entry_call_recursion_depth,
55780 entry_curr_thread,
55781 entry_thread_state,
55782 entry_ptr_curr_pc,
55783 idx_func,
55784 old_jmpbuf_ptr);
55786 }
55787 }
55788#endif
55789}
55790
55792 duk_idx_t num_stack_args,
55793 duk_small_uint_t call_flags) {
55794 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55795
55796 /* Argument validation and func/args offset. */
55797 idx_func = duk__get_idx_func(thr, num_stack_args);
55798
55799 duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
55800}
55801
55803 duk_idx_t num_stack_args,
55804 duk_small_uint_t call_flags,
55805 duk_idx_t idx_func) {
55806 duk_context *ctx;
55807 duk_size_t entry_valstack_bottom_index;
55808 duk_size_t entry_valstack_end;
55809 duk_size_t entry_callstack_top;
55810 duk_size_t entry_catchstack_top;
55811 duk_int_t entry_call_recursion_depth;
55812 duk_hthread *entry_curr_thread;
55813 duk_uint_fast8_t entry_thread_state;
55814 duk_instr_t **entry_ptr_curr_pc;
55815 duk_idx_t nargs; /* # argument registers target function wants (< 0 => "as is") */
55816 duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => "as is") */
55817 duk_hobject *func; /* 'func' on stack (borrowed reference) */
55818 duk_tval *tv_func; /* duk_tval ptr for 'func' on stack (borrowed reference) or tv_func_copy */
55819 duk_tval tv_func_copy; /* to avoid relookups */
55820 duk_activation *act;
55821 duk_hobject *env;
55822 duk_ret_t rc;
55823
55824 ctx = (duk_context *) thr;
55825 DUK_ASSERT(thr != NULL);
55827 DUK_ASSERT(ctx != NULL);
55828 DUK_ASSERT(num_stack_args >= 0);
55829 /* XXX: currently NULL allocations are not supported; remove if later allowed */
55830 DUK_ASSERT(thr->valstack != NULL);
55831 DUK_ASSERT(thr->callstack != NULL);
55832 DUK_ASSERT(thr->catchstack != NULL);
55833
55834 DUK_DD(DUK_DDPRINT("duk__handle_call_inner: num_stack_args=%ld, call_flags=0x%08lx, top=%ld",
55835 (long) num_stack_args, (long) call_flags, (long) duk_get_top(ctx)));
55836
55837 /*
55838 * Store entry state.
55839 */
55840
55841 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
55842#if defined(DUK_USE_PREFER_SIZE)
55843 entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
55844#else
55845 DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
55846 entry_valstack_end = thr->valstack_size;
55847#endif
55848 entry_callstack_top = thr->callstack_top;
55849 entry_catchstack_top = thr->catchstack_top;
55850 entry_call_recursion_depth = thr->heap->call_recursion_depth;
55851 entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
55852 entry_thread_state = thr->state;
55853 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
55854
55855 /* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
55856 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
55857 * activation when side effects occur.
55858 */
55860
55861 DUK_DD(DUK_DDPRINT("duk__handle_call_inner: thr=%p, num_stack_args=%ld, "
55862 "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
55863 "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
55864 "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
55865 "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
55866 (void *) thr,
55867 (long) num_stack_args,
55868 (unsigned long) call_flags,
55869 (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
55870 (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
55871 (long) duk_get_top(ctx),
55872 (long) idx_func,
55873 (long) (idx_func + 2),
55874 (long) thr->heap->call_recursion_depth,
55875 (long) thr->heap->call_recursion_limit,
55876 (long) entry_valstack_bottom_index,
55877 (long) entry_callstack_top,
55878 (long) entry_catchstack_top,
55879 (long) entry_call_recursion_depth,
55880 (void *) entry_curr_thread,
55881 (long) entry_thread_state));
55882
55883
55884 /*
55885 * Thread state check and book-keeping.
55886 */
55887
55888 if (thr == thr->heap->curr_thread) {
55889 /* same thread */
55890 if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
55891 /* should actually never happen, but check anyway */
55892 goto thread_state_error;
55893 }
55894 } else {
55895 /* different thread */
55896 DUK_ASSERT(thr->heap->curr_thread == NULL ||
55897 thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
55898 if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
55899 goto thread_state_error;
55900 }
55901 DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
55902 thr->state = DUK_HTHREAD_STATE_RUNNING;
55903
55904 /* Note: multiple threads may be simultaneously in the RUNNING
55905 * state, but not in the same "resume chain".
55906 */
55907 }
55908 DUK_ASSERT(thr->heap->curr_thread == thr);
55910
55911 /*
55912 * C call recursion depth check, which provides a reasonable upper
55913 * bound on maximum C stack size (arbitrary C stack growth is only
55914 * possible by recursive handle_call / handle_safe_call calls).
55915 */
55916
55917 /* XXX: remove DUK_CALL_FLAG_IGNORE_RECLIMIT flag: there's now the
55918 * reclimit bump?
55919 */
55920
55921 DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
55922 DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
55923 if (call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) {
55924 DUK_DD(DUK_DDPRINT("ignoring reclimit for this call (probably an errhandler call)"));
55925 } else {
55926 if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit) {
55927 /* XXX: error message is a bit misleading: we reached a recursion
55928 * limit which is also essentially the same as a C callstack limit
55929 * (except perhaps with some relaxed threading assumptions).
55930 */
55932 }
55933 thr->heap->call_recursion_depth++;
55934 }
55935
55936 /*
55937 * Check the function type, handle bound function chains, and prepare
55938 * parameters for the rest of the call handling. Also figure out the
55939 * effective 'this' binding, which replaces the current value at
55940 * idx_func + 1.
55941 *
55942 * If the target function is a 'bound' one, follow the chain of 'bound'
55943 * functions until a non-bound function is found. During this process,
55944 * bound arguments are 'prepended' to existing ones, and the "this"
55945 * binding is overridden. See E5 Section 15.3.4.5.1.
55946 *
55947 * Lightfunc detection happens here too. Note that lightweight functions
55948 * can be wrapped by (non-lightweight) bound functions so we must resolve
55949 * the bound function chain first.
55950 */
55951
55952 func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
55953 DUK_TVAL_SET_TVAL(&tv_func_copy, tv_func);
55954 tv_func = &tv_func_copy; /* local copy to avoid relookups */
55955
55956 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
55959
55960 duk__coerce_effective_this_binding(thr, func, idx_func + 1);
55961 DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
55962 (duk_tval *) duk_get_tval(ctx, idx_func + 1)));
55963
55964 /* [ ... func this arg1 ... argN ] */
55965
55966 /*
55967 * Setup a preliminary activation and figure out nargs/nregs.
55968 *
55969 * Don't touch valstack_bottom or valstack_top yet so that Duktape API
55970 * calls work normally.
55971 */
55972
55974
55975 if (thr->callstack_top > 0) {
55976 /*
55977 * Update idx_retval of current activation.
55978 *
55979 * Although it might seem this is not necessary (bytecode executor
55980 * does this for Ecmascript-to-Ecmascript calls; other calls are
55981 * handled here), this turns out to be necessary for handling yield
55982 * and resume. For them, an Ecmascript-to-native call happens, and
55983 * the Ecmascript call's idx_retval must be set for things to work.
55984 */
55985
55986 (thr->callstack + thr->callstack_top - 1)->idx_retval = entry_valstack_bottom_index + idx_func;
55987 }
55988
55989 DUK_ASSERT(thr->callstack_top < thr->callstack_size);
55990 act = thr->callstack + thr->callstack_top;
55991 thr->callstack_top++;
55992 DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
55993 DUK_ASSERT(thr->valstack_top > thr->valstack_bottom); /* at least effective 'this' */
55994 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
55995
55996 act->flags = 0;
55997
55998 /* For now all calls except Ecma-to-Ecma calls prevent a yield. */
56000 if (call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) {
56002 }
56003 if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
56005 }
56006
56007 /* These base values are never used, but if the compiler doesn't know
56008 * that DUK_ERROR() won't return, these are needed to silence warnings.
56009 * On the other hand, scan-build will warn about the values not being
56010 * used, so add a DUK_UNREF.
56011 */
56012 nargs = 0; DUK_UNREF(nargs);
56013 nregs = 0; DUK_UNREF(nregs);
56014
56015 if (DUK_LIKELY(func != NULL)) {
56016 if (DUK_HOBJECT_HAS_STRICT(func)) {
56017 act->flags |= DUK_ACT_FLAG_STRICT;
56018 }
56020 nargs = ((duk_hcompiledfunction *) func)->nargs;
56021 nregs = ((duk_hcompiledfunction *) func)->nregs;
56022 DUK_ASSERT(nregs >= nargs);
56023 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
56024 /* Note: nargs (and nregs) may be negative for a native,
56025 * function, which indicates that the function wants the
56026 * input stack "as is" (i.e. handles "vararg" arguments).
56027 */
56028 nargs = ((duk_hnativefunction *) func)->nargs;
56029 nregs = nargs;
56030 } else {
56031 /* XXX: this should be an assert */
56033 }
56034 } else {
56035 duk_small_uint_t lf_flags;
56036
56038 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
56039 nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
56040 if (nargs == DUK_LFUNC_NARGS_VARARGS) {
56041 nargs = -1; /* vararg */
56042 }
56043 nregs = nargs;
56044
56045 act->flags |= DUK_ACT_FLAG_STRICT;
56046 }
56047
56048 act->func = func; /* NULL for lightfunc */
56049 act->var_env = NULL;
56050 act->lex_env = NULL;
56051#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
56052 act->prev_caller = NULL;
56053#endif
56054 act->curr_pc = NULL;
56055#if defined(DUK_USE_DEBUGGER_SUPPORT)
56056 act->prev_line = 0;
56057#endif
56058 act->idx_bottom = entry_valstack_bottom_index + idx_func + 2;
56059#if 0 /* topmost activation idx_retval is considered garbage, no need to init */
56060 act->idx_retval = 0;
56061#endif
56062 DUK_TVAL_SET_TVAL(&act->tv_func, tv_func); /* borrowed, no refcount */
56063
56064 /* XXX: remove the preventcount and make yield walk the callstack?
56065 * Or perhaps just use a single flag, not a counter, faster to just
56066 * set and restore?
56067 */
56068 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
56069 /* duk_hthread_callstack_unwind() will decrease this on unwind */
56070 thr->callstack_preventcount++;
56071 }
56072
56073 /* XXX: Is this INCREF necessary? 'func' is always a borrowed
56074 * reference reachable through the value stack? If changed, stack
56075 * unwind code also needs to be fixed to match.
56076 */
56077 DUK_HOBJECT_INCREF_ALLOWNULL(thr, func); /* act->func */
56078
56079#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
56080 if (func) {
56081 duk__update_func_caller_prop(thr, func);
56082 }
56083 act = thr->callstack + thr->callstack_top - 1;
56084#endif
56085
56086 /* [ ... func this arg1 ... argN ] */
56087
56088 /*
56089 * Environment record creation and 'arguments' object creation.
56090 * Named function expression name binding is handled by the
56091 * compiler; the compiled function's parent env will contain
56092 * the (immutable) binding already.
56093 *
56094 * This handling is now identical for C and Ecmascript functions.
56095 * C functions always have the 'NEWENV' flag set, so their
56096 * environment record initialization is delayed (which is good).
56097 *
56098 * Delayed creation (on demand) is handled in duk_js_var.c.
56099 */
56100
56101 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func)); /* bound function chain has already been resolved */
56102
56103 if (DUK_LIKELY(func != NULL)) {
56106 /* Use a new environment but there's no 'arguments' object;
56107 * delayed environment initialization. This is the most
56108 * common case.
56109 */
56110 DUK_ASSERT(act->lex_env == NULL);
56111 DUK_ASSERT(act->var_env == NULL);
56112 } else {
56113 /* Use a new environment and there's an 'arguments' object.
56114 * We need to initialize it right now.
56115 */
56116
56117 /* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
56119 DUK_ASSERT(env != NULL);
56120
56121 /* [ ... func this arg1 ... argN envobj ] */
56122
56124 duk__handle_createargs_for_call(thr, func, env, num_stack_args);
56125
56126 /* [ ... func this arg1 ... argN envobj ] */
56127
56128 act = thr->callstack + thr->callstack_top - 1;
56129 act->lex_env = env;
56130 act->var_env = env;
56131 DUK_HOBJECT_INCREF(thr, env);
56132 DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (2) directly */
56133 duk_pop(ctx);
56134 }
56135 } else {
56136 /* Use existing env (e.g. for non-strict eval); cannot have
56137 * an own 'arguments' object (but can refer to an existing one).
56138 */
56139
56141
56142 duk__handle_oldenv_for_call(thr, func, act);
56143
56144 DUK_ASSERT(act->lex_env != NULL);
56145 DUK_ASSERT(act->var_env != NULL);
56146 }
56147 } else {
56148 /* Lightfuncs are always native functions and have "newenv". */
56149 DUK_ASSERT(act->lex_env == NULL);
56150 DUK_ASSERT(act->var_env == NULL);
56151 }
56152
56153 /* [ ... func this arg1 ... argN ] */
56154
56155 /*
56156 * Setup value stack: clamp to 'nargs', fill up to 'nregs'
56157 *
56158 * Value stack may either grow or shrink, depending on the
56159 * number of func registers and the number of actual arguments.
56160 * If nregs >= 0, func wants args clamped to 'nargs'; else it
56161 * wants all args (= 'num_stack_args').
56162 */
56163
56164 /* XXX: optimize value stack operation */
56165 /* XXX: don't want to shrink allocation here */
56166
56168 num_stack_args,
56169 idx_func + 2,
56170 nregs,
56171 nargs,
56172 func);
56173
56174 /*
56175 * Determine call type, then finalize activation, shift to
56176 * new value stack bottom, and call the target.
56177 */
56178
56179 if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
56180 /*
56181 * Ecmascript call
56182 */
56183
56184 duk_tval *tv_ret;
56185 duk_tval *tv_funret;
56186
56187 DUK_ASSERT(func != NULL);
56190
56191 thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
56192 /* keep current valstack_top */
56193 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56194 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56195 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56196
56197 /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
56198
56199 /*
56200 * Bytecode executor call.
56201 *
56202 * Execute bytecode, handling any recursive function calls and
56203 * thread resumptions. Returns when execution would return from
56204 * the entry level activation. When the executor returns, a
56205 * single return value is left on the stack top.
56206 *
56207 * The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
56208 * other types are handled internally by the executor.
56209 */
56210
56211 /* thr->ptr_curr_pc is set by bytecode executor early on entry */
56212 DUK_ASSERT(thr->ptr_curr_pc == NULL);
56213 DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
56215 DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
56216
56217 /* Unwind. */
56218
56219 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top); /* may need unwind */
56220 DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56221 DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56222 duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56224 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56226
56227 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56228 /* keep current valstack_top */
56229 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56230 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56231 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56232 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
56233
56234 /* Return value handling. */
56235
56236 /* [ ... func this (crud) retval ] */
56237
56238 tv_ret = thr->valstack_bottom + idx_func;
56239 tv_funret = thr->valstack_top - 1;
56240#if defined(DUK_USE_FASTINT)
56241 /* Explicit check for fastint downgrade. */
56242 DUK_TVAL_CHKFAST_INPLACE(tv_funret);
56243#endif
56244 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
56245 } else {
56246 /*
56247 * Native call.
56248 */
56249
56250 duk_tval *tv_ret;
56251 duk_tval *tv_funret;
56252
56253 thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
56254 /* keep current valstack_top */
56255 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56256 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56257 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56258 DUK_ASSERT(func == NULL || ((duk_hnativefunction *) func)->func != NULL);
56259
56260 /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
56261
56262 /* For native calls must be NULL so we don't sync back */
56263 DUK_ASSERT(thr->ptr_curr_pc == NULL);
56264
56265 if (func) {
56266 rc = ((duk_hnativefunction *) func)->func((duk_context *) thr);
56267 } else {
56269 rc = funcptr((duk_context *) thr);
56270 }
56271
56272 /* Automatic error throwing, retval check. */
56273
56274 if (rc < 0) {
56277 } else if (rc > 1) {
56278 DUK_ERROR_API(thr, "c function returned invalid rc");
56279 }
56280 DUK_ASSERT(rc == 0 || rc == 1);
56281
56282 /* Unwind. */
56283
56284 DUK_ASSERT(thr->catchstack_top == entry_catchstack_top); /* no need to unwind */
56285 DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56286 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56288
56289 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56290 /* keep current valstack_top */
56291 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56292 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56293 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56294 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
56295
56296 /* Return value handling. */
56297
56298 /* XXX: should this happen in the callee's activation or after unwinding? */
56299 tv_ret = thr->valstack_bottom + idx_func;
56300 if (rc == 0) {
56301 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv_ret); /* side effects */
56302 } else {
56303 /* [ ... func this (crud) retval ] */
56304 tv_funret = thr->valstack_top - 1;
56305#if defined(DUK_USE_FASTINT)
56306 /* Explicit check for fastint downgrade. */
56307 DUK_TVAL_CHKFAST_INPLACE(tv_funret);
56308#endif
56309 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
56310 }
56311 }
56312
56313 duk_set_top(ctx, idx_func + 1); /* XXX: unnecessary, handle in adjust */
56314
56315 /* [ ... retval ] */
56316
56317 /* Ensure there is internal valstack spare before we exit; this may
56318 * throw an alloc error. The same guaranteed size must be available
56319 * as before the call. This is not optimal now: we store the valstack
56320 * allocated size during entry; this value may be higher than the
56321 * minimal guarantee for an application.
56322 */
56323
56324 /* XXX: we should never shrink here; when we error out later, we'd
56325 * need to potentially grow the value stack in error unwind which could
56326 * cause another error.
56327 */
56328
56329 (void) duk_valstack_resize_raw((duk_context *) thr,
56330 entry_valstack_end, /* same as during entry */
56331 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
56334
56335 /* Restore entry thread executor curr_pc stack frame pointer. */
56336 thr->ptr_curr_pc = entry_ptr_curr_pc;
56337
56338 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
56339 thr->state = (duk_uint8_t) entry_thread_state;
56340
56341 DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
56342 (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
56343 (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
56344
56345 thr->heap->call_recursion_depth = entry_call_recursion_depth;
56346
56347 /* If the debugger is active we need to force an interrupt so that
56348 * debugger breakpoints are rechecked. This is important for function
56349 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
56350 * GH-303. Only needed for success path, error path always causes a
56351 * breakpoint recheck in the executor. It would be enough to set this
56352 * only when returning to an Ecmascript activation, but setting the flag
56353 * on every return should have no ill effect.
56354 */
56355#if defined(DUK_USE_DEBUGGER_SUPPORT)
56356 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
56357 DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
56358 DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
56359 thr->interrupt_init -= thr->interrupt_counter;
56360 thr->interrupt_counter = 0;
56361 thr->heap->dbg_force_restart = 1;
56362 }
56363#endif
56364
56365#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
56366 duk__interrupt_fixup(thr, entry_curr_thread);
56367#endif
56368
56369 return;
56370
56371 thread_state_error:
56372 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for call (%ld)", (long) thr->state);
56374 return; /* never executed */
56375}
56376
56378 duk_size_t entry_valstack_bottom_index,
56379 duk_size_t entry_valstack_end,
56380 duk_size_t entry_catchstack_top,
56381 duk_size_t entry_callstack_top,
56382 duk_int_t entry_call_recursion_depth,
56383 duk_hthread *entry_curr_thread,
56384 duk_uint_fast8_t entry_thread_state,
56385 duk_instr_t **entry_ptr_curr_pc,
56386 duk_idx_t idx_func,
56387 duk_jmpbuf *old_jmpbuf_ptr) {
56388 duk_context *ctx;
56389 duk_tval *tv_ret;
56390
56391 ctx = (duk_context *) thr;
56392
56393 DUK_DDD(DUK_DDDPRINT("error caught during duk__handle_call_inner(): %!T",
56394 (duk_tval *) &thr->heap->lj.value1));
56395
56396 /* Other longjmp types are handled by executor before propagating
56397 * the error here.
56398 */
56400 DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
56401 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
56402
56403 /* We don't need to sync back thr->ptr_curr_pc here because
56404 * the bytecode executor always has a setjmp catchpoint which
56405 * does that before errors propagate to here.
56406 */
56407 DUK_ASSERT(thr->ptr_curr_pc == NULL);
56408
56409 /* Restore the previous setjmp catcher so that any error in
56410 * error handling will propagate outwards rather than re-enter
56411 * the same handler. However, the error handling path must be
56412 * designed to be error free so that sandboxing guarantees are
56413 * reliable, see e.g. https://github.com/svaarala/duktape/issues/476.
56414 */
56415 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56416
56417 /* XXX: callstack unwind may now throw an error when closing
56418 * scopes; this is a sandboxing issue, described in:
56419 * https://github.com/svaarala/duktape/issues/476
56420 */
56421 duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56423 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56425
56426 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56427 tv_ret = thr->valstack_bottom + idx_func; /* XXX: byte offset? */
56428 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, &thr->heap->lj.value1); /* side effects */
56429#if defined(DUK_USE_FASTINT)
56430 /* Explicit check for fastint downgrade. */
56432#endif
56433 duk_set_top(ctx, idx_func + 1); /* XXX: could be eliminated with valstack adjust */
56434
56435 /* [ ... errobj ] */
56436
56437 /* Ensure there is internal valstack spare before we exit; this may
56438 * throw an alloc error. The same guaranteed size must be available
56439 * as before the call. This is not optimal now: we store the valstack
56440 * allocated size during entry; this value may be higher than the
56441 * minimal guarantee for an application.
56442 */
56443
56444 /* XXX: this needs to be reworked so that we never shrink the value
56445 * stack on function entry so that we never need to grow it here.
56446 * Needing to grow here is a sandboxing issue because we need to
56447 * allocate which may cause an error in the error handling path
56448 * and thus propagate an error out of a protected call.
56449 */
56450
56451 (void) duk_valstack_resize_raw((duk_context *) thr,
56452 entry_valstack_end, /* same as during entry */
56453 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
56456
56457
56458 /* These are just convenience "wiping" of state. Side effects should
56459 * not be an issue here: thr->heap and thr->heap->lj have a stable
56460 * pointer. Finalizer runs etc capture even out-of-memory errors so
56461 * nothing should throw here.
56462 */
56464 thr->heap->lj.iserror = 0;
56465 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
56466 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
56467
56468 /* Restore entry thread executor curr_pc stack frame pointer. */
56469 thr->ptr_curr_pc = entry_ptr_curr_pc;
56470
56471 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
56472 thr->state = (duk_uint8_t) entry_thread_state;
56473
56474 DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
56475 (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
56476 (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
56477
56478 thr->heap->call_recursion_depth = entry_call_recursion_depth;
56479
56480 /* If the debugger is active we need to force an interrupt so that
56481 * debugger breakpoints are rechecked. This is important for function
56482 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
56483 * GH-303. Only needed for success path, error path always causes a
56484 * breakpoint recheck in the executor. It would be enough to set this
56485 * only when returning to an Ecmascript activation, but setting the flag
56486 * on every return should have no ill effect.
56487 */
56488#if defined(DUK_USE_DEBUGGER_SUPPORT)
56489 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
56490 DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
56491 DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
56492 thr->interrupt_init -= thr->interrupt_counter;
56493 thr->interrupt_counter = 0;
56494 thr->heap->dbg_force_restart = 1;
56495 }
56496#endif
56497
56498#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
56499 duk__interrupt_fixup(thr, entry_curr_thread);
56500#endif
56501}
56502
56503/*
56504 * duk_handle_safe_call(): make a "C protected call" within the
56505 * current activation.
56506 *
56507 * The allowed thread states for making a call are the same as for
56508 * duk_handle_call_xxx().
56509 *
56510 * Error handling is similar to duk_handle_call_xxx(); errors may be thrown
56511 * (and result in a fatal error) for insane arguments.
56512 */
56513
56514/* XXX: bump preventcount by one for the duration of this call? */
56515
56518 duk_idx_t num_stack_args,
56519 duk_idx_t num_stack_rets) {
56520 duk_context *ctx = (duk_context *) thr;
56521 duk_size_t entry_valstack_bottom_index;
56522 duk_size_t entry_callstack_top;
56523 duk_size_t entry_catchstack_top;
56524 duk_int_t entry_call_recursion_depth;
56525 duk_hthread *entry_curr_thread;
56526 duk_uint_fast8_t entry_thread_state;
56527 duk_instr_t **entry_ptr_curr_pc;
56528 duk_jmpbuf *old_jmpbuf_ptr = NULL;
56529 duk_jmpbuf our_jmpbuf;
56530 duk_idx_t idx_retbase;
56531 duk_int_t retval;
56532
56533 DUK_ASSERT(thr != NULL);
56534 DUK_ASSERT(ctx != NULL);
56535
56536 /* Note: careful with indices like '-x'; if 'x' is zero, it refers to bottom */
56537 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
56538 entry_callstack_top = thr->callstack_top;
56539 entry_catchstack_top = thr->catchstack_top;
56540 entry_call_recursion_depth = thr->heap->call_recursion_depth;
56541 entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
56542 entry_thread_state = thr->state;
56543 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
56544 idx_retbase = duk_get_top(ctx) - num_stack_args; /* Note: not a valid stack index if num_stack_args == 0 */
56545
56546 /* Note: cannot portably debug print a function pointer, hence 'func' not printed! */
56547 DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
56548 "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
56549 "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
56550 "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
56551 (void *) thr,
56552 (long) num_stack_args,
56553 (long) num_stack_rets,
56554 (long) duk_get_top(ctx),
56555 (long) idx_retbase,
56556 (long) thr->heap->call_recursion_depth,
56557 (long) thr->heap->call_recursion_limit,
56558 (long) entry_valstack_bottom_index,
56559 (long) entry_callstack_top,
56560 (long) entry_catchstack_top,
56561 (long) entry_call_recursion_depth,
56562 (void *) entry_curr_thread,
56563 (long) entry_thread_state));
56564
56565 if (idx_retbase < 0) {
56566 /* Since stack indices are not reliable, we can't do anything useful
56567 * here. Invoke the existing setjmp catcher, or if it doesn't exist,
56568 * call the fatal error handler.
56569 */
56570
56572 }
56573
56574 /* setjmp catchpoint setup */
56575
56576 old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
56577 thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
56578
56579#if defined(DUK_USE_CPP_EXCEPTIONS)
56580 try {
56581#else
56582 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
56583 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
56584 /* Success path. */
56585#endif
56586 DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
56587
56589 func,
56590 idx_retbase,
56591 num_stack_rets,
56592 entry_valstack_bottom_index,
56593 entry_callstack_top,
56594 entry_catchstack_top);
56595
56596 /* Longjmp state is kept clean in success path */
56597 DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
56598 DUK_ASSERT(thr->heap->lj.iserror == 0);
56599 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
56600 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
56601
56602 /* Note: either pointer may be NULL (at entry), so don't assert */
56603 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56604
56605 retval = DUK_EXEC_SUCCESS;
56606#if defined(DUK_USE_CPP_EXCEPTIONS)
56607 } catch (duk_internal_exception &exc) {
56608 DUK_UNREF(exc);
56609#else
56610 } else {
56611 /* Error path. */
56612#endif
56614 idx_retbase,
56615 num_stack_rets,
56616 entry_valstack_bottom_index,
56617 entry_callstack_top,
56618 entry_catchstack_top,
56619 old_jmpbuf_ptr);
56620
56621 /* Longjmp state is cleaned up by error handling */
56622 DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
56623 DUK_ASSERT(thr->heap->lj.iserror == 0);
56624 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
56625 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
56626
56627 retval = DUK_EXEC_ERROR;
56628 }
56629#if defined(DUK_USE_CPP_EXCEPTIONS)
56630 catch (std::exception &exc) {
56631 const char *what = exc.what();
56632 if (!what) {
56633 what = "unknown";
56634 }
56635 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
56636 try {
56637 DUK_ERROR_FMT1(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
56638 } catch (duk_internal_exception exc) {
56639 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
56640 DUK_UNREF(exc);
56642 idx_retbase,
56643 num_stack_rets,
56644 entry_valstack_bottom_index,
56645 entry_callstack_top,
56646 entry_catchstack_top,
56647 old_jmpbuf_ptr);
56648 retval = DUK_EXEC_ERROR;
56649 }
56650 } catch (...) {
56651 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
56652 try {
56653 DUK_ERROR_API(thr, "caught invalid c++ exception (perhaps thrown by user code)");
56654 } catch (duk_internal_exception exc) {
56655 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
56656 DUK_UNREF(exc);
56658 idx_retbase,
56659 num_stack_rets,
56660 entry_valstack_bottom_index,
56661 entry_callstack_top,
56662 entry_catchstack_top,
56663 old_jmpbuf_ptr);
56664 retval = DUK_EXEC_ERROR;
56666 }
56667#endif
56668
56669 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr); /* success/error path both do this */
56670
56672 idx_retbase,
56673 num_stack_rets,
56674 entry_call_recursion_depth,
56675 entry_curr_thread,
56676 entry_thread_state,
56677 entry_ptr_curr_pc);
56678
56679 return retval;
56680}
56681
56684 duk_idx_t idx_retbase,
56685 duk_idx_t num_stack_rets,
56686 duk_size_t entry_valstack_bottom_index,
56687 duk_size_t entry_callstack_top,
56688 duk_size_t entry_catchstack_top) {
56689 duk_context *ctx;
56690 duk_ret_t rc;
56691
56692 DUK_ASSERT(thr != NULL);
56693 ctx = (duk_context *) thr;
56695 DUK_UNREF(entry_valstack_bottom_index);
56696 DUK_UNREF(entry_callstack_top);
56697 DUK_UNREF(entry_catchstack_top);
56698
56699 /*
56700 * Thread state check and book-keeping.
56701 */
56702
56703 if (thr == thr->heap->curr_thread) {
56704 /* same thread */
56705 if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
56706 /* should actually never happen, but check anyway */
56707 goto thread_state_error;
56708 }
56709 } else {
56710 /* different thread */
56711 DUK_ASSERT(thr->heap->curr_thread == NULL ||
56713 if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
56714 goto thread_state_error;
56715 }
56716 DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
56718
56719 /* Note: multiple threads may be simultaneously in the RUNNING
56720 * state, but not in the same "resume chain".
56721 */
56722 }
56723
56724 DUK_ASSERT(thr->heap->curr_thread == thr);
56726
56727 /*
56728 * Recursion limit check.
56729 *
56730 * Note: there is no need for an "ignore recursion limit" flag
56731 * for duk_handle_safe_call now.
56732 */
56733
56737 /* XXX: error message is a bit misleading: we reached a recursion
56738 * limit which is also essentially the same as a C callstack limit
56739 * (except perhaps with some relaxed threading assumptions).
56740 */
56742 }
56743 thr->heap->call_recursion_depth++;
56744
56745 /*
56746 * Valstack spare check
56747 */
56748
56749 duk_require_stack(ctx, 0); /* internal spare */
56750
56751 /*
56752 * Make the C call
56753 */
56754
56755 rc = func(ctx);
56756
56757 DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
56758
56759 /*
56760 * Valstack manipulation for results.
56761 */
56762
56763 /* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
56764 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
56765 DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);
56766 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56767 DUK_ASSERT((duk_size_t) (thr->valstack_bottom - thr->valstack) == entry_valstack_bottom_index);
56769 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56770
56771 if (rc < 0) {
56773 }
56774 DUK_ASSERT(rc >= 0);
56775
56776 if (duk_get_top(ctx) < rc) {
56777 DUK_ERROR_API(thr, "not enough stack values for safe_call rc");
56778 }
56779
56780 DUK_ASSERT(thr->catchstack_top == entry_catchstack_top); /* no need to unwind */
56781 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
56782
56783 duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);
56784 return;
56785
56786 thread_state_error:
56787 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for safe_call (%ld)", (long) thr->state);
56789}
56790
56792 duk_idx_t idx_retbase,
56793 duk_idx_t num_stack_rets,
56794 duk_size_t entry_valstack_bottom_index,
56795 duk_size_t entry_callstack_top,
56796 duk_size_t entry_catchstack_top,
56797 duk_jmpbuf *old_jmpbuf_ptr) {
56798 duk_context *ctx;
56799
56800 DUK_ASSERT(thr != NULL);
56801 ctx = (duk_context *) thr;
56803
56804 /*
56805 * Error during call. The error value is at heap->lj.value1.
56806 *
56807 * The very first thing we do is restore the previous setjmp catcher.
56808 * This means that any error in error handling will propagate outwards
56809 * instead of causing a setjmp() re-entry above.
56810 */
56811
56812 DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
56813
56814 /* Other longjmp types are handled by executor before propagating
56815 * the error here.
56816 */
56818 DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
56819 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
56820
56821 /* Note: either pointer may be NULL (at entry), so don't assert. */
56822 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56823
56824 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
56825 DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
56826 duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56828 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56830 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56831
56832 /* [ ... | (crud) ] */
56833
56834 /* XXX: space in valstack? see discussion in duk_handle_call_xxx(). */
56835 duk_push_tval(ctx, &thr->heap->lj.value1);
56836
56837 /* [ ... | (crud) errobj ] */
56838
56839 DUK_ASSERT(duk_get_top(ctx) >= 1); /* at least errobj must be on stack */
56840
56841 /* check that the valstack has space for the final amount and any
56842 * intermediate space needed; this is unoptimal but should be safe
56843 */
56844 duk_require_stack_top(ctx, idx_retbase + num_stack_rets); /* final configuration */
56845 duk_require_stack(ctx, num_stack_rets);
56846
56847 duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1); /* 1 = num actual 'return values' */
56848
56849 /* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
56850
56851 /* These are just convenience "wiping" of state. Side effects should
56852 * not be an issue here: thr->heap and thr->heap->lj have a stable
56853 * pointer. Finalizer runs etc capture even out-of-memory errors so
56854 * nothing should throw here.
56855 */
56857 thr->heap->lj.iserror = 0;
56858 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
56859 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
56860}
56861
56863 duk_idx_t idx_retbase,
56864 duk_idx_t num_stack_rets,
56865 duk_int_t entry_call_recursion_depth,
56866 duk_hthread *entry_curr_thread,
56867 duk_uint_fast8_t entry_thread_state,
56868 duk_instr_t **entry_ptr_curr_pc) {
56869 duk_context *ctx;
56870
56871 DUK_ASSERT(thr != NULL);
56872 ctx = (duk_context *) thr;
56874 DUK_UNREF(ctx);
56875 DUK_UNREF(idx_retbase);
56876 DUK_UNREF(num_stack_rets);
56877
56878 /* Restore entry thread executor curr_pc stack frame pointer. */
56879 thr->ptr_curr_pc = entry_ptr_curr_pc;
56880
56881 /* XXX: because we unwind stacks above, thr->heap->curr_thread is at
56882 * risk of pointing to an already freed thread. This was indeed the
56883 * case in test-bug-multithread-valgrind.c, until duk_handle_call()
56884 * was fixed to restore thr->heap->curr_thread before rethrowing an
56885 * uncaught error.
56886 */
56887 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
56888 thr->state = (duk_uint8_t) entry_thread_state;
56889
56890 DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
56891 (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
56892 (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
56893
56894 thr->heap->call_recursion_depth = entry_call_recursion_depth;
56895
56896 /* stack discipline consistency check */
56897 DUK_ASSERT(duk_get_top(ctx) == idx_retbase + num_stack_rets);
56898
56899 /* A debugger forced interrupt check is not needed here, as
56900 * problematic safe calls are not caused by side effects.
56901 */
56902
56903#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
56904 duk__interrupt_fixup(thr, entry_curr_thread);
56905#endif
56906}
56907
56908/*
56909 * Helper for handling an Ecmascript-to-Ecmascript call or an Ecmascript
56910 * function (initial) Duktape.Thread.resume().
56911 *
56912 * Compared to normal calls handled by duk_handle_call(), there are a
56913 * bunch of differences:
56914 *
56915 * - the call is never protected
56916 * - there is no C recursion depth increase (hence an "ignore recursion
56917 * limit" flag is not applicable)
56918 * - instead of making the call, this helper just performs the thread
56919 * setup and returns; the bytecode executor then restarts execution
56920 * internally
56921 * - ecmascript functions are never 'vararg' functions (they access
56922 * varargs through the 'arguments' object)
56923 *
56924 * The callstack of the target contains an earlier Ecmascript call in case
56925 * of an Ecmascript-to-Ecmascript call (whose idx_retval is updated), or
56926 * is empty in case of an initial Duktape.Thread.resume().
56927 *
56928 * The first thing to do here is to figure out whether an ecma-to-ecma
56929 * call is actually possible. It's not always the case if the target is
56930 * a bound function; the final function may be native. In that case,
56931 * return an error so caller can fall back to a normal call path.
56932 */
56933
56935 duk_idx_t num_stack_args,
56936 duk_small_uint_t call_flags) {
56937 duk_context *ctx = (duk_context *) thr;
56938 duk_size_t entry_valstack_bottom_index;
56939 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
56940 duk_idx_t idx_args; /* valstack index of start of args (arg1) (relative to entry valstack_bottom) */
56941 duk_idx_t nargs; /* # argument registers target function wants (< 0 => never for ecma calls) */
56942 duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => never for ecma calls) */
56943 duk_hobject *func; /* 'func' on stack (borrowed reference) */
56944 duk_tval *tv_func; /* duk_tval ptr for 'func' on stack (borrowed reference) */
56945 duk_activation *act;
56946 duk_hobject *env;
56947 duk_bool_t use_tailcall;
56948 duk_instr_t **entry_ptr_curr_pc;
56949
56950 DUK_ASSERT(thr != NULL);
56951 DUK_ASSERT(ctx != NULL);
56952 DUK_ASSERT(!((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 && (call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0));
56953
56954 /* XXX: assume these? */
56955 DUK_ASSERT(thr->valstack != NULL);
56956 DUK_ASSERT(thr->callstack != NULL);
56957 DUK_ASSERT(thr->catchstack != NULL);
56958
56959 /* no need to handle thread state book-keeping here */
56960 DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ||
56962 thr->heap->curr_thread == thr));
56963
56964 /* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
56965 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
56966 * activation when side effects occur. If we end up not making the
56967 * call we must restore the value.
56968 */
56969 entry_ptr_curr_pc = thr->ptr_curr_pc;
56971
56972 /* if a tail call:
56973 * - an Ecmascript activation must be on top of the callstack
56974 * - there cannot be any active catchstack entries
56975 */
56976#if defined(DUK_USE_ASSERTIONS)
56977 if (call_flags & DUK_CALL_FLAG_IS_TAILCALL) {
56978 duk_size_t our_callstack_index;
56979 duk_size_t i;
56980
56981 DUK_ASSERT(thr->callstack_top >= 1);
56982 our_callstack_index = thr->callstack_top - 1;
56983 DUK_ASSERT_DISABLE(our_callstack_index >= 0);
56984 DUK_ASSERT(our_callstack_index < thr->callstack_size);
56985 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index) != NULL);
56987
56988 /* No entry in the catchstack which would actually catch a
56989 * throw can refer to the callstack entry being reused.
56990 * There *can* be catchstack entries referring to the current
56991 * callstack entry as long as they don't catch (e.g. label sites).
56992 */
56993
56994 for (i = 0; i < thr->catchstack_top; i++) {
56995 DUK_ASSERT(thr->catchstack[i].callstack_index < our_callstack_index || /* refer to callstack entries below current */
56996 DUK_CAT_GET_TYPE(thr->catchstack + i) == DUK_CAT_TYPE_LABEL); /* or a non-catching entry */
56997 }
56998 }
56999#endif /* DUK_USE_ASSERTIONS */
57000
57001 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
57002 /* XXX: rework */
57003 idx_func = duk_normalize_index(thr, -num_stack_args - 2);
57004 idx_args = idx_func + 2;
57005
57006 DUK_DD(DUK_DDPRINT("handle_ecma_call_setup: thr=%p, "
57007 "num_stack_args=%ld, call_flags=0x%08lx (resume=%ld, tailcall=%ld), "
57008 "idx_func=%ld, idx_args=%ld, entry_valstack_bottom_index=%ld",
57009 (void *) thr,
57010 (long) num_stack_args,
57011 (unsigned long) call_flags,
57012 (long) ((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ? 1 : 0),
57013 (long) ((call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0 ? 1 : 0),
57014 (long) idx_func,
57015 (long) idx_args,
57016 (long) entry_valstack_bottom_index));
57017
57018 if (DUK_UNLIKELY(idx_func < 0 || idx_args < 0)) {
57019 /* XXX: assert? compiler is responsible for this never happening */
57021 }
57022
57023 /*
57024 * Check the function type, handle bound function chains, and prepare
57025 * parameters for the rest of the call handling. Also figure out the
57026 * effective 'this' binding, which replaces the current value at
57027 * idx_func + 1.
57028 *
57029 * If the target function is a 'bound' one, follow the chain of 'bound'
57030 * functions until a non-bound function is found. During this process,
57031 * bound arguments are 'prepended' to existing ones, and the "this"
57032 * binding is overridden. See E5 Section 15.3.4.5.1.
57033 *
57034 * If the final target function cannot be handled by an ecma-to-ecma
57035 * call, return to the caller with a return value indicating this case.
57036 * The bound chain is resolved and the caller can resume with a plain
57037 * function call.
57038 */
57039
57040 func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
57041 if (func == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
57042 DUK_DDD(DUK_DDDPRINT("final target is a lightfunc/nativefunc, cannot do ecma-to-ecma call"));
57043 thr->ptr_curr_pc = entry_ptr_curr_pc;
57044 return 0;
57045 }
57046 /* XXX: tv_func is not actually needed */
57047
57048 DUK_ASSERT(func != NULL);
57051
57052 duk__coerce_effective_this_binding(thr, func, idx_func + 1);
57053 DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
57054 duk_get_tval(ctx, idx_func + 1)));
57055
57056 nargs = ((duk_hcompiledfunction *) func)->nargs;
57057 nregs = ((duk_hcompiledfunction *) func)->nregs;
57058 DUK_ASSERT(nregs >= nargs);
57059
57060 /* [ ... func this arg1 ... argN ] */
57061
57062 /*
57063 * Preliminary activation record and valstack manipulation.
57064 * The concrete actions depend on whether the we're dealing
57065 * with a tail call (reuse an existing activation), a resume,
57066 * or a normal call.
57067 *
57068 * The basic actions, in varying order, are:
57069 *
57070 * - Check stack size for call handling
57071 * - Grow call stack if necessary (non-tail-calls)
57072 * - Update current activation (idx_retval) if necessary
57073 * (non-tail, non-resume calls)
57074 * - Move start of args (idx_args) to valstack bottom
57075 * (tail calls)
57076 *
57077 * Don't touch valstack_bottom or valstack_top yet so that Duktape API
57078 * calls work normally.
57079 */
57080
57081 /* XXX: some overlapping code; cleanup */
57082 use_tailcall = call_flags & DUK_CALL_FLAG_IS_TAILCALL;
57083#if !defined(DUK_USE_TAILCALL)
57084 DUK_ASSERT(use_tailcall == 0); /* compiler ensures this */
57085#endif
57086 if (use_tailcall) {
57087 /* tailcall cannot be flagged to resume calls, and a
57088 * previous frame must exist
57089 */
57090 DUK_ASSERT(thr->callstack_top >= 1);
57091 DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) == 0);
57092
57093 act = thr->callstack + thr->callstack_top - 1;
57094 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
57095 /* See: test-bug-tailcall-preventyield-assert.c. */
57096 DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENTYIELD"));
57097 use_tailcall = 0;
57098 } else if (DUK_HOBJECT_HAS_NOTAIL(func)) {
57099 DUK_D(DUK_DPRINT("tail call prevented by function having a notail flag"));
57100 use_tailcall = 0;
57101 }
57102 }
57103
57104 if (use_tailcall) {
57105 duk_tval *tv1, *tv2;
57106 duk_size_t cs_index;
57107 duk_int_t i_stk; /* must be signed for loop structure */
57108 duk_idx_t i_arg;
57109
57110 /*
57111 * Tailcall handling
57112 *
57113 * Although the callstack entry is reused, we need to explicitly unwind
57114 * the current activation (or simulate an unwind). In particular, the
57115 * current activation must be closed, otherwise something like
57116 * test-bug-reduce-judofyr.js results. Also catchstack needs be unwound
57117 * because there may be non-error-catching label entries in valid tail calls.
57118 */
57119
57120 DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
57121 (long) (thr->callstack_top - 1)));
57122
57123 /* 'act' already set above */
57124
57129
57130 /* Unwind catchstack entries referring to the callstack entry we're reusing */
57131 cs_index = thr->callstack_top - 1;
57132 DUK_ASSERT(thr->catchstack_top <= DUK_INT_MAX); /* catchstack limits */
57133 for (i_stk = (duk_int_t) (thr->catchstack_top - 1); i_stk >= 0; i_stk--) {
57134 duk_catcher *cat = thr->catchstack + i_stk;
57135 if (cat->callstack_index != cs_index) {
57136 /* 'i' is the first entry we'll keep */
57137 break;
57138 }
57139 }
57140 duk_hthread_catchstack_unwind(thr, i_stk + 1);
57141
57142 /* Unwind the topmost callstack entry before reusing it */
57143 DUK_ASSERT(thr->callstack_top > 0);
57145
57146 /* Then reuse the unwound activation; callstack was not shrunk so there is always space */
57147 thr->callstack_top++;
57149 act = thr->callstack + thr->callstack_top - 1;
57150
57151 /* Start filling in the activation */
57152 act->func = func; /* don't want an intermediate exposed state with func == NULL */
57153#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57154 act->prev_caller = NULL;
57155#endif
57156 DUK_ASSERT(func != NULL);
57158 /* don't want an intermediate exposed state with invalid pc */
57160#if defined(DUK_USE_DEBUGGER_SUPPORT)
57161 act->prev_line = 0;
57162#endif
57163 DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
57164#if defined(DUK_USE_REFERENCE_COUNTING)
57165 DUK_HOBJECT_INCREF(thr, func);
57166 act = thr->callstack + thr->callstack_top - 1; /* side effects (currently none though) */
57167#endif
57168
57169#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57170#if defined(DUK_USE_TAILCALL)
57171#error incorrect options: tail calls enabled with function caller property
57172#endif
57173 /* XXX: this doesn't actually work properly for tail calls, so
57174 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
57175 * is in use.
57176 */
57177 duk__update_func_caller_prop(thr, func);
57178 act = thr->callstack + thr->callstack_top - 1;
57179#endif
57180
57181 act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
57184
57185 DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func); /* already updated */
57186 DUK_ASSERT(act->var_env == NULL); /* already NULLed (by unwind) */
57187 DUK_ASSERT(act->lex_env == NULL); /* already NULLed (by unwind) */
57188 act->idx_bottom = entry_valstack_bottom_index; /* tail call -> reuse current "frame" */
57189 DUK_ASSERT(nregs >= 0);
57190#if 0 /* topmost activation idx_retval is considered garbage, no need to init */
57191 act->idx_retval = 0;
57192#endif
57193
57194 /*
57195 * Manipulate valstack so that args are on the current bottom and the
57196 * previous caller's 'this' binding (which is the value preceding the
57197 * current bottom) is replaced with the new 'this' binding:
57198 *
57199 * [ ... this_old | (crud) func this_new arg1 ... argN ]
57200 * --> [ ... this_new | arg1 ... argN ]
57201 *
57202 * For tail calling to work properly, the valstack bottom must not grow
57203 * here; otherwise crud would accumulate on the valstack.
57204 */
57205
57206 tv1 = thr->valstack_bottom - 1;
57207 tv2 = thr->valstack_bottom + idx_func + 1;
57208 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top); /* tv1 is -below- valstack_bottom */
57209 DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
57210 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
57211
57212 for (i_arg = 0; i_arg < idx_args; i_arg++) {
57213 /* XXX: block removal API primitive */
57214 /* Note: 'func' is popped from valstack here, but it is
57215 * already reachable from the activation.
57216 */
57217 duk_remove(ctx, 0);
57218 }
57219 idx_func = 0; DUK_UNREF(idx_func); /* really 'not applicable' anymore, should not be referenced after this */
57220 idx_args = 0;
57221
57222 /* [ ... this_new | arg1 ... argN ] */
57223 } else {
57224 DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
57225 (long) (thr->callstack_top)));
57226
57228
57229 if (call_flags & DUK_CALL_FLAG_IS_RESUME) {
57230 DUK_DDD(DUK_DDDPRINT("is resume -> no update to current activation (may not even exist)"));
57231 } else {
57232 DUK_DDD(DUK_DDDPRINT("update to current activation idx_retval"));
57234 DUK_ASSERT(thr->callstack_top >= 1);
57235 act = thr->callstack + thr->callstack_top - 1;
57238 act->idx_retval = entry_valstack_bottom_index + idx_func;
57239 }
57240
57242 act = thr->callstack + thr->callstack_top;
57243 thr->callstack_top++;
57245
57249
57250 act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
57252 0);
57253 act->func = func;
57254 act->var_env = NULL;
57255 act->lex_env = NULL;
57256#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57257 act->prev_caller = NULL;
57258#endif
57259 DUK_ASSERT(func != NULL);
57262#if defined(DUK_USE_DEBUGGER_SUPPORT)
57263 act->prev_line = 0;
57264#endif
57265 act->idx_bottom = entry_valstack_bottom_index + idx_args;
57266 DUK_ASSERT(nregs >= 0);
57267#if 0 /* topmost activation idx_retval is considered garbage, no need to init */
57268 act->idx_retval = 0;
57269#endif
57270 DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
57271
57272 DUK_HOBJECT_INCREF(thr, func); /* act->func */
57273
57274#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57275 duk__update_func_caller_prop(thr, func);
57276 act = thr->callstack + thr->callstack_top - 1;
57277#endif
57278 }
57279
57280 /* [ ... func this arg1 ... argN ] (not tail call)
57281 * [ this | arg1 ... argN ] (tail call)
57282 *
57283 * idx_args updated to match
57284 */
57285
57286 /*
57287 * Environment record creation and 'arguments' object creation.
57288 * Named function expression name binding is handled by the
57289 * compiler; the compiled function's parent env will contain
57290 * the (immutable) binding already.
57291 *
57292 * Delayed creation (on demand) is handled in duk_js_var.c.
57293 */
57294
57295 /* XXX: unify handling with native call. */
57296
57297 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func)); /* bound function chain has already been resolved */
57298
57299 if (!DUK_HOBJECT_HAS_NEWENV(func)) {
57300 /* use existing env (e.g. for non-strict eval); cannot have
57301 * an own 'arguments' object (but can refer to the existing one)
57302 */
57303
57304 duk__handle_oldenv_for_call(thr, func, act);
57305
57306 DUK_ASSERT(act->lex_env != NULL);
57307 DUK_ASSERT(act->var_env != NULL);
57308 goto env_done;
57309 }
57310
57312
57313 if (!DUK_HOBJECT_HAS_CREATEARGS(func)) {
57314 /* no need to create environment record now; leave as NULL */
57315 DUK_ASSERT(act->lex_env == NULL);
57316 DUK_ASSERT(act->var_env == NULL);
57317 goto env_done;
57318 }
57319
57320 /* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
57322 DUK_ASSERT(env != NULL);
57323
57324 /* [ ... arg1 ... argN envobj ] */
57325
57326 /* original input stack before nargs/nregs handling must be
57327 * intact for 'arguments' object
57328 */
57330 duk__handle_createargs_for_call(thr, func, env, num_stack_args);
57331
57332 /* [ ... arg1 ... argN envobj ] */
57333
57334 act = thr->callstack + thr->callstack_top - 1;
57335 act->lex_env = env;
57336 act->var_env = env;
57337 DUK_HOBJECT_INCREF(thr, act->lex_env);
57338 DUK_HOBJECT_INCREF(thr, act->var_env);
57339 duk_pop(ctx);
57340
57341 env_done:
57342 /* [ ... arg1 ... argN ] */
57343
57344 /*
57345 * Setup value stack: clamp to 'nargs', fill up to 'nregs'
57346 */
57347
57349 num_stack_args,
57350 idx_args,
57351 nregs,
57352 nargs,
57353 func);
57354
57355 /*
57356 * Shift to new valstack_bottom.
57357 */
57358
57359 thr->valstack_bottom = thr->valstack_bottom + idx_args;
57360 /* keep current valstack_top */
57361 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
57363 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
57364
57365 /*
57366 * Return to bytecode executor, which will resume execution from
57367 * the topmost activation.
57368 */
57369
57370 return 1;
57371}
57372/*
57373 * Ecmascript compiler.
57374 *
57375 * Parses an input string and generates a function template result.
57376 * Compilation may happen in multiple contexts (global code, eval
57377 * code, function code).
57378 *
57379 * The parser uses a traditional top-down recursive parsing for the
57380 * statement level, and an operator precedence based top-down approach
57381 * for the expression level. The attempt is to minimize the C stack
57382 * depth. Bytecode is generated directly without an intermediate
57383 * representation (tree), at the cost of needing two passes over each
57384 * function.
57385 *
57386 * The top-down recursive parser functions are named "duk__parse_XXX".
57387 *
57388 * Recursion limits are in key functions to prevent arbitrary C recursion:
57389 * function body parsing, statement parsing, and expression parsing.
57391 * See doc/compiler.rst for discussion on the design.
57392 *
57393 * A few typing notes:
57394 *
57395 * - duk_regconst_t: unsigned, no marker value for "none"
57396 * - duk_reg_t: signed, < 0 = none
57397 * - PC values: duk_int_t, negative values used as markers
57400/* include removed: duk_internal.h */
57401
57402/* if highest bit of a register number is set, it refers to a constant instead */
57403#define DUK__CONST_MARKER DUK_JS_CONST_MARKER
57404
57405/* for array and object literals */
57406#define DUK__MAX_ARRAY_INIT_VALUES 20
57407#define DUK__MAX_OBJECT_INIT_PAIRS 10
57408
57409/* XXX: hack, remove when const lookup is not O(n) */
57410#define DUK__GETCONST_MAX_CONSTS_CHECK 256
57411
57412/* These limits are based on bytecode limits. Max temps is limited
57413 * by duk_hcompiledfunction nargs/nregs fields being 16 bits.
57414 */
57415#define DUK__MAX_CONSTS DUK_BC_BC_MAX
57416#define DUK__MAX_FUNCS DUK_BC_BC_MAX
57417#define DUK__MAX_TEMPS 0xffffL
57419/* Initial bytecode size allocation. */
57420#define DUK__BC_INITIAL_INSTS 256
57422#define DUK__RECURSION_INCREASE(comp_ctx,thr) do { \
57423 DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
57424 duk__recursion_increase((comp_ctx)); \
57425 } while (0)
57426
57427#define DUK__RECURSION_DECREASE(comp_ctx,thr) do { \
57428 DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
57429 duk__recursion_decrease((comp_ctx)); \
57430 } while (0)
57431
57432/* Value stack slot limits: these are quite approximate right now, and
57433 * because they overlap in control flow, some could be eliminated.
57434 */
57435#define DUK__COMPILE_ENTRY_SLOTS 8
57436#define DUK__FUNCTION_INIT_REQUIRE_SLOTS 16
57437#define DUK__FUNCTION_BODY_REQUIRE_SLOTS 16
57438#define DUK__PARSE_STATEMENTS_SLOTS 16
57439#define DUK__PARSE_EXPR_SLOTS 16
57440
57441/* Temporary structure used to pass a stack allocated region through
57442 * duk_safe_call().
57443 */
57444typedef struct {
57445 duk_small_uint_t flags;
57446 duk_compiler_ctx comp_ctx_alloc;
57447 duk_lexer_point lex_pt_alloc;
57449
57450/*
57451 * Prototypes
57452 */
57453
57454/* lexing */
57458
57459/* function helpers */
57465
57466/* code emission */
57470#if 0 /* unused */
57471DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
57472#endif
57475#if 0 /* unused */
57476DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
57477#endif
57484DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
57485DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
57486DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
57489DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
57491DUK_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);
57495
57496/* ivalue/ispec helpers */
57506 duk_ispec *x,
57507 duk_reg_t forced_reg,
57508 duk_small_uint_t flags);
57515 duk_ivalue *x,
57516 duk_reg_t forced_reg,
57517 duk_small_uint_t flags);
57519#if 0 /* unused */
57520DUK_LOCAL_DECL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57521#endif
57525
57526/* identifier handling */
57528DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
57529
57530/* label handling */
57531DUK_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);
57533DUK_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);
57535
57536/* top-down expression parser */
57541
57542/* exprtop is the top level variant which resets nud/led counts */
57545
57546/* convenience helpers */
57547#if 0 /* unused */
57548DUK_LOCAL_DECL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57549#endif
57550#if 0 /* unused */
57551DUK_LOCAL_DECL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57552#endif
57555#if 0 /* unused */
57556DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57557#endif
57561#if 0 /* unused */
57562DUK_LOCAL_DECL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57563#endif
57566#if 0 /* unused */
57567DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57568#endif
57569
57570/* expression parsing helpers */
57575
57576/* statement parsing */
57577DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
57579DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57582DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57583DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57589DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
57591DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
57592
57593DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token);
57599 * Parser control values for tokens. The token table is ordered by the
57600 * DUK_TOK_XXX defines.
57602 * The binding powers are for lbp() use (i.e. for use in led() context).
57603 * Binding powers are positive for typing convenience, and bits at the
57604 * top should be reserved for flags. Binding power step must be higher
57605 * than 1 so that binding power "lbp - 1" can be used for right associative
57606 * operators. Currently a step of 2 is used (which frees one more bit for
57607 * flags).
57610/* XXX: actually single step levels would work just fine, clean up */
57612/* binding power "levels" (see doc/compiler.rst) */
57613#define DUK__BP_INVALID 0 /* always terminates led() */
57614#define DUK__BP_EOF 2
57615#define DUK__BP_CLOSING 4 /* token closes expression, e.g. ')', ']' */
57616#define DUK__BP_FOR_EXPR DUK__BP_CLOSING /* bp to use when parsing a top level Expression */
57617#define DUK__BP_COMMA 6
57618#define DUK__BP_ASSIGNMENT 8
57619#define DUK__BP_CONDITIONAL 10
57620#define DUK__BP_LOR 12
57621#define DUK__BP_LAND 14
57622#define DUK__BP_BOR 16
57623#define DUK__BP_BXOR 18
57624#define DUK__BP_BAND 20
57625#define DUK__BP_EQUALITY 22
57626#define DUK__BP_RELATIONAL 24
57627#define DUK__BP_SHIFT 26
57628#define DUK__BP_ADDITIVE 28
57629#define DUK__BP_MULTIPLICATIVE 30
57630#define DUK__BP_POSTFIX 32
57631#define DUK__BP_CALL 34
57632#define DUK__BP_MEMBER 36
57633
57634#define DUK__TOKEN_LBP_BP_MASK 0x1f
57635#define DUK__TOKEN_LBP_FLAG_NO_REGEXP (1 << 5) /* regexp literal must not follow this token */
57636#define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6) /* terminates expression; e.g. post-increment/-decrement */
57637#define DUK__TOKEN_LBP_FLAG_UNUSED (1 << 7) /* spare */
57638
57639#define DUK__TOKEN_LBP_GET_BP(x) ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
57640
57641#define DUK__MK_LBP(bp) ((bp) >> 1) /* bp is assumed to be even */
57642#define DUK__MK_LBP_FLAGS(bp,flags) (((bp) >> 1) | (flags))
57643
57644DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
57645 DUK__MK_LBP(DUK__BP_EOF), /* DUK_TOK_EOF */
57647 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BREAK */
57648 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CASE */
57649 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CATCH */
57650 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONTINUE */
57651 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEBUGGER */
57652 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEFAULT */
57653 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DELETE */
57654 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DO */
57655 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ELSE */
57656 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FINALLY */
57657 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FOR */
57658 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FUNCTION */
57659 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IF */
57660 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_IN */
57661 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_INSTANCEOF */
57662 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_NEW */
57663 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_RETURN */
57664 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SWITCH */
57666 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_THROW */
57667 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TRY */
57668 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TYPEOF */
57669 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VAR */
57670 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
57671 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VOID */
57672 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WHILE */
57673 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WITH */
57674 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CLASS */
57675 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ENUM */
57676 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXPORT */
57677 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXTENDS */
57678 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPORT */
57679 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SUPER */
57683 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_GET */
57684 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SET */
57685 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPLEMENTS */
57686 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_INTERFACE */
57687 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LET */
57688 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PACKAGE */
57689 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PRIVATE */
57690 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PROTECTED */
57691 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PUBLIC */
57692 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_STATIC */
57693 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_YIELD */
57694 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LCURLY */
57696 DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_LBRACKET */
57698 DUK__MK_LBP(DUK__BP_CALL), /* DUK_TOK_LPAREN */
57700 DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_PERIOD */
57701 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SEMICOLON */
57702 DUK__MK_LBP(DUK__BP_COMMA), /* DUK_TOK_COMMA */
57703 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LT */
57704 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GT */
57705 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LE */
57706 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GE */
57707 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_EQ */
57708 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_NEQ */
57709 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SEQ */
57710 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SNEQ */
57711 DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_ADD */
57712 DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_SUB */
57713 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MUL */
57714 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_DIV */
57715 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MOD */
57716 DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_INCREMENT */
57717 DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_DECREMENT */
57718 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ALSHIFT */
57719 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ARSHIFT */
57720 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_RSHIFT */
57721 DUK__MK_LBP(DUK__BP_BAND), /* DUK_TOK_BAND */
57722 DUK__MK_LBP(DUK__BP_BOR), /* DUK_TOK_BOR */
57723 DUK__MK_LBP(DUK__BP_BXOR), /* DUK_TOK_BXOR */
57724 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LNOT */
57725 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BNOT */
57726 DUK__MK_LBP(DUK__BP_LAND), /* DUK_TOK_LAND */
57727 DUK__MK_LBP(DUK__BP_LOR), /* DUK_TOK_LOR */
57728 DUK__MK_LBP(DUK__BP_CONDITIONAL), /* DUK_TOK_QUESTION */
57729 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_COLON */
57730 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EQUALSIGN */
57731 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ADD_EQ */
57732 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_SUB_EQ */
57733 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MUL_EQ */
57734 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_DIV_EQ */
57735 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MOD_EQ */
57736 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ALSHIFT_EQ */
57737 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ARSHIFT_EQ */
57738 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_RSHIFT_EQ */
57739 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BAND_EQ */
57740 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BOR_EQ */
57741 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BXOR_EQ */
57748 * Misc helpers
57750
57752 DUK_ASSERT(comp_ctx != NULL);
57753 DUK_ASSERT(comp_ctx->recursion_depth >= 0);
57754 if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
57756 }
57757 comp_ctx->recursion_depth++;
57758}
57759
57761 DUK_ASSERT(comp_ctx != NULL);
57762 DUK_ASSERT(comp_ctx->recursion_depth > 0);
57763 comp_ctx->recursion_depth--;
57764}
57765
57767 DUK_UNREF(comp_ctx);
57768 DUK_ASSERT(h != NULL);
57770}
57771
57773 DUK_ASSERT(h != NULL);
57774 return (comp_ctx->curr_func.is_strict &&
57776}
57777
57778/*
57779 * Parser duk__advance() token eating functions
57780 */
57781
57782/* XXX: valstack handling is awkward. Add a valstack helper which
57783 * avoids dup():ing; valstack_copy(src, dst)?
57784 */
57785
57787 duk_hthread *thr = comp_ctx->thr;
57788 duk_context *ctx = (duk_context *) thr;
57789 duk_bool_t regexp;
57790
57791 DUK_ASSERT(comp_ctx->curr_token.t >= 0 && comp_ctx->curr_token.t <= DUK_TOK_MAXVAL); /* MAXVAL is inclusive */
57792
57793 /*
57794 * Use current token to decide whether a RegExp can follow.
57795 *
57796 * We can use either 't' or 't_nores'; the latter would not
57797 * recognize keywords. Some keywords can be followed by a
57798 * RegExp (e.g. "return"), so using 't' is better. This is
57799 * not trivial, see doc/compiler.rst.
57800 */
57801
57802 regexp = 1;
57804 regexp = 0;
57805 }
57806 if (comp_ctx->curr_func.reject_regexp_in_adv) {
57807 comp_ctx->curr_func.reject_regexp_in_adv = 0;
57808 regexp = 0;
57809 }
57810
57811 if (expect >= 0 && comp_ctx->curr_token.t != expect) {
57812 DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
57813 (long) expect, (long) comp_ctx->curr_token.t));
57815 }
57816
57817 /* make current token the previous; need to fiddle with valstack "backing store" */
57818 DUK_MEMCPY(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
57819 duk_copy(ctx, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
57820 duk_copy(ctx, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
57821
57822 /* parse new token */
57824 &comp_ctx->curr_token,
57825 comp_ctx->curr_func.is_strict,
57826 regexp);
57827
57828 DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
57829 "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
57830 (long) comp_ctx->curr_token.t,
57831 (long) comp_ctx->curr_token.t_nores,
57832 (long) comp_ctx->curr_token.start_line,
57833 (long) comp_ctx->curr_token.lineterm,
57834 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok11_idx),
57835 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok12_idx),
57836 (long) comp_ctx->prev_token.t,
57837 (long) comp_ctx->prev_token.t_nores,
57838 (long) comp_ctx->prev_token.start_line,
57839 (long) comp_ctx->prev_token.lineterm,
57840 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok21_idx),
57841 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok22_idx)));
57843
57844/* advance, expecting current token to be a specific token; parse next token in regexp context */
57846 duk__advance_helper(comp_ctx, expect);
57847}
57848
57849/* advance, whatever the current token is; parse next token in regexp context */
57850DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
57851 duk__advance_helper(comp_ctx, -1);
57852}
57853
57854/*
57855 * Helpers for duk_compiler_func.
57856 */
57857
57858/* init function state: inits valstack allocations */
57860 duk_compiler_func *func = &comp_ctx->curr_func;
57861 duk_hthread *thr = comp_ctx->thr;
57862 duk_context *ctx = (duk_context *) thr;
57863 duk_idx_t entry_top;
57864
57865 entry_top = duk_get_top(ctx);
57866
57867 DUK_MEMZERO(func, sizeof(*func)); /* intentional overlap with earlier memzero */
57868#ifdef DUK_USE_EXPLICIT_NULL_INIT
57869 func->h_name = NULL;
57870 func->h_consts = NULL;
57871 func->h_funcs = NULL;
57872 func->h_decls = NULL;
57873 func->h_labelnames = NULL;
57874 func->h_labelinfos = NULL;
57875 func->h_argnames = NULL;
57876 func->h_varmap = NULL;
57877#endif
57878
57880
57882 /* code_idx = entry_top + 0 */
57883
57884 duk_push_array(ctx);
57885 func->consts_idx = entry_top + 1;
57886 func->h_consts = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 1);
57887 DUK_ASSERT(func->h_consts != NULL);
57888
57889 duk_push_array(ctx);
57890 func->funcs_idx = entry_top + 2;
57891 func->h_funcs = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 2);
57892 DUK_ASSERT(func->h_funcs != NULL);
57893 DUK_ASSERT(func->fnum_next == 0);
57894
57895 duk_push_array(ctx);
57896 func->decls_idx = entry_top + 3;
57897 func->h_decls = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 3);
57898 DUK_ASSERT(func->h_decls != NULL);
57899
57900 duk_push_array(ctx);
57901 func->labelnames_idx = entry_top + 4;
57902 func->h_labelnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 4);
57903 DUK_ASSERT(func->h_labelnames != NULL);
57904
57906 func->labelinfos_idx = entry_top + 5;
57907 func->h_labelinfos = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 5);
57908 DUK_ASSERT(func->h_labelinfos != NULL);
57910
57911 duk_push_array(ctx);
57912 func->argnames_idx = entry_top + 6;
57913 func->h_argnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 6);
57914 DUK_ASSERT(func->h_argnames != NULL);
57915
57917 func->varmap_idx = entry_top + 7;
57918 func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 7);
57919 DUK_ASSERT(func->h_varmap != NULL);
57920}
57921
57922/* reset function state (prepare for pass 2) */
57924 duk_compiler_func *func = &comp_ctx->curr_func;
57925 duk_hthread *thr = comp_ctx->thr;
57926 duk_context *ctx = (duk_context *) thr;
57927
57928 /* reset bytecode buffer but keep current size; pass 2 will
57929 * require same amount or more.
57930 */
57931 DUK_BW_RESET_SIZE(thr, &func->bw_code);
57932
57934 /* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
57935 func->fnum_next = 0;
57936 /* duk_hobject_set_length_zero(thr, func->h_funcs); */
57938 duk_hbuffer_reset(thr, func->h_labelinfos);
57939 /* keep func->h_argnames; it is fixed for all passes */
57940
57941 /* truncated in case pass 3 needed */
57943 duk_replace(ctx, func->varmap_idx);
57944 func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, func->varmap_idx);
57945 DUK_ASSERT(func->h_varmap != NULL);
57946}
57947
57948/* cleanup varmap from any null entries, compact it, etc; returns number
57949 * of final entries after cleanup.
57950 */
57952 duk_hthread *thr = comp_ctx->thr;
57953 duk_context *ctx = (duk_context *) thr;
57954 duk_hobject *h_varmap;
57955 duk_hstring *h_key;
57956 duk_tval *tv;
57957 duk_uint32_t i, e_next;
57958 duk_int_t ret;
57959
57960 /* [ ... varmap ] */
57961
57962 h_varmap = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
57963 DUK_ASSERT(h_varmap != NULL);
57964
57965 ret = 0;
57966 e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
57967 for (i = 0; i < e_next; i++) {
57968 h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
57969 if (!h_key) {
57970 continue;
57971 }
57972
57973 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
57974
57975 /* The entries can either be register numbers or 'null' values.
57976 * Thus, no need to DECREF them and get side effects. DECREF'ing
57977 * the keys (strings) can cause memory to be freed but no side
57978 * effects as strings don't have finalizers. This is why we can
57979 * rely on the object properties not changing from underneath us.
57980 */
57981
57982 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
57983 if (!DUK_TVAL_IS_NUMBER(tv)) {
57985 DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
57986 DUK_HSTRING_DECREF(thr, h_key);
57987 /* when key is NULL, value is garbage so no need to set */
57988 } else {
57989 ret++;
57990 }
57991 }
57992
57993 duk_compact(ctx, -1);
57994
57995 return ret;
57996}
57997
57998/* convert duk_compiler_func into a function template, leaving the result
57999 * on top of stack.
58000 */
58001/* XXX: awkward and bloated asm -- use faster internal accesses */
58002DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind) {
58003 duk_compiler_func *func = &comp_ctx->curr_func;
58004 duk_hthread *thr = comp_ctx->thr;
58005 duk_context *ctx = (duk_context *) thr;
58006 duk_hcompiledfunction *h_res;
58007 duk_hbuffer_fixed *h_data;
58008 duk_size_t consts_count;
58009 duk_size_t funcs_count;
58010 duk_size_t code_count;
58011 duk_size_t code_size;
58012 duk_size_t data_size;
58013 duk_size_t i;
58014 duk_tval *p_const;
58015 duk_hobject **p_func;
58016 duk_instr_t *p_instr;
58017 duk_compiler_instr *q_instr;
58018 duk_tval *tv;
58019
58020 DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
58021
58022 /*
58023 * Push result object and init its flags
58024 */
58025
58026 /* Valstack should suffice here, required on function valstack init */
58027
58028 (void) duk_push_compiledfunction(ctx);
58029 h_res = (duk_hcompiledfunction *) DUK_GET_HOBJECT_NEGIDX(ctx, -1); /* XXX: specific getter */
58030 DUK_ASSERT(h_res != NULL);
58031
58032 if (func->is_function) {
58033 DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
58035
58036 if (!func->is_arguments_shadowed) {
58037 /* arguments object would be accessible; note that shadowing
58038 * bindings are arguments or function declarations, neither
58039 * of which are deletable, so this is safe.
58040 */
58041
58042 if (func->id_access_arguments || func->may_direct_eval) {
58043 DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
58044 "indirectly -> set CREATEARGS"));
58046 }
58047 }
58048 } else if (func->is_eval && func->is_strict) {
58049 DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
58051 } else {
58052 /* non-strict eval: env is caller's env or global env (direct vs. indirect call)
58053 * global code: env is is global env
58054 */
58055 DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
58057 }
58058
58059 if (func->is_function && !func->is_decl && func->h_name != NULL && !force_no_namebind) {
58060 /* Object literal set/get functions have a name (property
58061 * name) but must not have a lexical name binding, see
58062 * test-bug-getset-func-name.js.
58063 */
58064 DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
58066 }
58067
58068 if (func->is_strict) {
58069 DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
58071 }
58072
58073 if (func->is_notail) {
58074 DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
58076 }
58077
58078 /*
58079 * Build function fixed size 'data' buffer, which contains bytecode,
58080 * constants, and inner function references.
58081 *
58082 * During the building phase 'data' is reachable but incomplete.
58083 * Only incref's occur during building (no refzero or GC happens),
58084 * so the building process is atomic.
58085 */
58086
58087 consts_count = duk_hobject_get_length(thr, func->h_consts);
58088 funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
58089 code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
58090 code_size = code_count * sizeof(duk_instr_t);
58091
58092 data_size = consts_count * sizeof(duk_tval) +
58093 funcs_count * sizeof(duk_hobject *) +
58094 code_size;
58095
58096 DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
58097 "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
58098 (long) consts_count, (long) funcs_count, (long) code_size,
58099 (long) consts_count, (long) sizeof(duk_tval),
58100 (long) funcs_count, (long) sizeof(duk_hobject *),
58101 (long) code_size, (long) data_size));
58102
58103 duk_push_fixed_buffer(ctx, data_size);
58104 h_data = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
58105 DUK_ASSERT(h_data != NULL);
58106
58107 DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
58108 DUK_HEAPHDR_INCREF(thr, h_data);
58109
58110 p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
58111 for (i = 0; i < consts_count; i++) {
58112 DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* const limits */
58114 DUK_ASSERT(tv != NULL);
58115 DUK_TVAL_SET_TVAL(p_const, tv);
58116 p_const++;
58117 DUK_TVAL_INCREF(thr, tv); /* may be a string constant */
58118
58119 DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
58120 }
58121
58122 p_func = (duk_hobject **) p_const;
58123 DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_res, p_func);
58124 for (i = 0; i < funcs_count; i++) {
58125 duk_hobject *h;
58126 DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX); /* func limits */
58128 DUK_ASSERT(tv != NULL);
58130 h = DUK_TVAL_GET_OBJECT(tv);
58131 DUK_ASSERT(h != NULL);
58133 *p_func++ = h;
58134 DUK_HOBJECT_INCREF(thr, h);
58135
58136 DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
58137 (void *) h, (duk_heaphdr *) h));
58138 }
58139
58140 p_instr = (duk_instr_t *) p_func;
58141 DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_res, p_instr);
58142
58143 /* copy bytecode instructions one at a time */
58144 q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
58145 for (i = 0; i < code_count; i++) {
58146 p_instr[i] = q_instr[i].ins;
58147 }
58148 /* Note: 'q_instr' is still used below */
58149
58150 DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
58151
58152 duk_pop(ctx); /* 'data' (and everything in it) is reachable through h_res now */
58153
58154 /*
58155 * Init object properties
58156 *
58157 * Properties should be added in decreasing order of access frequency.
58158 * (Not very critical for function templates.)
58159 */
58160
58161 DUK_DDD(DUK_DDDPRINT("init function properties"));
58162
58163 /* [ ... res ] */
58164
58165 /* _Varmap: omitted if function is guaranteed not to do slow path identifier
58166 * accesses or if it would turn out to be empty of actual register mappings
58167 * after a cleanup. When debugging is enabled, we always need the varmap to
58168 * be able to lookup variables at any point.
58169 */
58170#if defined(DUK_USE_DEBUGGER_SUPPORT)
58171 if (1) {
58172#else
58173 if (func->id_access_slow || /* directly uses slow accesses */
58174 func->may_direct_eval || /* may indirectly slow access through a direct eval */
58175 funcs_count > 0) { /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
58176#endif
58177 duk_int_t num_used;
58178 duk_dup(ctx, func->varmap_idx);
58179 num_used = duk__cleanup_varmap(comp_ctx);
58180 DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
58181 (duk_tval *) duk_get_tval(ctx, -1), (long) num_used));
58182
58183 if (num_used > 0) {
58185 } else {
58186 DUK_DDD(DUK_DDDPRINT("varmap is empty after cleanup -> no need to add"));
58187 duk_pop(ctx);
58188 }
58189 }
58190
58191 /* _Formals: omitted if function is guaranteed not to need a (non-strict) arguments object */
58192 if (1) {
58193 /* XXX: Add a proper condition. If formals list is omitted, recheck
58194 * handling for 'length' in duk_js_push_closure(); it currently relies
58195 * on _Formals being set. Removal may need to be conditional to debugging
58196 * being enabled/disabled too.
58197 */
58198 duk_dup(ctx, func->argnames_idx);
58200 }
58201
58202 /* name */
58203 if (func->h_name) {
58204 duk_push_hstring(ctx, func->h_name);
58206 }
58207
58208 /* _Source */
58209#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
58210 if (0) {
58211 /* XXX: Currently function source code is not stored, as it is not
58212 * required by the standard. Source code should not be stored by
58213 * default (user should enable it explicitly), and the source should
58214 * probably be compressed with a trivial text compressor; average
58215 * compression of 20-30% is quite easy to achieve even with a trivial
58216 * compressor (RLE + backwards lookup).
58217 *
58218 * Debugging needs source code to be useful: sometimes input code is
58219 * not found in files as it may be generated and then eval()'d, given
58220 * by dynamic C code, etc.
58221 *
58222 * Other issues:
58223 *
58224 * - Need tokenizer indices for start and end to substring
58225 * - Always normalize function declaration part?
58226 * - If we keep _Formals, only need to store body
58227 */
58228
58229 /*
58230 * For global or eval code this is straightforward. For functions
58231 * created with the Function constructor we only get the source for
58232 * the body and must manufacture the "function ..." part.
58233 *
58234 * For instance, for constructed functions (v8):
58235 *
58236 * > a = new Function("foo", "bar", "print(foo)");
58237 * [Function]
58238 * > a.toString()
58239 * 'function anonymous(foo,bar) {\nprint(foo)\n}'
58240 *
58241 * Similarly for e.g. getters (v8):
58242 *
58243 * > x = { get a(foo,bar) { print(foo); } }
58244 * { a: [Getter] }
58245 * > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
58246 * 'function a(foo,bar) { print(foo); }'
58247 */
58248
58249#if 0
58250 duk_push_string(ctx, "XXX");
58252#endif
58253 }
58254#endif /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
58255
58256 /* _Pc2line */
58257#if defined(DUK_USE_PC2LINE)
58258 if (1) {
58259 /*
58260 * Size-optimized pc->line mapping.
58261 */
58262
58264 duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count); /* -> pushes fixed buffer */
58266
58267 /* XXX: if assertions enabled, walk through all valid PCs
58268 * and check line mapping.
58269 */
58270 }
58271#endif /* DUK_USE_PC2LINE */
58272
58273 /* fileName */
58274 if (comp_ctx->h_filename) {
58275 /*
58276 * Source filename (or equivalent), for identifying thrown errors.
58277 */
58278
58279 duk_push_hstring(ctx, comp_ctx->h_filename);
58281 }
58282
58283 /*
58284 * Init remaining result fields
58285 *
58286 * 'nregs' controls how large a register frame is allocated.
58287 *
58288 * 'nargs' controls how many formal arguments are written to registers:
58289 * r0, ... r(nargs-1). The remaining registers are initialized to
58290 * undefined.
58291 */
58292
58293 DUK_ASSERT(func->temp_max >= 0);
58294 h_res->nregs = (duk_uint16_t) func->temp_max;
58295 h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
58296 DUK_ASSERT(h_res->nregs >= h_res->nargs); /* pass2 allocation handles this */
58297#if defined(DUK_USE_DEBUGGER_SUPPORT)
58298 h_res->start_line = (duk_uint32_t) func->min_line;
58299 h_res->end_line = (duk_uint32_t) func->max_line;
58300#endif
58301
58302 DUK_DD(DUK_DDPRINT("converted function: %!ixT",
58303 (duk_tval *) duk_get_tval(ctx, -1)));
58304
58305 /*
58306 * Compact the function template.
58307 */
58308
58309 duk_compact(ctx, -1);
58310
58311 /*
58312 * Debug dumping
58313 */
58314
58315#ifdef DUK_USE_DDDPRINT
58316 {
58318 duk_instr_t *p, *p_start, *p_end;
58319
58320 h = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
58323
58324 p = p_start;
58325 while (p < p_end) {
58326 DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld",
58327 (long) (p - p_start),
58328 (duk_instr_t) (*p),
58329 (unsigned long) (*p),
58330 (long) DUK_DEC_OP(*p),
58331 (long) DUK_DEC_OP(*p),
58332 (long) DUK_DEC_A(*p),
58333 (long) DUK_DEC_B(*p),
58334 (long) DUK_DEC_C(*p)));
58335 p++;
58336 }
58337 }
58338#endif
58339}
58340
58341/*
58342 * Code emission helpers
58343 *
58344 * Some emission helpers understand the range of target and source reg/const
58345 * values and automatically emit shuffling code if necessary. This is the
58346 * case when the slot in question (A, B, C) is used in the standard way and
58347 * for opcodes the emission helpers explicitly understand (like DUK_OP_CALL).
58348 *
58349 * The standard way is that:
58350 * - slot A is a target register
58351 * - slot B is a source register/constant
58352 * - slot C is a source register/constant
58353 *
58354 * If a slot is used in a non-standard way the caller must indicate this
58355 * somehow. If a slot is used as a target instead of a source (or vice
58356 * versa), this can be indicated with a flag to trigger proper shuffling
58357 * (e.g. DUK__EMIT_FLAG_B_IS_TARGET). If the value in the slot is not
58358 * register/const related at all, the caller must ensure that the raw value
58359 * fits into the corresponding slot so as to not trigger shuffling. The
58360 * caller must set a "no shuffle" flag to ensure compilation fails if
58361 * shuffling were to be triggered because of an internal error.
58363 * For slots B and C the raw slot size is 9 bits but one bit is reserved for
58364 * the reg/const indicator. To use the full 9-bit range for a raw value,
58365 * shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
58366 * Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
58367 *
58368 * There is call handling specific understanding in the A-B-C emitter to
58369 * convert call setup and call instructions into indirect ones if necessary.
58370 */
58372/* Code emission flags, passed in the 'opcode' field. Opcode + flags
58373 * fit into 16 bits for now, so use duk_small_uint.t.
58374 */
58375#define DUK__EMIT_FLAG_NO_SHUFFLE_A (1 << 8)
58376#define DUK__EMIT_FLAG_NO_SHUFFLE_B (1 << 9)
58377#define DUK__EMIT_FLAG_NO_SHUFFLE_C (1 << 10)
58378#define DUK__EMIT_FLAG_A_IS_SOURCE (1 << 11) /* slot A is a source (default: target) */
58379#define DUK__EMIT_FLAG_B_IS_TARGET (1 << 12) /* slot B is a target (default: source) */
58380#define DUK__EMIT_FLAG_C_IS_TARGET (1 << 13) /* slot C is a target (default: source) */
58381#define DUK__EMIT_FLAG_B_IS_TARGETSOURCE (1 << 14) /* slot B is both a target and a source (used by extraops like DUK_EXTRAOP_INSTOF */
58382#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT (1 << 15) /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
58383
58384/* XXX: clarify on when and where DUK__CONST_MARKER is allowed */
58385/* XXX: opcode specific assertions on when consts are allowed */
58387/* XXX: macro smaller than call? */
58389 duk_compiler_func *func;
58390 func = &comp_ctx->curr_func;
58391 return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
58392}
58393
58395 DUK_ASSERT(pc >= 0);
58396 DUK_ASSERT((duk_size_t) pc < (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)));
58397 return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
58398}
58399
58400/* emit instruction; could return PC but that's not needed in the majority
58401 * of cases.
58402 */
58403DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
58404#if defined(DUK_USE_PC2LINE)
58405 duk_int_t line;
58406#endif
58407 duk_compiler_instr *instr;
58408
58409 DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
58410 (unsigned long) ins,
58411 (long) comp_ctx->curr_token.start_line,
58412 (long) comp_ctx->prev_token.start_line,
58413 (long) duk__get_current_pc(comp_ctx),
58414 (duk_instr_t) ins));
58415
58416 instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
58417 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
58418
58419#if defined(DUK_USE_PC2LINE)
58420 /* The line number tracking is a bit inconsistent right now, which
58421 * affects debugger accuracy. Mostly call sites emit opcodes when
58422 * they have parsed a token (say a terminating semicolon) and called
58423 * duk__advance(). In this case the line number of the previous
58424 * token is the most accurate one (except in prologue where
58425 * prev_token.start_line is 0). This is probably not 100% correct
58426 * right now.
58427 */
58428 /* approximation, close enough */
58429 line = comp_ctx->prev_token.start_line;
58430 if (line == 0) {
58431 line = comp_ctx->curr_token.start_line;
58432 }
58433#endif
58434
58435 instr->ins = ins;
58436#if defined(DUK_USE_PC2LINE)
58437 instr->line = line;
58438#endif
58439#if defined(DUK_USE_DEBUGGER_SUPPORT)
58440 if (line < comp_ctx->curr_func.min_line) {
58441 comp_ctx->curr_func.min_line = line;
58442 }
58443 if (line > comp_ctx->curr_func.max_line) {
58444 comp_ctx->curr_func.max_line = line;
58445 }
58446#endif
58447
58448 /* Limit checks for bytecode byte size and line number. */
58450 goto fail_bc_limit;
58451 }
58452#if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
58453#if defined(DUK_USE_BUFLEN16)
58454 /* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
58456 goto fail_bc_limit;
58457 }
58458#else
58460 goto fail_bc_limit;
58461 }
58462#endif
58463#endif
58464
58465 return;
58466
58467 fail_bc_limit:
58469}
58470
58471/* Update function min/max line from current token. Needed to improve
58472 * function line range information for debugging, so that e.g. opening
58473 * curly brace is covered by line range even when no opcodes are emitted
58474 * for the line containing the brace.
58475 */
58477#if defined(DUK_USE_DEBUGGER_SUPPORT)
58478 duk_int_t line;
58479
58480 line = comp_ctx->curr_token.start_line;
58481 if (line == 0) {
58482 return;
58483 }
58484 if (line < comp_ctx->curr_func.min_line) {
58485 comp_ctx->curr_func.min_line = line;
58486 }
58487 if (line > comp_ctx->curr_func.max_line) {
58488 comp_ctx->curr_func.max_line = line;
58489 }
58490#else
58491 DUK_UNREF(comp_ctx);
58492#endif
58493}
58494
58495#if 0 /* unused */
58496DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
58497 duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
58498}
58499#endif
58500
58501/* Important main primitive. */
58503 duk_instr_t ins = 0;
58504 duk_int_t a_out = -1;
58505 duk_int_t b_out = -1;
58506 duk_int_t c_out = -1;
58507 duk_int_t tmp;
58508
58509 DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
58510 (unsigned long) op_flags, (long) a, (long) b, (long) c));
58511
58512 /* We could rely on max temp/const checks: if they don't exceed BC
58513 * limit, nothing here can either (just asserts would be enough).
58514 * Currently we check for the limits, which provides additional
58515 * protection against creating invalid bytecode due to compiler
58516 * bugs.
58517 */
58518
58519 DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
58520 DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
58521
58522 /* Input shuffling happens before the actual operation, while output
58523 * shuffling happens afterwards. Output shuffling decisions are still
58524 * made at the same time to reduce branch clutter; output shuffle decisions
58525 * are recorded into X_out variables.
58526 */
58527
58528 /* Slot A */
58529
58530#if defined(DUK_USE_SHUFFLE_TORTURE)
58531 if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
58532#else
58533 if (a <= DUK_BC_A_MAX) {
58534#endif
58535 ;
58536 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
58537 DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
58538 goto error_outofregs;
58539 } else if (a <= DUK_BC_BC_MAX) {
58540 comp_ctx->curr_func.needs_shuffle = 1;
58541 tmp = comp_ctx->curr_func.shuffle1;
58542 if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
58543 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
58544 } else {
58545 duk_small_int_t op = op_flags & 0xff;
58546 if (op == DUK_OP_CSVAR || op == DUK_OP_CSREG || op == DUK_OP_CSPROP) {
58547 /* Special handling for call setup instructions. The target
58548 * is expressed indirectly, but there is no output shuffling.
58549 */
58550 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) == 0);
58551 duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
58555 op_flags++; /* indirect opcode follows direct */
58556 } else {
58557 /* Output shuffle needed after main operation */
58558 a_out = a;
58559 }
58560 }
58561 a = tmp;
58562 } else {
58563 DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
58564 goto error_outofregs;
58565 }
58566
58567 /* Slot B */
58568
58569 if (b & DUK__CONST_MARKER) {
58570 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
58571 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
58572 DUK_ASSERT((op_flags & 0xff) != DUK_OP_CALL);
58573 DUK_ASSERT((op_flags & 0xff) != DUK_OP_NEW);
58574 b = b & ~DUK__CONST_MARKER;
58575#if defined(DUK_USE_SHUFFLE_TORTURE)
58576 if (0) {
58577#else
58578 if (b <= 0xff) {
58579#endif
58580 ins |= DUK_ENC_OP_A_B_C(0, 0, 0x100, 0); /* const flag for B */
58581 } else if (b <= DUK_BC_BC_MAX) {
58582 comp_ctx->curr_func.needs_shuffle = 1;
58583 tmp = comp_ctx->curr_func.shuffle2;
58584 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
58585 b = tmp;
58586 } else {
58587 DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
58588 goto error_outofregs;
58589 }
58590 } else {
58591#if defined(DUK_USE_SHUFFLE_TORTURE)
58592 if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
58593#else
58594 if (b <= 0xff) {
58595#endif
58596 ;
58597 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
58598 if (b > DUK_BC_B_MAX) {
58599 /* Note: 0xff != DUK_BC_B_MAX */
58600 DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
58601 goto error_outofregs;
58602 }
58603 } else if (b <= DUK_BC_BC_MAX) {
58604 comp_ctx->curr_func.needs_shuffle = 1;
58605 tmp = comp_ctx->curr_func.shuffle2;
58606 if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
58607 /* Output shuffle needed after main operation */
58608 b_out = b;
58609 }
58610 if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET) || (op_flags & DUK__EMIT_FLAG_B_IS_TARGETSOURCE)) {
58611 duk_small_int_t op = op_flags & 0xff;
58612 if (op == DUK_OP_CALL || op == DUK_OP_NEW ||
58613 op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
58614 /* Special handling for CALL/NEW/MPUTOBJ/MPUTARR shuffling.
58615 * For each, slot B identifies the first register of a range
58616 * of registers, so normal shuffling won't work. Instead,
58617 * an indirect version of the opcode is used.
58618 */
58619 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
58620 duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
58625 op_flags++; /* indirect opcode follows direct */
58626 } else {
58627 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
58628 }
58629 }
58630 b = tmp;
58631 } else {
58632 DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
58633 goto error_outofregs;
58634 }
58635 }
58636
58637 /* Slot C */
58638
58639 if (c & DUK__CONST_MARKER) {
58640 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
58641 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
58642 c = c & ~DUK__CONST_MARKER;
58643#if defined(DUK_USE_SHUFFLE_TORTURE)
58644 if (0) {
58645#else
58646 if (c <= 0xff) {
58647#endif
58648 ins |= DUK_ENC_OP_A_B_C(0, 0, 0, 0x100); /* const flag for C */
58649 } else if (c <= DUK_BC_BC_MAX) {
58650 comp_ctx->curr_func.needs_shuffle = 1;
58651 tmp = comp_ctx->curr_func.shuffle3;
58652 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
58653 c = tmp;
58654 } else {
58655 DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
58656 goto error_outofregs;
58657 }
58658 } else {
58659#if defined(DUK_USE_SHUFFLE_TORTURE)
58660 if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
58661#else
58662 if (c <= 0xff) {
58663#endif
58664 ;
58665 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
58666 if (c > DUK_BC_C_MAX) {
58667 /* Note: 0xff != DUK_BC_C_MAX */
58668 DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
58669 goto error_outofregs;
58670 }
58671 } else if (c <= DUK_BC_BC_MAX) {
58672 comp_ctx->curr_func.needs_shuffle = 1;
58673 tmp = comp_ctx->curr_func.shuffle3;
58674 if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
58675 /* Output shuffle needed after main operation */
58676 c_out = c;
58677 } else {
58678 duk_small_int_t op = op_flags & 0xff;
58679 if (op == DUK_OP_EXTRA &&
58681 /* Special shuffling for INITGET/INITSET, where slot C
58682 * identifies a register pair and cannot be shuffled
58683 * normally. Use an indirect variant instead.
58684 */
58685 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
58686 duk__emit_load_int32_noshuffle(comp_ctx, tmp, c);
58689 a++; /* indirect opcode follows direct */
58690 } else {
58691 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
58692 }
58693 }
58694 c = tmp;
58695 } else {
58696 DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
58697 goto error_outofregs;
58698 }
58699 }
58700
58701 /* Main operation */
58702
58703 DUK_ASSERT_DISABLE(a >= DUK_BC_A_MIN); /* unsigned */
58705 DUK_ASSERT_DISABLE(b >= DUK_BC_B_MIN); /* unsigned */
58707 DUK_ASSERT_DISABLE(c >= DUK_BC_C_MIN); /* unsigned */
58709
58710 ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
58711 duk__emit(comp_ctx, ins);
58712
58713 /* NEXTENUM needs a jump slot right after the main instruction.
58714 * When the JUMP is taken, output spilling is not needed so this
58715 * workaround is possible. The jump slot PC is exceptionally
58716 * plumbed through comp_ctx to minimize call sites.
58717 */
58718 if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
58719 comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
58720 duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
58721 }
58722
58723 /* Output shuffling: only one output register is realistically possible.
58724 *
58725 * (Zero would normally be an OK marker value: if the target register
58726 * was zero, it would never be shuffled. But with DUK_USE_SHUFFLE_TORTURE
58727 * this is no longer true, so use -1 as a marker instead.)
58728 */
58729
58730 if (a_out >= 0) {
58731 DUK_ASSERT(b_out < 0);
58732 DUK_ASSERT(c_out < 0);
58734 } else if (b_out >= 0) {
58735 DUK_ASSERT(a_out < 0);
58736 DUK_ASSERT(c_out < 0);
58737 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
58738 } else if (c_out >= 0) {
58739 DUK_ASSERT(b_out < 0);
58740 DUK_ASSERT(c_out < 0);
58741 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
58742 }
58744 return;
58745
58746 error_outofregs:
58748}
58749
58751 duk__emit_a_b_c(comp_ctx, op_flags | DUK__EMIT_FLAG_NO_SHUFFLE_C, a, b, 0);
58752}
58753
58754#if 0 /* unused */
58755DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
58757}
58758#endif
58759
58761 duk_instr_t ins;
58762 duk_int_t tmp;
58763
58764 /* allow caller to give a const number with the DUK__CONST_MARKER */
58765 bc = bc & (~DUK__CONST_MARKER);
58766
58767 DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
58768 DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
58769 DUK_ASSERT_DISABLE(bc >= DUK_BC_BC_MIN); /* unsigned */
58771 DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
58772
58773 if (bc <= DUK_BC_BC_MAX) {
58774 ;
58775 } else {
58776 /* No BC shuffling now. */
58777 goto error_outofregs;
58778 }
58779
58780#if defined(DUK_USE_SHUFFLE_TORTURE)
58781 if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
58782#else
58783 if (a <= DUK_BC_A_MAX) {
58784#endif
58785 ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
58786 duk__emit(comp_ctx, ins);
58787 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
58788 goto error_outofregs;
58789 } else if (a <= DUK_BC_BC_MAX) {
58790 comp_ctx->curr_func.needs_shuffle = 1;
58791 tmp = comp_ctx->curr_func.shuffle1;
58792 ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
58793 if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
58794 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
58795 duk__emit(comp_ctx, ins);
58796 } else {
58797 duk__emit(comp_ctx, ins);
58798 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
58799 }
58800 } else {
58801 goto error_outofregs;
58802 }
58803 return;
58804
58805 error_outofregs:
58807}
58808
58810 duk_instr_t ins;
58811
58812 DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN); /* unsigned */
58814 DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN); /* unsigned */
58815 DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
58816 DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
58817
58818 if (abc <= DUK_BC_ABC_MAX) {
58819 ;
58820 } else {
58821 goto error_outofregs;
58822 }
58823 ins = DUK_ENC_OP_ABC(op, abc);
58824 DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
58825 (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
58826 (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
58827 (long) abc, (duk_instr_t) ins));
58828 duk__emit(comp_ctx, ins);
58829 return;
58830
58831 error_outofregs:
58833}
58834
58836 DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58837 DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
58838 /* Setting "no shuffle A" is covered by the assert, but it's needed
58839 * with DUK_USE_SHUFFLE_TORTURE.
58840 */
58841 duk__emit_a_b_c(comp_ctx,
58842 DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff), /* transfer flags */
58843 extraop_flags & 0xff,
58845 c);
58846}
58847
58849 DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58850 DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
58851 /* Setting "no shuffle A" is covered by the assert, but it's needed
58852 * with DUK_USE_SHUFFLE_TORTURE.
58853 */
58854 duk__emit_a_b_c(comp_ctx,
58855 DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff), /* transfer flags */
58856 extraop_flags & 0xff,
58857 b,
58858 0);
58859}
58860
58862 DUK_ASSERT_DISABLE(extraop >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58863 DUK_ASSERT(extraop <= DUK_BC_EXTRAOP_MAX);
58864 /* Setting "no shuffle A" is covered by the assert, but it's needed
58865 * with DUK_USE_SHUFFLE_TORTURE.
58866 */
58867 duk__emit_a_bc(comp_ctx,
58869 extraop,
58870 bc);
58871}
58872
58874 DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58875 DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
58876 /* Setting "no shuffle A" is covered by the assert, but it's needed
58877 * with DUK_USE_SHUFFLE_TORTURE.
58878 */
58879 duk__emit_a_b_c(comp_ctx,
58881 DUK__EMIT_FLAG_NO_SHUFFLE_C | (extraop_flags & ~0xff), /* transfer flags */
58882 extraop_flags & 0xff,
58883 0,
58884 0);
58885}
58886
58887DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val, duk_small_uint_t op_flags) {
58888 /* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
58889 * would only shuffle once (instead of twice). The current code works
58890 * though, and has a smaller compiler footprint.
58892
58893 if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
58894 (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
58895 DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
58896 duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
58897 } else {
58898 duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
58899 duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
58900 DUK_ASSERT(lo >= 0);
58901 DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
58902 (long) reg, (long) val, (long) hi, (long) lo));
58903 duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
58904 duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
58905 }
58906}
58907
58908DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
58909 duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
58910}
58911
58912#if defined(DUK_USE_SHUFFLE_TORTURE)
58913/* Used by duk__emit*() calls so that we don't shuffle the loadints that
58914 * are needed to handle indirect opcodes.
58915 */
58916DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
58917 duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
58918}
58919#else
58920DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
58921 /* When torture not enabled, can just use the same helper because
58922 * 'reg' won't get spilled.
58924 DUK_ASSERT(reg <= DUK_BC_A_MAX);
58925 duk__emit_load_int32(comp_ctx, reg, val);
58926}
58927#endif
58928
58929DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
58930 duk_int_t curr_pc;
58931 duk_int_t offset;
58932
58933 curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
58934 offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
58938}
58939
58941 duk_int_t ret;
58942
58943 ret = duk__get_current_pc(comp_ctx); /* useful for patching jumps later */
58944 duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
58945 return ret;
58946}
58947
58948/* Insert an empty jump in the middle of code emitted earlier. This is
58949 * currently needed for compiling for-in.
58950 */
58952#if defined(DUK_USE_PC2LINE)
58953 duk_int_t line;
58954#endif
58955 duk_compiler_instr *instr;
58956 duk_size_t offset;
58957
58958 offset = jump_pc * sizeof(duk_compiler_instr),
58959 instr = (duk_compiler_instr *) (void *)
58961 &comp_ctx->curr_func.bw_code,
58962 offset,
58963 sizeof(duk_compiler_instr));
58964
58965#if defined(DUK_USE_PC2LINE)
58966 line = comp_ctx->curr_token.start_line; /* approximation, close enough */
58967#endif
58968 instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
58969#if defined(DUK_USE_PC2LINE)
58970 instr->line = line;
58971#endif
58972
58973 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
58975 goto fail_bc_limit;
58976 }
58977 return;
58978
58979 fail_bc_limit:
58981}
58982
58983/* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
58984 * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
58985 */
58986DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
58987 duk_compiler_instr *instr;
58988 duk_int_t offset;
58989
58990 /* allow negative PCs, behave as a no-op */
58991 if (jump_pc < 0) {
58992 DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
58993 (long) jump_pc, (long) target_pc));
58994 return;
58995 }
58996 DUK_ASSERT(jump_pc >= 0);
58998 /* XXX: range assert */
58999 instr = duk__get_instr_ptr(comp_ctx, jump_pc);
59000 DUK_ASSERT(instr != NULL);
59001
59002 /* XXX: range assert */
59003 offset = target_pc - jump_pc - 1;
59004
59005 instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
59006 DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
59007 (long) jump_pc, (long) target_pc, (long) offset));
59008}
59009
59011 duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
59012}
59013
59014DUK_LOCAL 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) {
59015 duk_compiler_instr *instr;
59016
59017 DUK_ASSERT((reg_catch & DUK__CONST_MARKER) == 0);
59018
59019 instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
59021 DUK_ASSERT(instr != NULL);
59022 if (const_varname & DUK__CONST_MARKER) {
59023 /* Have a catch variable. */
59024 const_varname = const_varname & (~DUK__CONST_MARKER);
59025 if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
59026 /* Catch attempts to use out-of-range reg/const. Without this
59027 * check Duktape 0.12.0 could generate invalid code which caused
59028 * an assert failure on execution. This error is triggered e.g.
59029 * for functions with a lot of constants and a try-catch statement.
59030 * Shuffling or opcode semantics change is needed to fix the issue.
59031 * See: test-bug-trycatch-many-constants.js.
59032 */
59033 DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
59034 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
59036 }
59037 instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
59038 } else {
59039 /* No catch variable, e.g. a try-finally; replace LDCONST with
59040 * NOP to avoid a bogus LDCONST.
59041 */
59044
59045 instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
59046 DUK_ASSERT(instr != NULL);
59048 DUK_ASSERT(flags <= DUK_BC_A_MAX);
59049 instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
59050}
59053 duk__emit_a_b_c(comp_ctx,
59055 0 /*false*/,
59056 regconst,
59057 0 /*unused*/);
59058}
59059
59061 duk__emit_a_b_c(comp_ctx,
59063 1 /*true*/,
59064 regconst,
59065 0 /*unused*/);
59066}
59067
59070}
59071
59072/*
59073 * Peephole optimizer for finished bytecode.
59074 *
59075 * Does not remove opcodes; currently only straightens out unconditional
59076 * jump chains which are generated by several control structures.
59077 */
59078
59081 duk_small_uint_t iter;
59082 duk_int_t i, n;
59083 duk_int_t count_opt;
59084
59085 bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
59086#if defined(DUK_USE_BUFLEN16)
59087 /* No need to assert, buffer size maximum is 0xffff. */
59088#else
59089 DUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <= (duk_size_t) DUK_INT_MAX); /* bytecode limits */
59090#endif
59091 n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
59092
59093 for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
59094 count_opt = 0;
59095
59096 for (i = 0; i < n; i++) {
59097 duk_instr_t ins;
59098 duk_int_t target_pc1;
59099 duk_int_t target_pc2;
59100
59101 ins = bc[i].ins;
59102 if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
59103 continue;
59104 }
59105
59106 target_pc1 = i + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
59107 DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
59108 DUK_ASSERT(target_pc1 >= 0);
59109 DUK_ASSERT(target_pc1 < n);
59110
59111 /* Note: if target_pc1 == i, we'll optimize a jump to itself.
59112 * This does not need to be checked for explicitly; the case
59113 * is rare and max iter breaks us out.
59114 */
59115
59116 ins = bc[target_pc1].ins;
59117 if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
59118 continue;
59119 }
59120
59121 target_pc2 = target_pc1 + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
59122
59123 DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
59124 (long) i, (long) target_pc1, (long) target_pc2));
59125
59126 bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
59128 count_opt++;
59131 DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
59133 if (count_opt == 0) {
59134 break;
59135 }
59136 }
59137}
59138
59140 * Intermediate value helpers
59142
59143#define DUK__ISREG(comp_ctx,x) (((x) & DUK__CONST_MARKER) == 0)
59144#define DUK__ISCONST(comp_ctx,x) (((x) & DUK__CONST_MARKER) != 0)
59145#define DUK__ISTEMP(comp_ctx,x) (DUK__ISREG((comp_ctx), (x)) && (duk_regconst_t) (x) >= (duk_regconst_t) ((comp_ctx)->curr_func.temp_first))
59146#define DUK__GETTEMP(comp_ctx) ((comp_ctx)->curr_func.temp_next)
59147#define DUK__SETTEMP(comp_ctx,x) ((comp_ctx)->curr_func.temp_next = (x)) /* dangerous: must only lower (temp_max not updated) */
59148#define DUK__SETTEMP_CHECKMAX(comp_ctx,x) duk__settemp_checkmax((comp_ctx),(x))
59149#define DUK__ALLOCTEMP(comp_ctx) duk__alloctemp((comp_ctx))
59150#define DUK__ALLOCTEMPS(comp_ctx,count) duk__alloctemps((comp_ctx),(count))
59151
59152/* Flags for intermediate value coercions. A flag for using a forced reg
59153 * is not needed, the forced_reg argument suffices and generates better
59154 * code (it is checked as it is used).
59155 */
59156#define DUK__IVAL_FLAG_ALLOW_CONST (1 << 0) /* allow a constant to be returned */
59157#define DUK__IVAL_FLAG_REQUIRE_TEMP (1 << 1) /* require a (mutable) temporary as a result (or a const if allowed) */
59158#define DUK__IVAL_FLAG_REQUIRE_SHORT (1 << 2) /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
59159
59160/* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(ctx,x) */
59161
59162#if 0 /* enable manually for dumping */
59163#define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
59164#define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
59166DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
59167 DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
59168 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
59170}
59171DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
59172 DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
59173 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
59174 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
59175 (long) x->t, (long) x->op,
59176 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
59178 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
59179 duk_get_tval((duk_context *) comp_ctx->thr, x->x2.valstack_idx)));
59180}
59181#else
59182#define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
59183#define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
59184#endif
59185
59186DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
59187 duk_context *ctx = (duk_context *) comp_ctx->thr;
59188
59189 dst->t = src->t;
59190 dst->regconst = src->regconst;
59191 duk_copy(ctx, src->valstack_idx, dst->valstack_idx);
59192}
59193
59195 duk_context *ctx = (duk_context *) comp_ctx->thr;
59196
59197 dst->t = src->t;
59198 dst->op = src->op;
59199 dst->x1.t = src->x1.t;
59200 dst->x1.regconst = src->x1.regconst;
59201 dst->x2.t = src->x2.t;
59202 dst->x2.regconst = src->x2.regconst;
59203 duk_copy(ctx, src->x1.valstack_idx, dst->x1.valstack_idx);
59204 duk_copy(ctx, src->x2.valstack_idx, dst->x2.valstack_idx);
59205}
59206
59207/* XXX: to util */
59210 duk_int32_t t;
59211
59212 c = DUK_FPCLASSIFY(x);
59213 if (c == DUK_FP_NORMAL || (c == DUK_FP_ZERO && !DUK_SIGNBIT(x))) {
59214 /* Don't allow negative zero as it will cause trouble with
59215 * LDINT+LDINTX. But positive zero is OK.
59216 */
59217 t = (duk_int32_t) x;
59218 if ((duk_double_t) t == x) {
59219 *ival = t;
59220 return 1;
59221 }
59222 }
59223
59224 return 0;
59225}
59226
59229
59230 res = comp_ctx->curr_func.temp_next;
59231 comp_ctx->curr_func.temp_next += num;
59233 if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) { /* == DUK__MAX_TEMPS is OK */
59235 }
59236
59237 /* maintain highest 'used' temporary, needed to figure out nregs of function */
59238 if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
59239 comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
59241
59242 return res;
59243}
59244
59246 return duk__alloctemps(comp_ctx, 1);
59247}
59248
59249DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next) {
59250 comp_ctx->curr_func.temp_next = temp_next;
59251 if (temp_next > comp_ctx->curr_func.temp_max) {
59252 comp_ctx->curr_func.temp_max = temp_next;
59253 }
59254}
59255
59256/* get const for value at valstack top */
59258 duk_hthread *thr = comp_ctx->thr;
59259 duk_context *ctx = (duk_context *) thr;
59260 duk_compiler_func *f = &comp_ctx->curr_func;
59261 duk_tval *tv1;
59262 duk_int_t i, n, n_check;
59263
59264 n = (duk_int_t) duk_get_length(ctx, f->consts_idx);
59265
59266 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
59267 DUK_ASSERT(tv1 != NULL);
59268
59269#if defined(DUK_USE_FASTINT)
59270 /* Explicit check for fastint downgrade. */
59272#endif
59273
59274 /* Sanity workaround for handling functions with a large number of
59275 * constants at least somewhat reasonably. Otherwise checking whether
59276 * we already have the constant would grow very slow (as it is O(N^2)).
59277 */
59279 for (i = 0; i < n_check; i++) {
59281
59282 /* Strict equality is NOT enough, because we cannot use the same
59283 * constant for e.g. +0 and -0.
59284 */
59285 if (duk_js_samevalue(tv1, tv2)) {
59286 DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
59287 (duk_tval *) tv1, (long) i));
59288 duk_pop(ctx);
59289 return (duk_regconst_t) (i | DUK__CONST_MARKER);
59290 }
59291 }
59292
59293 if (n > DUK__MAX_CONSTS) {
59295 }
59296
59297 DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
59298 (duk_tval *) tv1, (long) n));
59299 (void) duk_put_prop_index(ctx, f->consts_idx, n); /* invalidates tv1, tv2 */
59300 return (duk_regconst_t) (n | DUK__CONST_MARKER);
59301}
59302
59303/* Get the value represented by an duk_ispec to a register or constant.
59304 * The caller can control the result by indicating whether or not:
59305 *
59306 * (1) a constant is allowed (sometimes the caller needs the result to
59307 * be in a register)
59308 *
59309 * (2) a temporary register is required (usually when caller requires
59310 * the register to be safely mutable; normally either a bound
59311 * register or a temporary register are both OK)
59312 *
59313 * (3) a forced register target needs to be used
59314 *
59315 * Bytecode may be emitted to generate the necessary value. The return
59316 * value is either a register or a constant.
59317 */
59318
59321 duk_ispec *x,
59322 duk_reg_t forced_reg,
59323 duk_small_uint_t flags) {
59324 duk_hthread *thr = comp_ctx->thr;
59325 duk_context *ctx = (duk_context *) thr;
59326
59327 DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
59328 "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
59329 (long) x->t,
59330 (long) x->regconst,
59331 (duk_tval *) duk_get_tval(ctx, x->valstack_idx),
59332 (long) forced_reg,
59333 (unsigned long) flags,
59334 (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
59335 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
59336 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
59337
59338 switch (x->t) {
59339 case DUK_ISPEC_VALUE: {
59340 duk_tval *tv;
59341
59342 tv = DUK_GET_TVAL_POSIDX(ctx, x->valstack_idx);
59343 DUK_ASSERT(tv != NULL);
59344
59345 switch (DUK_TVAL_GET_TAG(tv)) {
59346 case DUK_TAG_UNDEFINED: {
59347 /* Note: although there is no 'undefined' literal, undefined
59348 * values can occur during compilation as a result of e.g.
59349 * the 'void' operator.
59350 */
59351 duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59353 return (duk_regconst_t) dest;
59354 }
59355 case DUK_TAG_NULL: {
59356 duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59358 return (duk_regconst_t) dest;
59359 }
59360 case DUK_TAG_BOOLEAN: {
59361 duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59362 duk__emit_extraop_bc(comp_ctx,
59364 (duk_regconst_t) dest);
59365 return (duk_regconst_t) dest;
59366 }
59367 case DUK_TAG_POINTER: {
59369 break;
59370 }
59371 case DUK_TAG_STRING: {
59372 duk_hstring *h;
59373 duk_reg_t dest;
59374 duk_regconst_t constidx;
59375
59376 h = DUK_TVAL_GET_STRING(tv);
59377 DUK_UNREF(h);
59378 DUK_ASSERT(h != NULL);
59379
59380#if 0 /* XXX: to be implemented? */
59381 /* Use special opcodes to load short strings */
59382 if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
59383 /* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
59384 } else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
59385 /* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
59386 }
59387#endif
59388 duk_dup(ctx, x->valstack_idx);
59389 constidx = duk__getconst(comp_ctx);
59390
59391 if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
59392 return constidx;
59393 }
59394
59395 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59396 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
59397 return (duk_regconst_t) dest;
59398 }
59399 case DUK_TAG_OBJECT: {
59401 break;
59402 }
59403 case DUK_TAG_BUFFER: {
59405 break;
59406 }
59407 case DUK_TAG_LIGHTFUNC: {
59409 break;
59410 }
59411#if defined(DUK_USE_FASTINT)
59412 case DUK_TAG_FASTINT:
59413#endif
59414 default: {
59415 /* number */
59416 duk_reg_t dest;
59417 duk_regconst_t constidx;
59418 duk_double_t dval;
59419 duk_int32_t ival;
59420
59423 dval = DUK_TVAL_GET_NUMBER(tv);
59424
59425 if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
59426 /* A number can be loaded either through a constant, using
59427 * LDINT, or using LDINT+LDINTX. LDINT is always a size win,
59428 * LDINT+LDINTX is not if the constant is used multiple times.
59429 * Currently always prefer LDINT+LDINTX over a double constant.
59430 */
59431
59432 if (duk__is_whole_get_int32(dval, &ival)) {
59433 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59434 duk__emit_load_int32(comp_ctx, dest, ival);
59435 return (duk_regconst_t) dest;
59436 }
59437 }
59438
59439 duk_dup(ctx, x->valstack_idx);
59440 constidx = duk__getconst(comp_ctx);
59441
59442 if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
59443 return constidx;
59444 } else {
59445 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59446 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
59447 return (duk_regconst_t) dest;
59448 }
59449 }
59450 } /* end switch */
59451 }
59452 case DUK_ISPEC_REGCONST: {
59453 if (forced_reg >= 0) {
59454 if (x->regconst & DUK__CONST_MARKER) {
59455 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
59456 } else if (x->regconst != (duk_regconst_t) forced_reg) {
59457 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
59458 } else {
59459 ; /* already in correct reg */
59460 }
59461 return (duk_regconst_t) forced_reg;
59462 }
59463
59464 DUK_ASSERT(forced_reg < 0);
59465 if (x->regconst & DUK__CONST_MARKER) {
59466 if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
59467 duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
59469 return (duk_regconst_t) dest;
59470 }
59471 return x->regconst;
59472 }
59473
59474 DUK_ASSERT(forced_reg < 0 && !(x->regconst & DUK__CONST_MARKER));
59475 if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISTEMP(comp_ctx, x->regconst)) {
59476 duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
59477 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, (duk_regconst_t) dest, x->regconst);
59478 return (duk_regconst_t) dest;
59479 }
59480 return x->regconst;
59481 }
59482 default: {
59483 break;
59485 }
59486
59488 return 0;
59489}
59490
59492 DUK_ASSERT(forced_reg >= 0);
59493 (void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
59494}
59495
59496/* Coerce an duk_ivalue to a 'plain' value by generating the necessary
59497 * arithmetic operations, property access, or variable access bytecode.
59498 * The duk_ivalue argument ('x') is converted into a plain value as a
59499 * side effect.
59500 */
59502 duk_hthread *thr = comp_ctx->thr;
59503 duk_context *ctx = (duk_context *) thr;
59504
59505 DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
59506 "forced_reg=%ld",
59507 (long) x->t, (long) x->op,
59508 (long) x->x1.t, (long) x->x1.regconst,
59509 (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
59510 (long) x->x2.t, (long) x->x2.regconst,
59511 (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
59512 (long) forced_reg));
59513
59514 switch (x->t) {
59515 case DUK_IVAL_PLAIN: {
59516 return;
59517 }
59518 /* XXX: support unary arithmetic ivalues (useful?) */
59519 case DUK_IVAL_ARITH:
59521 duk_regconst_t arg1;
59522 duk_regconst_t arg2;
59523 duk_reg_t dest;
59524 duk_tval *tv1;
59525 duk_tval *tv2;
59526
59527 DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
59528
59529 /* inline arithmetic check for constant values */
59530 /* XXX: use the exactly same arithmetic function here as in executor */
59531 if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
59532 tv1 = DUK_GET_TVAL_POSIDX(ctx, x->x1.valstack_idx);
59533 tv2 = DUK_GET_TVAL_POSIDX(ctx, x->x2.valstack_idx);
59534 DUK_ASSERT(tv1 != NULL);
59535 DUK_ASSERT(tv2 != NULL);
59536
59537 DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
59538 (duk_tval *) tv1,
59539 (duk_tval *) tv2));
59540
59541 if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
59544 duk_double_t d3;
59545 duk_bool_t accept = 1;
59546
59547 DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
59548 (double) d1, (double) d2, (long) x->op));
59549 switch (x->op) {
59550 case DUK_OP_ADD: d3 = d1 + d2; break;
59551 case DUK_OP_SUB: d3 = d1 - d2; break;
59552 case DUK_OP_MUL: d3 = d1 * d2; break;
59553 case DUK_OP_DIV: d3 = d1 / d2; break;
59554 default: accept = 0; break;
59555 }
59556
59557 if (accept) {
59559 du.d = d3;
59561 d3 = du.d;
59562
59563 x->t = DUK_IVAL_PLAIN;
59565 DUK_TVAL_SET_NUMBER(tv1, d3); /* old value is number: no refcount */
59566 return;
59567 }
59568 } else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
59569 /* inline string concatenation */
59570 duk_dup(ctx, x->x1.valstack_idx);
59571 duk_dup(ctx, x->x2.valstack_idx);
59572 duk_concat(ctx, 2);
59573 duk_replace(ctx, x->x1.valstack_idx);
59574 x->t = DUK_IVAL_PLAIN;
59576 return;
59577 }
59578 }
59579
59582
59583 /* If forced reg, use it as destination. Otherwise try to
59584 * use either coerced ispec if it is a temporary.
59585 *
59586 * When using extraops, avoid reusing arg2 as dest because that
59587 * would lead to an LDREG shuffle below. We still can't guarantee
59588 * dest != arg2 because we may have a forced_reg.
59589 */
59590 if (forced_reg >= 0) {
59591 dest = forced_reg;
59592 } else if (DUK__ISTEMP(comp_ctx, arg1)) {
59593 dest = (duk_reg_t) arg1;
59594 } else if (DUK__ISTEMP(comp_ctx, arg2) && x->t != DUK_IVAL_ARITH_EXTRAOP) {
59595 dest = (duk_reg_t) arg2;
59596 } else {
59597 dest = DUK__ALLOCTEMP(comp_ctx);
59598 }
59599
59600 /* Extraop arithmetic opcodes must have destination same as
59601 * first source. If second source matches destination we need
59602 * a temporary register to avoid clobbering the second source.
59603 *
59604 * XXX: change calling code to avoid this situation in most cases.
59605 */
59606
59607 if (x->t == DUK_IVAL_ARITH_EXTRAOP) {
59608 if (!(DUK__ISREG(comp_ctx, arg1) && (duk_reg_t) arg1 == dest)) {
59609 if (DUK__ISREG(comp_ctx, arg2) && (duk_reg_t) arg2 == dest) {
59610 /* arg2 would be clobbered so reassign it to a temp. */
59611 duk_reg_t tempreg;
59612 tempreg = DUK__ALLOCTEMP(comp_ctx);
59613 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, tempreg, arg2);
59614 arg2 = tempreg;
59615 }
59616
59617 if (DUK__ISREG(comp_ctx, arg1)) {
59618 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, arg1);
59619 } else {
59620 DUK_ASSERT(DUK__ISCONST(comp_ctx, arg1));
59621 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, arg1);
59622 }
59623 }
59624
59625 /* Note: special DUK__EMIT_FLAG_B_IS_TARGETSOURCE
59626 * used to indicate that B is both a source and a
59627 * target register. When shuffled, it needs to be
59628 * both input and output shuffled.
59629 */
59630 DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
59631 duk__emit_extraop_b_c(comp_ctx,
59634 (duk_regconst_t) dest,
59635 (duk_regconst_t) arg2);
59636
59637 } else {
59638 DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
59639 duk__emit_a_b_c(comp_ctx, x->op, (duk_regconst_t) dest, arg1, arg2);
59640 }
59641
59642 x->t = DUK_IVAL_PLAIN;
59643 x->x1.t = DUK_ISPEC_REGCONST;
59644 x->x1.regconst = (duk_regconst_t) dest;
59645 return;
59646 }
59647 case DUK_IVAL_PROP: {
59648 /* XXX: very similar to DUK_IVAL_ARITH - merge? */
59649 duk_regconst_t arg1;
59650 duk_regconst_t arg2;
59651 duk_reg_t dest;
59652
59653 /* Need a short reg/const, does not have to be a mutable temp. */
59656
59657 /* Pick a destination register. If either base value or key
59658 * happens to be a temp value, reuse it as the destination.
59659 *
59660 * XXX: The temp must be a "mutable" one, i.e. such that no
59661 * other expression is using it anymore. Here this should be
59662 * the case because the value of a property access expression
59663 * is neither the base nor the key, but the lookup result.
59664 */
59665
59666 if (forced_reg >= 0) {
59667 dest = forced_reg;
59668 } else if (DUK__ISTEMP(comp_ctx, arg1)) {
59669 dest = (duk_reg_t) arg1;
59670 } else if (DUK__ISTEMP(comp_ctx, arg2)) {
59671 dest = (duk_reg_t) arg2;
59672 } else {
59673 dest = DUK__ALLOCTEMP(comp_ctx);
59674 }
59675
59676 duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROP, (duk_regconst_t) dest, arg1, arg2);
59677
59678 x->t = DUK_IVAL_PLAIN;
59679 x->x1.t = DUK_ISPEC_REGCONST;
59680 x->x1.regconst = (duk_regconst_t) dest;
59681 return;
59682 }
59683 case DUK_IVAL_VAR: {
59684 /* x1 must be a string */
59685 duk_reg_t dest;
59686 duk_reg_t reg_varbind;
59687 duk_regconst_t rc_varname;
59688
59690
59691 duk_dup(ctx, x->x1.valstack_idx);
59692 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
59693 x->t = DUK_IVAL_PLAIN;
59694 x->x1.t = DUK_ISPEC_REGCONST;
59695 x->x1.regconst = (duk_regconst_t) reg_varbind;
59696 } else {
59697 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59698 duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, (duk_regconst_t) dest, rc_varname);
59699 x->t = DUK_IVAL_PLAIN;
59701 x->x1.regconst = (duk_regconst_t) dest;
59702 }
59703 return;
59704 }
59706 default: {
59707 DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
59708 break;
59709 }
59710 }
59711
59713 return;
59714}
59715
59716/* evaluate to plain value, no forced register (temp/bound reg both ok) */
59718 duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
59719}
59720
59721/* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
59724
59725 /* If duk__ivalue_toplain_raw() allocates a temp, forget it and
59726 * restore next temp state.
59727 */
59728 temp = DUK__GETTEMP(comp_ctx);
59729 duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
59730 DUK__SETTEMP(comp_ctx, temp);
59731}
59732
59733/* Coerce an duk_ivalue to a register or constant; result register may
59734 * be a temp or a bound register.
59735 *
59736 * The duk_ivalue argument ('x') is converted into a regconst as a
59737 * side effect.
59738 */
59741 duk_ivalue *x,
59742 duk_reg_t forced_reg,
59743 duk_small_uint_t flags) {
59744 duk_hthread *thr = comp_ctx->thr;
59745 duk_context *ctx = (duk_context *) thr;
59746 duk_regconst_t reg;
59747 DUK_UNREF(thr);
59748 DUK_UNREF(ctx);
59749
59750 DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
59751 "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
59752 (long) x->t, (long) x->op,
59753 (long) x->x1.t, (long) x->x1.regconst,
59754 (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
59755 (long) x->x2.t, (long) x->x2.regconst,
59756 (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
59757 (long) forced_reg,
59758 (unsigned long) flags,
59759 (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
59760 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
59761 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
59762
59763 /* first coerce to a plain value */
59764 duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
59766
59767 /* then to a register */
59768 reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
59769 x->x1.t = DUK_ISPEC_REGCONST;
59770 x->x1.regconst = reg;
59771
59772 return reg;
59776 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
59778
59779#if 0 /* unused */
59780DUK_LOCAL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
59781 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
59782}
59783#endif
59784
59786 DUK_ASSERT(forced_reg >= 0);
59787 (void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
59788}
59789
59791 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
59792}
59796}
59797
59798/* The issues below can be solved with better flags */
59799
59800/* XXX: many operations actually want toforcedtemp() -- brand new temp? */
59801/* XXX: need a toplain_ignore() which will only coerce a value to a temp
59802 * register if it might have a side effect. Side-effect free values do not
59803 * need to be coerced.
59804 */
59805
59806/*
59807 * Identifier handling
59808 */
59809
59811 duk_hthread *thr = comp_ctx->thr;
59812 duk_context *ctx = (duk_context *) thr;
59813 duk_hstring *h_varname;
59814 duk_reg_t ret;
59815
59816 DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
59817 (duk_tval *) duk_get_tval(ctx, -1)));
59818
59819 /*
59820 * Special name handling
59821 */
59822
59823 h_varname = duk_get_hstring(ctx, -1);
59824 DUK_ASSERT(h_varname != NULL);
59825
59826 if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
59827 DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
59828 comp_ctx->curr_func.id_access_arguments = 1;
59829 }
59830
59831 /*
59832 * Inside one or more 'with' statements fall back to slow path always.
59833 * (See e.g. test-stmt-with.js.)
59834 */
59835
59836 if (comp_ctx->curr_func.with_depth > 0) {
59837 DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
59838 goto slow_path;
59839 }
59840
59841 /*
59842 * Any catch bindings ("catch (e)") also affect identifier binding.
59843 *
59844 * Currently, the varmap is modified for the duration of the catch
59845 * clause to ensure any identifier accesses with the catch variable
59846 * name will use slow path.
59847 */
59848
59849 duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
59850 if (duk_is_number(ctx, -1)) {
59851 ret = duk_to_int(ctx, -1);
59852 duk_pop(ctx);
59853 } else {
59854 duk_pop(ctx);
59855 goto slow_path;
59856 }
59857
59858 DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
59859 return ret;
59860
59861 slow_path:
59862 DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path"));
59863
59864 comp_ctx->curr_func.id_access_slow = 1;
59865 return (duk_reg_t) -1;
59866}
59867
59868/* Lookup an identifier name in the current varmap, indicating whether the
59869 * identifier is register-bound and if not, allocating a constant for the
59870 * identifier name. Returns 1 if register-bound, 0 otherwise. Caller can
59871 * also check (out_reg_varbind >= 0) to check whether or not identifier is
59872 * register bound. The caller must NOT use out_rc_varname at all unless
59873 * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
59874 * is unsigned and doesn't have a "unused" / none value.
59875 */
59876DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
59877 duk_hthread *thr = comp_ctx->thr;
59878 duk_context *ctx = (duk_context *) thr;
59879 duk_reg_t reg_varbind;
59880 duk_regconst_t rc_varname;
59881
59882 /* [ ... varname ] */
59883
59884 duk_dup_top(ctx);
59885 reg_varbind = duk__lookup_active_register_binding(comp_ctx);
59886
59887 if (reg_varbind >= 0) {
59888 *out_reg_varbind = reg_varbind;
59889 *out_rc_varname = 0; /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
59890 duk_pop(ctx);
59891 return 1;
59892 } else {
59893 rc_varname = duk__getconst(comp_ctx);
59894 *out_reg_varbind = -1;
59895 *out_rc_varname = rc_varname;
59896 return 0;
59897 }
59898}
59899
59900/*
59901 * Label handling
59902 *
59903 * Labels are initially added with flags prohibiting both break and continue.
59904 * When the statement type is finally uncovered (after potentially multiple
59905 * labels), all the labels are updated to allow/prohibit break and continue.
59906 */
59907
59908DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {
59909 duk_hthread *thr = comp_ctx->thr;
59910 duk_context *ctx = (duk_context *) thr;
59911 duk_size_t n;
59912 duk_size_t new_size;
59913 duk_uint8_t *p;
59914 duk_labelinfo *li_start, *li;
59915
59916 /* Duplicate (shadowing) labels are not allowed, except for the empty
59917 * labels (which are used as default labels for switch and iteration
59918 * statements).
59919 *
59920 * We could also allow shadowing of non-empty pending labels without any
59921 * other issues than breaking the required label shadowing requirements
59922 * of the E5 specification, see Section 12.12.
59923 */
59924
59925 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
59926 li_start = (duk_labelinfo *) (void *) p;
59927 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
59928 n = (duk_size_t) (li - li_start);
59929
59930 while (li > li_start) {
59931 li--;
59932
59933 if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
59935 }
59936 }
59937
59938 duk_push_hstring(ctx, h_label);
59939 DUK_ASSERT(n <= DUK_UARRIDX_MAX); /* label limits */
59940 (void) duk_put_prop_index(ctx, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
59941
59942 new_size = (n + 1) * sizeof(duk_labelinfo);
59943 duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
59944 /* XXX: spare handling, slow now */
59945
59946 /* relookup after possible realloc */
59947 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
59948 li_start = (duk_labelinfo *) (void *) p;
59949 DUK_UNREF(li_start); /* silence scan-build warning */
59950 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
59951 li--;
59952
59953 /* Labels can be used for iteration statements but also for other statements,
59954 * in particular a label can be used for a block statement. All cases of a
59955 * named label accept a 'break' so that flag is set here. Iteration statements
59956 * also allow 'continue', so that flag is updated when we figure out the
59957 * statement type.
59958 */
59959
59961 li->label_id = label_id;
59962 li->h_label = h_label;
59963 li->catch_depth = comp_ctx->curr_func.catch_depth; /* catch depth from current func */
59964 li->pc_label = pc_label;
59965
59966 DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
59967 (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
59968 (long) li->catch_depth, (long) li->pc_label));
59969}
59970
59971/* Update all labels with matching label_id. */
59973 duk_uint8_t *p;
59974 duk_labelinfo *li_start, *li;
59975
59976 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
59977 li_start = (duk_labelinfo *) (void *) p;
59978 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
59979
59980 /* Match labels starting from latest; once label_id no longer matches, we can
59981 * safely exit without checking the rest of the labels (only the topmost labels
59982 * are ever updated).
59983 */
59984 while (li > li_start) {
59985 li--;
59986
59987 if (li->label_id != label_id) {
59988 break;
59989 }
59990
59991 DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
59992 (void *) li, (long) label_id, (long) flags));
59993
59994 li->flags = flags;
59995 }
59997
59998/* Lookup active label information. Break/continue distinction is necessary to handle switch
59999 * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
60000 *
60001 * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
60002 * iteration and switch statements) can. A break will match the closest unlabelled or labelled
60003 * statement. A continue will match the closest unlabelled or labelled iteration statement. It is
60004 * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
60005 * be duplicated, the continue cannot match any valid label outside the switch.
60006 *
60007 * A side effect of these rules is that a LABEL statement related to a switch should never actually
60008 * catch a continue abrupt completion at run-time. Hence an INVALID opcode can be placed in the
60009 * continue slot of the switch's LABEL statement.
60010 */
60011
60012/* XXX: awkward, especially the bunch of separate output values -> output struct? */
60013DUK_LOCAL 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) {
60014 duk_hthread *thr = comp_ctx->thr;
60015 duk_context *ctx = (duk_context *) thr;
60016 duk_uint8_t *p;
60017 duk_labelinfo *li_start, *li_end, *li;
60018 duk_bool_t match = 0;
60019
60020 DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
60021 (duk_heaphdr *) h_label, (long) is_break));
60022
60023 DUK_UNREF(ctx);
60024
60025 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
60026 li_start = (duk_labelinfo *) (void *) p;
60027 li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60028 li = li_end;
60029
60030 /* Match labels starting from latest label because there can be duplicate empty
60031 * labels in the label set.
60032 */
60033 while (li > li_start) {
60034 li--;
60035
60036 if (li->h_label != h_label) {
60037 DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
60038 (long) (li - li_start),
60039 (duk_heaphdr *) li->h_label,
60040 (duk_heaphdr *) h_label));
60041 continue;
60042 }
60043
60044 DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
60045 (long) (li - li_start), (duk_heaphdr *) h_label));
60046
60047 /* currently all labels accept a break, so no explicit check for it now */
60049
60050 if (is_break) {
60051 /* break matches always */
60052 match = 1;
60053 break;
60054 } else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
60055 /* iteration statements allow continue */
60056 match = 1;
60057 break;
60058 } else {
60059 /* continue matched this label -- we can only continue if this is the empty
60060 * label, for which duplication is allowed, and thus there is hope of
60061 * finding a match deeper in the label stack.
60062 */
60063 if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
60065 } else {
60066 DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
60067 "allow a continue -> continue lookup deeper in label stack"));
60068 }
60070 }
60071 /* XXX: match flag is awkward, rework */
60072 if (!match) {
60074 }
60075
60076 DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
60077 (duk_heaphdr *) h_label, (long) li->label_id,
60078 (long) li->catch_depth, (long) li->pc_label));
60079
60080 *out_label_id = li->label_id;
60081 *out_label_catch_depth = li->catch_depth;
60082 *out_label_pc = li->pc_label;
60083 *out_is_closest = (li == li_end - 1);
60084}
60085
60087 duk_hthread *thr = comp_ctx->thr;
60088 duk_context *ctx = (duk_context *) thr;
60089 duk_size_t new_size;
60091 /* XXX: duk_set_length */
60092 new_size = sizeof(duk_labelinfo) * (duk_size_t) len;
60093 duk_push_int(ctx, len);
60095 duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
60096}
60097
60098/*
60099 * Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
60100 *
60101 * - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
60102 * - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
60103 * - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
60104 */
60105
60106/* object literal key tracking flags */
60107#define DUK__OBJ_LIT_KEY_PLAIN (1 << 0) /* key encountered as a plain property */
60108#define DUK__OBJ_LIT_KEY_GET (1 << 1) /* key encountered as a getter */
60109#define DUK__OBJ_LIT_KEY_SET (1 << 2) /* key encountered as a setter */
60110
60112 duk_hthread *thr = comp_ctx->thr;
60113 duk_reg_t reg_obj; /* result reg */
60114 duk_reg_t reg_temp; /* temp reg */
60115 duk_reg_t temp_start; /* temp reg value for start of loop */
60116 duk_small_uint_t max_init_values; /* max # of values initialized in one MPUTARR set */
60117 duk_small_uint_t num_values; /* number of values in current MPUTARR set */
60118 duk_uarridx_t curr_idx; /* current (next) array index */
60119 duk_uarridx_t start_idx; /* start array index of current MPUTARR set */
60120 duk_uarridx_t init_idx; /* last array index explicitly initialized, +1 */
60121 duk_bool_t require_comma; /* next loop requires a comma */
60122
60123 /* DUK_TOK_LBRACKET already eaten, current token is right after that */
60125
60126 max_init_values = DUK__MAX_ARRAY_INIT_VALUES; /* XXX: depend on available temps? */
60127
60128 reg_obj = DUK__ALLOCTEMP(comp_ctx);
60129 duk__emit_extraop_b_c(comp_ctx,
60131 reg_obj,
60132 0); /* XXX: patch initial size afterwards? */
60133 temp_start = DUK__GETTEMP(comp_ctx);
60134
60135 /*
60136 * Emit initializers in sets of maximum max_init_values.
60137 * Corner cases such as single value initializers do not have
60138 * special handling now.
60139 *
60140 * Elided elements must not be emitted as 'undefined' values,
60141 * because such values would be enumerable (which is incorrect).
60142 * Also note that trailing elisions must be reflected in the
60143 * length of the final array but cause no elements to be actually
60144 * inserted.
60145 */
60146
60147 curr_idx = 0;
60148 init_idx = 0; /* tracks maximum initialized index + 1 */
60149 start_idx = 0;
60150 require_comma = 0;
60151
60152 for (;;) {
60153 num_values = 0;
60154 DUK__SETTEMP(comp_ctx, temp_start);
60155
60156 if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
60157 break;
60158 }
60159
60160 for (;;) {
60161 if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
60162 /* the outer loop will recheck and exit */
60163 break;
60164 }
60165
60166 /* comma check */
60167 if (require_comma) {
60168 if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
60169 /* comma after a value, expected */
60170 duk__advance(comp_ctx);
60171 require_comma = 0;
60172 continue;
60173 } else {
60174 goto syntax_error;
60175 }
60176 } else {
60177 if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
60178 /* elision - flush */
60179 curr_idx++;
60180 duk__advance(comp_ctx);
60181 /* if num_values > 0, MPUTARR emitted by outer loop after break */
60182 break;
60183 }
60184 }
60185 /* else an array initializer element */
60186
60187 /* initial index */
60188 if (num_values == 0) {
60189 start_idx = curr_idx;
60190 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60191 duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
60192 }
60193
60194 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
60195 DUK__SETTEMP(comp_ctx, reg_temp);
60196 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
60197 DUK__SETTEMP(comp_ctx, reg_temp + 1);
60198
60199 num_values++;
60200 curr_idx++;
60201 require_comma = 1;
60202
60203 if (num_values >= max_init_values) {
60204 /* MPUTARR emitted by outer loop */
60205 break;
60206 }
60207 }
60208
60209 if (num_values > 0) {
60210 /* - A is a source register (it's not a write target, but used
60211 * to identify the target object) but can be shuffled.
60212 * - B cannot be shuffled normally because it identifies a range
60213 * of registers, the emitter has special handling for this
60214 * (the "no shuffle" flag must not be set).
60215 * - C is a non-register number and cannot be shuffled, but
60216 * never needs to be.
60217 */
60218 duk__emit_a_b_c(comp_ctx,
60222 (duk_regconst_t) reg_obj,
60223 (duk_regconst_t) temp_start,
60224 (duk_regconst_t) num_values);
60225 init_idx = start_idx + num_values;
60226
60227 /* num_values and temp_start reset at top of outer loop */
60228 }
60229 }
60230
60232 duk__advance(comp_ctx);
60233
60234 DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
60235 (long) curr_idx, (long) init_idx));
60236
60237 /* trailing elisions? */
60238 if (curr_idx > init_idx) {
60239 /* yes, must set array length explicitly */
60240 DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
60241 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60242 duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
60243 duk__emit_extraop_b_c(comp_ctx,
60245 (duk_regconst_t) reg_obj,
60246 (duk_regconst_t) reg_temp);
60247 }
60248
60249 DUK__SETTEMP(comp_ctx, temp_start);
60250
60251 res->t = DUK_IVAL_PLAIN;
60252 res->x1.t = DUK_ISPEC_REGCONST;
60253 res->x1.regconst = (duk_regconst_t) reg_obj;
60254 return;
60255
60256 syntax_error:
60258}
60259
60260/* duplicate/invalid key checks; returns 1 if syntax error */
60262 duk_hthread *thr = comp_ctx->thr;
60263 duk_context *ctx = (duk_context *) thr;
60264 duk_small_uint_t key_flags;
60265
60266 /* [ ... key_obj key ] */
60267
60268 DUK_ASSERT(duk_is_string(ctx, -1));
60269
60270 /*
60271 * 'key_obj' tracks keys encountered so far by associating an
60272 * integer with flags with already encountered keys. The checks
60273 * below implement E5 Section 11.1.5, step 4 for production:
60274 *
60275 * PropertyNameAndValueList: PropertyNameAndValueList , PropertyAssignment
60276 */
60277
60278 duk_dup(ctx, -1); /* [ ... key_obj key key ] */
60279 duk_get_prop(ctx, -3); /* [ ... key_obj key val ] */
60280 key_flags = duk_to_int(ctx, -1);
60281 duk_pop(ctx); /* [ ... key_obj key ] */
60282
60283 if (new_key_flags & DUK__OBJ_LIT_KEY_PLAIN) {
60284 if ((key_flags & DUK__OBJ_LIT_KEY_PLAIN) && comp_ctx->curr_func.is_strict) {
60285 /* step 4.a */
60286 DUK_DDD(DUK_DDDPRINT("duplicate key: plain key appears twice in strict mode"));
60287 return 1;
60288 }
60289 if (key_flags & (DUK__OBJ_LIT_KEY_GET | DUK__OBJ_LIT_KEY_SET)) {
60290 /* step 4.c */
60291 DUK_DDD(DUK_DDDPRINT("duplicate key: plain key encountered after setter/getter"));
60292 return 1;
60293 }
60294 } else {
60295 if (key_flags & DUK__OBJ_LIT_KEY_PLAIN) {
60296 /* step 4.b */
60297 DUK_DDD(DUK_DDDPRINT("duplicate key: getter/setter encountered after plain key"));
60298 return 1;
60299 }
60300 if (key_flags & new_key_flags) {
60301 /* step 4.d */
60302 DUK_DDD(DUK_DDDPRINT("duplicate key: getter/setter encountered twice"));
60303 return 1;
60304 }
60305 }
60306
60307 new_key_flags |= key_flags;
60308 DUK_DDD(DUK_DDDPRINT("setting/updating key %!T flags: 0x%08lx -> 0x%08lx",
60309 (duk_tval *) duk_get_tval(ctx, -1),
60310 (unsigned long) key_flags,
60311 (unsigned long) new_key_flags));
60312 duk_dup(ctx, -1);
60313 duk_push_int(ctx, new_key_flags); /* [ ... key_obj key key flags ] */
60314 duk_put_prop(ctx, -4); /* [ ... key_obj key ] */
60315
60316 return 0;
60317}
60318
60320 duk_hthread *thr = comp_ctx->thr;
60321 duk_context *ctx = (duk_context *) thr;
60322 duk_reg_t reg_obj; /* result reg */
60323 duk_reg_t reg_key; /* temp reg for key literal */
60324 duk_reg_t reg_temp; /* temp reg */
60325 duk_reg_t temp_start; /* temp reg value for start of loop */
60326 duk_small_uint_t max_init_pairs; /* max # of key-value pairs initialized in one MPUTOBJ set */
60327 duk_small_uint_t num_pairs; /* number of pairs in current MPUTOBJ set */
60328 duk_bool_t first; /* first value: comma must not precede the value */
60329 duk_bool_t is_set, is_get; /* temps */
60330
60331 DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
60332
60333 max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS; /* XXX: depend on available temps? */
60334
60335 reg_obj = DUK__ALLOCTEMP(comp_ctx);
60336 duk__emit_extraop_b_c(comp_ctx,
60338 reg_obj,
60339 0); /* XXX: patch initial size afterwards? */
60340 temp_start = DUK__GETTEMP(comp_ctx);
60341
60342 /* temp object for tracking / detecting duplicate keys */
60343 duk_push_object(ctx);
60344
60345 /*
60346 * Emit initializers in sets of maximum max_init_pairs keys.
60347 * Setter/getter is handled separately and terminates the
60348 * current set of initializer values. Corner cases such as
60349 * single value initializers do not have special handling now.
60350 */
60351
60352 first = 1;
60353 for (;;) {
60354 num_pairs = 0;
60355 DUK__SETTEMP(comp_ctx, temp_start);
60356
60357 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60358 break;
60359 }
60360
60361 for (;;) {
60362 /*
60363 * Three possible element formats:
60364 * 1) PropertyName : AssignmentExpression
60365 * 2) get PropertyName () { FunctionBody }
60366 * 3) set PropertyName ( PropertySetParameterList ) { FunctionBody }
60367 *
60368 * PropertyName can be IdentifierName (includes reserved words), a string
60369 * literal, or a number literal. Note that IdentifierName allows 'get' and
60370 * 'set' too, so we need to look ahead to the next token to distinguish:
60371 *
60372 * { get : 1 }
60373 *
60374 * and
60375 *
60376 * { get foo() { return 1 } }
60377 * { get get() { return 1 } } // 'get' as getter propertyname
60378 *
60379 * Finally, a trailing comma is allowed.
60380 *
60381 * Key name is coerced to string at compile time (and ends up as a
60382 * a string constant) even for numeric keys (e.g. "{1:'foo'}").
60383 * These could be emitted using e.g. LDINT, but that seems hardly
60384 * worth the effort and would increase code size.
60385 */
60386
60387 DUK_DDD(DUK_DDDPRINT("object literal inner loop, curr_token->t = %ld",
60388 (long) comp_ctx->curr_token.t));
60389
60390 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60391 /* the outer loop will recheck and exit */
60392 break;
60393 }
60394 if (num_pairs >= max_init_pairs) {
60395 /* MPUTOBJ emitted by outer loop */
60396 break;
60397 }
60398
60399 if (first) {
60400 first = 0;
60401 } else {
60402 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
60403 goto syntax_error;
60404 }
60405 duk__advance(comp_ctx);
60406 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60407 /* trailing comma followed by rcurly */
60408 break;
60409 }
60410 }
60411
60412 /* advance to get one step of lookup */
60413 duk__advance(comp_ctx);
60414
60415 /* NOTE: "get" and "set" are not officially ReservedWords and the lexer
60416 * currently treats them always like ordinary identifiers (DUK_TOK_GET
60417 * and DUK_TOK_SET are unused). They need to be detected based on the
60418 * identifier string content.
60419 */
60420
60421 is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
60422 comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
60423 is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
60424 comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
60425 if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
60426 /* getter/setter */
60427 duk_int_t fnum;
60428
60429 if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER ||
60430 comp_ctx->curr_token.t_nores == DUK_TOK_STRING) {
60431 /* same handling for identifiers and strings */
60432 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
60433 duk_push_hstring(ctx, comp_ctx->curr_token.str1);
60434 } else if (comp_ctx->curr_token.t == DUK_TOK_NUMBER) {
60435 duk_push_number(ctx, comp_ctx->curr_token.num);
60436 duk_to_string(ctx, -1);
60437 } else {
60438 goto syntax_error;
60439 }
60440
60441 DUK_ASSERT(duk_is_string(ctx, -1));
60444 goto syntax_error;
60445 }
60446 reg_key = duk__getconst(comp_ctx);
60447
60448 if (num_pairs > 0) {
60449 /* - A is a source register (it's not a write target, but used
60450 * to identify the target object) but can be shuffled.
60451 * - B cannot be shuffled normally because it identifies a range
60452 * of registers, the emitter has special handling for this
60453 * (the "no shuffle" flag must not be set).
60454 * - C is a non-register number and cannot be shuffled, but
60455 * never needs to be.
60456 */
60457 duk__emit_a_b_c(comp_ctx,
60461 reg_obj,
60462 temp_start,
60463 num_pairs);
60464 num_pairs = 0;
60465 DUK__SETTEMP(comp_ctx, temp_start);
60466 }
60467
60468 /* curr_token = get/set name */
60469 fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*is_decl*/, 1 /*is_setget*/);
60470
60471 DUK_ASSERT(DUK__GETTEMP(comp_ctx) == temp_start);
60472 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60473 duk__emit_a_bc(comp_ctx,
60475 (duk_regconst_t) reg_temp,
60476 (duk_regconst_t) reg_key);
60477 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60478 duk__emit_a_bc(comp_ctx,
60480 (duk_regconst_t) reg_temp,
60481 (duk_regconst_t) fnum);
60482
60483 /* Slot C is used in a non-standard fashion (range of regs),
60484 * emitter code has special handling for it (must not set the
60485 * "no shuffle" flag).
60486 */
60487 duk__emit_extraop_b_c(comp_ctx,
60489 reg_obj,
60490 temp_start); /* temp_start+0 = key, temp_start+1 = closure */
60491
60492 DUK__SETTEMP(comp_ctx, temp_start);
60493 } else {
60494 /* normal key/value */
60495 if (comp_ctx->prev_token.t_nores == DUK_TOK_IDENTIFIER ||
60496 comp_ctx->prev_token.t_nores == DUK_TOK_STRING) {
60497 /* same handling for identifiers and strings */
60498 DUK_ASSERT(comp_ctx->prev_token.str1 != NULL);
60499 duk_push_hstring(ctx, comp_ctx->prev_token.str1);
60500 } else if (comp_ctx->prev_token.t == DUK_TOK_NUMBER) {
60501 duk_push_number(ctx, comp_ctx->prev_token.num);
60502 duk_to_string(ctx, -1);
60503 } else {
60504 goto syntax_error;
60505 }
60506
60507 DUK_ASSERT(duk_is_string(ctx, -1));
60509 goto syntax_error;
60510 }
60511 reg_key = duk__getconst(comp_ctx);
60512
60513 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60514 duk__emit_a_bc(comp_ctx,
60516 (duk_regconst_t) reg_temp,
60517 (duk_regconst_t) reg_key);
60519
60520 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
60521 DUK__SETTEMP(comp_ctx, reg_temp);
60522 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
60523 DUK__SETTEMP(comp_ctx, reg_temp + 1);
60524
60525 num_pairs++;
60526 }
60527 }
60528
60529 if (num_pairs > 0) {
60530 /* See MPUTOBJ comments above. */
60531 duk__emit_a_b_c(comp_ctx,
60535 reg_obj,
60536 temp_start,
60537 num_pairs);
60538
60539 /* num_pairs and temp_start reset at top of outer loop */
60540 }
60541 }
60542
60543 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
60544 duk__advance(comp_ctx);
60545
60546 DUK__SETTEMP(comp_ctx, temp_start);
60547
60549 res->x1.t = DUK_ISPEC_REGCONST;
60550 res->x1.regconst = (duk_regconst_t) reg_obj;
60551
60552 DUK_DDD(DUK_DDDPRINT("final tracking object: %!T",
60553 (duk_tval *) duk_get_tval(ctx, -1)));
60554 duk_pop(ctx);
60555 return;
60556
60557 syntax_error:
60559}
60560
60561/* Parse argument list. Arguments are written to temps starting from
60562 * "next temp". Returns number of arguments parsed. Expects left paren
60563 * to be already eaten, and eats the right paren before returning.
60564 */
60566 duk_int_t nargs = 0;
60567 duk_reg_t reg_temp;
60568
60569 /* Note: expect that caller has already eaten the left paren */
60570
60571 DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
60572 (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
60573
60574 for (;;) {
60575 if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
60576 break;
60577 }
60578 if (nargs > 0) {
60580 }
60581
60582 /* We want the argument expression value to go to "next temp"
60583 * without additional moves. That should almost always be the
60584 * case, but we double check after expression parsing.
60585 *
60586 * This is not the cleanest possible approach.
60587 */
60588
60589 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* bump up "allocated" reg count, just in case */
60590 DUK__SETTEMP(comp_ctx, reg_temp);
60591
60592 /* binding power must be high enough to NOT allow comma expressions directly */
60593 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp); /* always allow 'in', coerce to 'tr' just in case */
60594
60595 DUK__SETTEMP(comp_ctx, reg_temp + 1);
60596 nargs++;
60597
60598 DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
60599 }
60600
60601 /* eat the right paren */
60603
60604 DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
60605
60606 return nargs;
60607}
60608
60610 /* empty expressions can be detected conveniently with nud/led counts */
60611 return (comp_ctx->curr_func.nud_count == 0) &&
60612 (comp_ctx->curr_func.led_count == 0);
60613}
60614
60615DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
60616 duk_hthread *thr = comp_ctx->thr;
60617 duk_context *ctx = (duk_context *) thr;
60618 duk_token *tk;
60619 duk_reg_t temp_at_entry;
60620 duk_small_int_t tok;
60621 duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
60622
60623 /*
60624 * ctx->prev_token token to process with duk__expr_nud()
60625 * ctx->curr_token updated by caller
60626 *
60627 * Note: the token in the switch below has already been eaten.
60628 */
60629
60630 temp_at_entry = DUK__GETTEMP(comp_ctx);
60631
60632 comp_ctx->curr_func.nud_count++;
60633
60634 tk = &comp_ctx->prev_token;
60635 tok = tk->t;
60636 res->t = DUK_IVAL_NONE;
60637
60638 DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
60639 (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
60640
60641 switch (tok) {
60642
60643 /* PRIMARY EXPRESSIONS */
60644
60645 case DUK_TOK_THIS: {
60646 duk_reg_t reg_temp;
60647 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60648 duk__emit_extraop_bc(comp_ctx,
60650 (duk_regconst_t) reg_temp);
60651 res->t = DUK_IVAL_PLAIN;
60652 res->x1.t = DUK_ISPEC_REGCONST;
60653 res->x1.regconst = (duk_regconst_t) reg_temp;
60654 return;
60655 }
60656 case DUK_TOK_IDENTIFIER: {
60657 res->t = DUK_IVAL_VAR;
60658 res->x1.t = DUK_ISPEC_VALUE;
60659 duk_push_hstring(ctx, tk->str1);
60660 duk_replace(ctx, res->x1.valstack_idx);
60661 return;
60662 }
60663 case DUK_TOK_NULL: {
60664 duk_push_null(ctx);
60665 goto plain_value;
60666 }
60667 case DUK_TOK_TRUE: {
60668 duk_push_true(ctx);
60669 goto plain_value;
60670 }
60671 case DUK_TOK_FALSE: {
60672 duk_push_false(ctx);
60673 goto plain_value;
60674 }
60675 case DUK_TOK_NUMBER: {
60676 duk_push_number(ctx, tk->num);
60677 goto plain_value;
60678 }
60679 case DUK_TOK_STRING: {
60680 DUK_ASSERT(tk->str1 != NULL);
60681 duk_push_hstring(ctx, tk->str1);
60682 goto plain_value;
60683 }
60684 case DUK_TOK_REGEXP: {
60685#ifdef DUK_USE_REGEXP_SUPPORT
60686 duk_reg_t reg_temp;
60687 duk_regconst_t rc_re_bytecode; /* const */
60688 duk_regconst_t rc_re_source; /* const */
60689
60690 DUK_ASSERT(tk->str1 != NULL);
60691 DUK_ASSERT(tk->str2 != NULL);
60692
60693 DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
60694 (duk_heaphdr *) tk->str1,
60695 (duk_heaphdr *) tk->str2));
60696
60697 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60698 duk_push_hstring(ctx, tk->str1);
60699 duk_push_hstring(ctx, tk->str2);
60700
60701 /* [ ... pattern flags ] */
60702
60703 duk_regexp_compile(thr);
60704
60705 /* [ ... escaped_source bytecode ] */
60706
60707 rc_re_bytecode = duk__getconst(comp_ctx);
60708 rc_re_source = duk__getconst(comp_ctx);
60709
60710 duk__emit_a_b_c(comp_ctx,
60712 (duk_regconst_t) reg_temp /*a*/,
60713 rc_re_bytecode /*b*/,
60714 rc_re_source /*c*/);
60715
60716 res->t = DUK_IVAL_PLAIN;
60717 res->x1.t = DUK_ISPEC_REGCONST;
60718 res->x1.regconst = (duk_regconst_t) reg_temp;
60719 return;
60720#else /* DUK_USE_REGEXP_SUPPORT */
60721 goto syntax_error;
60722#endif /* DUK_USE_REGEXP_SUPPORT */
60723 }
60724 case DUK_TOK_LBRACKET: {
60725 DUK_DDD(DUK_DDDPRINT("parsing array literal"));
60726 duk__nud_array_literal(comp_ctx, res);
60727 return;
60728 }
60729 case DUK_TOK_LCURLY: {
60730 DUK_DDD(DUK_DDDPRINT("parsing object literal"));
60731 duk__nud_object_literal(comp_ctx, res);
60732 return;
60733 }
60734 case DUK_TOK_LPAREN: {
60735 duk_bool_t prev_allow_in;
60736
60737 comp_ctx->curr_func.paren_level++;
60738 prev_allow_in = comp_ctx->curr_func.allow_in;
60739 comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
60740
60741 duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */
60742
60744 comp_ctx->curr_func.allow_in = prev_allow_in;
60745 comp_ctx->curr_func.paren_level--;
60746 return;
60747 }
60748
60749 /* MEMBER/NEW/CALL EXPRESSIONS */
60750
60751 case DUK_TOK_NEW: {
60752 /*
60753 * Parsing an expression starting with 'new' is tricky because
60754 * there are multiple possible productions deriving from
60755 * LeftHandSideExpression which begin with 'new'.
60756 *
60757 * We currently resort to one-token lookahead to distinguish the
60758 * cases. Hopefully this is correct. The binding power must be
60759 * such that parsing ends at an LPAREN (CallExpression) but not at
60760 * a PERIOD or LBRACKET (MemberExpression).
60761 *
60762 * See doc/compiler.rst for discussion on the parsing approach,
60763 * and testcases/test-dev-new.js for a bunch of documented tests.
60764 */
60765
60766 duk_reg_t reg_target;
60767 duk_int_t nargs;
60768
60769 DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
60770
60771 reg_target = DUK__ALLOCTEMP(comp_ctx);
60772 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
60773 DUK__SETTEMP(comp_ctx, reg_target + 1);
60774
60775 if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
60776 /* 'new' MemberExpression Arguments */
60777 DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
60778 duk__advance(comp_ctx);
60779 nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp", reg_target + 1 */
60780 /* right paren eaten */
60781 } else {
60782 /* 'new' MemberExpression */
60783 DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
60784 nargs = 0;
60785 }
60786
60787 /* Opcode slot C is used in a non-standard way, so shuffling
60788 * is not allowed.
60789 */
60790 duk__emit_a_b_c(comp_ctx,
60792 0 /*unused*/,
60793 reg_target /*target*/,
60794 nargs /*num_args*/);
60795
60796 DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
60797
60798 res->t = DUK_IVAL_PLAIN;
60799 res->x1.t = DUK_ISPEC_REGCONST;
60800 res->x1.regconst = (duk_regconst_t) reg_target;
60801 return;
60802 }
60803
60804 /* FUNCTION EXPRESSIONS */
60805
60806 case DUK_TOK_FUNCTION: {
60807 /* Function expression. Note that any statement beginning with 'function'
60808 * is handled by the statement parser as a function declaration, or a
60809 * non-standard function expression/statement (or a SyntaxError). We only
60810 * handle actual function expressions (occurring inside an expression) here.
60811 *
60812 * O(depth^2) parse count for inner functions is handled by recording a
60813 * lexer offset on the first compilation pass, so that the function can
60814 * be efficiently skipped on the second pass. This is encapsulated into
60815 * duk__parse_func_like_fnum().
60816 */
60817
60818 duk_reg_t reg_temp;
60819 duk_int_t fnum;
60820
60821 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60822
60823 /* curr_token follows 'function' */
60824 fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*is_decl*/, 0 /*is_setget*/);
60825 DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
60826
60827 duk__emit_a_bc(comp_ctx,
60829 (duk_regconst_t) reg_temp /*a*/,
60830 (duk_regconst_t) fnum /*bc*/);
60831
60832 res->t = DUK_IVAL_PLAIN;
60833 res->x1.t = DUK_ISPEC_REGCONST;
60834 res->x1.regconst = (duk_regconst_t) reg_temp;
60835 return;
60836 }
60837
60838 /* UNARY EXPRESSIONS */
60839
60840 case DUK_TOK_DELETE: {
60841 /* Delete semantics are a bit tricky. The description in E5 specification
60842 * is kind of confusing, because it distinguishes between resolvability of
60843 * a reference (which is only known at runtime) seemingly at compile time
60844 * (= SyntaxError throwing).
60845 */
60846 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60847 if (res->t == DUK_IVAL_VAR) {
60848 /* not allowed in strict mode, regardless of whether resolves;
60849 * in non-strict mode DELVAR handles both non-resolving and
60850 * resolving cases (the specification description is a bit confusing).
60851 */
60852
60853 duk_reg_t reg_temp;
60854 duk_reg_t reg_varbind;
60855 duk_regconst_t rc_varname;
60856
60857 if (comp_ctx->curr_func.is_strict) {
60859 }
60860
60861 DUK__SETTEMP(comp_ctx, temp_at_entry);
60862 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60863
60864 duk_dup(ctx, res->x1.valstack_idx);
60865 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
60866 /* register bound variables are non-configurable -> always false */
60867 duk__emit_extraop_bc(comp_ctx,
60869 (duk_regconst_t) reg_temp);
60870 } else {
60871 duk_dup(ctx, res->x1.valstack_idx);
60872 rc_varname = duk__getconst(comp_ctx);
60873 duk__emit_a_b(comp_ctx,
60875 (duk_regconst_t) reg_temp,
60876 (duk_regconst_t) rc_varname);
60877 }
60878 res->t = DUK_IVAL_PLAIN;
60879 res->x1.t = DUK_ISPEC_REGCONST;
60880 res->x1.regconst = (duk_regconst_t) reg_temp;
60881 } else if (res->t == DUK_IVAL_PROP) {
60882 duk_reg_t reg_temp;
60883 duk_reg_t reg_obj;
60884 duk_regconst_t rc_key;
60885
60886 DUK__SETTEMP(comp_ctx, temp_at_entry);
60887 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60888 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
60889 rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
60890 duk__emit_a_b_c(comp_ctx,
60892 (duk_regconst_t) reg_temp,
60893 (duk_regconst_t) reg_obj,
60894 rc_key);
60895
60896 res->t = DUK_IVAL_PLAIN;
60897 res->x1.t = DUK_ISPEC_REGCONST;
60898 res->x1.regconst = (duk_regconst_t) reg_temp;
60899 } else {
60900 /* non-Reference deletion is always 'true', even in strict mode */
60901 duk_push_true(ctx);
60902 goto plain_value;
60903 }
60904 return;
60905 }
60906 case DUK_TOK_VOID: {
60907 duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60908 duk_push_undefined(ctx);
60909 goto plain_value;
60910 }
60911 case DUK_TOK_TYPEOF: {
60912 /* 'typeof' must handle unresolvable references without throwing
60913 * a ReferenceError (E5 Section 11.4.3). Register mapped values
60914 * will never be unresolvable so special handling is only required
60915 * when an identifier is a "slow path" one.
60916 */
60917 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60918
60919 if (res->t == DUK_IVAL_VAR) {
60920 duk_reg_t reg_varbind;
60921 duk_regconst_t rc_varname;
60922 duk_reg_t reg_temp;
60923
60924 duk_dup(ctx, res->x1.valstack_idx);
60925 if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
60926 DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
60927 "at compile time, need to use special run-time handling"));
60928 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60929 duk__emit_extraop_b_c(comp_ctx,
60931 reg_temp,
60932 rc_varname);
60933 res->t = DUK_IVAL_PLAIN;
60934 res->x1.t = DUK_ISPEC_REGCONST;
60935 res->x1.regconst = (duk_regconst_t) reg_temp;
60936 return;
60937 }
60938 }
60939
60940 args = (DUK_EXTRAOP_TYPEOF << 8) + 0;
60941 goto unary_extraop;
60942 }
60943 case DUK_TOK_INCREMENT: {
60944 args = (DUK_OP_PREINCR << 8) + 0;
60945 goto preincdec;
60946 }
60947 case DUK_TOK_DECREMENT: {
60948 args = (DUK_OP_PREDECR << 8) + 0;
60949 goto preincdec;
60950 }
60951 case DUK_TOK_ADD: {
60952 /* unary plus */
60953 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60954 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
60955 duk_is_number(ctx, res->x1.valstack_idx)) {
60956 /* unary plus of a number is identity */
60957 ;
60958 return;
60959 }
60960 args = (DUK_EXTRAOP_UNP << 8) + 0;
60961 goto unary_extraop;
60962 }
60963 case DUK_TOK_SUB: {
60964 /* unary minus */
60965 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60966 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
60967 duk_is_number(ctx, res->x1.valstack_idx)) {
60968 /* this optimization is important to handle negative literals
60969 * (which are not directly provided by the lexical grammar)
60970 */
60971 duk_tval *tv_num;
60973
60974 tv_num = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
60975 DUK_ASSERT(tv_num != NULL);
60977 du.d = DUK_TVAL_GET_NUMBER(tv_num);
60978 du.d = -du.d;
60980 DUK_TVAL_SET_NUMBER(tv_num, du.d);
60981 return;
60982 }
60983 args = (DUK_EXTRAOP_UNM << 8) + 0;
60984 goto unary_extraop;
60985 }
60986 case DUK_TOK_BNOT: {
60987 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60988 args = (DUK_EXTRAOP_BNOT << 8) + 0;
60989 goto unary_extraop;
60990 }
60991 case DUK_TOK_LNOT: {
60992 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60993 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
60994 /* Very minimal inlining to handle common idioms '!0' and '!1',
60995 * and also boolean arguments like '!false' and '!true'.
60996 */
60997 duk_tval *tv_val;
60998
60999 tv_val = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
61000 DUK_ASSERT(tv_val != NULL);
61001 if (DUK_TVAL_IS_NUMBER(tv_val)) {
61002 duk_double_t d;
61003 d = DUK_TVAL_GET_NUMBER(tv_val);
61004 if (d == 0.0) {
61005 /* Matches both +0 and -0 on purpose. */
61006 DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
61008 return;
61009 } else if (d == 1.0) {
61010 DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
61012 return;
61013 }
61014 } else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
61016 v = DUK_TVAL_GET_BOOLEAN(tv_val);
61017 DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
61018 DUK_ASSERT(v == 0 || v == 1);
61019 DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
61020 return;
61021 }
61022 }
61023 args = (DUK_EXTRAOP_LNOT << 8) + 0;
61024 goto unary_extraop;
61025 }
61026
61027 } /* end switch */
61028
61030 return;
61031
61032 unary_extraop:
61033 {
61034 /* Note: must coerce to a (writable) temp register, so that e.g. "!x" where x
61035 * is a reg-mapped variable works correctly (does not mutate the variable register).
61036 */
61037
61038 duk_reg_t reg_temp;
61039 reg_temp = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
61040 duk__emit_extraop_bc(comp_ctx,
61041 (args >> 8),
61042 (duk_regconst_t) reg_temp);
61043 res->t = DUK_IVAL_PLAIN;
61044 res->x1.t = DUK_ISPEC_REGCONST;
61045 res->x1.regconst = (duk_regconst_t) reg_temp;
61046 return;
61047 }
61048
61049 preincdec:
61050 {
61051 /* preincrement and predecrement */
61052 duk_reg_t reg_res;
61053 duk_small_uint_t args_op = args >> 8;
61054
61055 /* Specific assumptions for opcode numbering. */
61060
61061 reg_res = DUK__ALLOCTEMP(comp_ctx);
61062
61063 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61064 if (res->t == DUK_IVAL_VAR) {
61065 duk_hstring *h_varname;
61066 duk_reg_t reg_varbind;
61067 duk_regconst_t rc_varname;
61068
61069 h_varname = duk_get_hstring(ctx, res->x1.valstack_idx);
61070 DUK_ASSERT(h_varname != NULL);
61071
61072 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
61073 goto syntax_error;
61074 }
61075
61076 duk_dup(ctx, res->x1.valstack_idx);
61077 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61078 duk__emit_a_bc(comp_ctx,
61079 args_op, /* e.g. DUK_OP_PREINCR */
61080 (duk_regconst_t) reg_res,
61081 (duk_regconst_t) reg_varbind);
61082 } else {
61083 duk__emit_a_bc(comp_ctx,
61084 args_op + 4, /* e.g. DUK_OP_PREINCV */
61085 (duk_regconst_t) reg_res,
61086 rc_varname);
61087 }
61088
61089 DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
61090 (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
61091 } else if (res->t == DUK_IVAL_PROP) {
61092 duk_reg_t reg_obj; /* allocate to reg only (not const) */
61093 duk_regconst_t rc_key;
61094 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
61095 rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
61096 duk__emit_a_b_c(comp_ctx,
61097 args_op + 8, /* e.g. DUK_OP_PREINCP */
61098 (duk_regconst_t) reg_res,
61099 (duk_regconst_t) reg_obj,
61100 rc_key);
61101 } else {
61102 /* Technically return value is not needed because INVLHS will
61103 * unconditially throw a ReferenceError. Coercion is necessary
61104 * for proper semantics (consider ToNumber() called for an object).
61105 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
61106 */
61107
61108 duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
61109 duk__emit_extraop_bc(comp_ctx,
61111 reg_res); /* for side effects, result ignored */
61112 duk__emit_extraop_only(comp_ctx,
61114 }
61115 res->t = DUK_IVAL_PLAIN;
61116 res->x1.t = DUK_ISPEC_REGCONST;
61117 res->x1.regconst = (duk_regconst_t) reg_res;
61118 DUK__SETTEMP(comp_ctx, reg_res + 1);
61119 return;
61120 }
61121
61122 plain_value:
61123 {
61124 /* Stack top contains plain value */
61125 res->t = DUK_IVAL_PLAIN;
61126 res->x1.t = DUK_ISPEC_VALUE;
61127 duk_replace(ctx, res->x1.valstack_idx);
61128 return;
61129 }
61130
61131 syntax_error:
61133}
61134
61135/* XXX: add flag to indicate whether caller cares about return value; this
61136 * affects e.g. handling of assignment expressions. This change needs API
61137 * changes elsewhere too.
61138 */
61140 duk_hthread *thr = comp_ctx->thr;
61141 duk_context *ctx = (duk_context *) thr;
61142 duk_token *tk;
61143 duk_small_int_t tok;
61144 duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
61145
61146 /*
61147 * ctx->prev_token token to process with duk__expr_led()
61148 * ctx->curr_token updated by caller
61149 */
61150
61151 comp_ctx->curr_func.led_count++;
61152
61153 /* The token in the switch has already been eaten here */
61154 tk = &comp_ctx->prev_token;
61155 tok = tk->t;
61156
61157 DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
61158 (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
61159
61160 /* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
61161
61162 switch (tok) {
61163
61164 /* PRIMARY EXPRESSIONS */
61165
61166 case DUK_TOK_PERIOD: {
61167 /* Property access expressions are critical for correct LHS ordering,
61168 * see comments in duk__expr()!
61169 *
61170 * A conservative approach would be to use duk__ivalue_totempconst()
61171 * for 'left'. However, allowing a reg-bound variable seems safe here
61172 * and is nice because "foo.bar" is a common expression. If the ivalue
61173 * is used in an expression a GETPROP will occur before any changes to
61174 * the base value can occur. If the ivalue is used as an assignment
61175 * LHS, the assignment code will ensure the base value is safe from
61176 * RHS mutation.
61177 */
61178
61179 /* XXX: This now coerces an identifier into a GETVAR to a temp, which
61180 * causes an extra LDREG in call setup. It's sufficient to coerce to a
61181 * unary ivalue?
61182 */
61183 duk__ivalue_toplain(comp_ctx, left);
61184
61185 /* NB: must accept reserved words as property name */
61186 if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
61188 }
61189
61190 res->t = DUK_IVAL_PROP;
61191 duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
61192 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
61193 duk_push_hstring(ctx, comp_ctx->curr_token.str1);
61194 duk_replace(ctx, res->x2.valstack_idx);
61195 res->x2.t = DUK_ISPEC_VALUE;
61196
61197 /* special RegExp literal handling after IdentifierName */
61198 comp_ctx->curr_func.reject_regexp_in_adv = 1;
61199
61200 duk__advance(comp_ctx);
61201 return;
61202 }
61203 case DUK_TOK_LBRACKET: {
61204 /* Property access expressions are critical for correct LHS ordering,
61205 * see comments in duk__expr()!
61206 */
61207
61208 /* XXX: optimize temp reg use */
61209 /* XXX: similar coercion issue as in DUK_TOK_PERIOD */
61210 /* XXX: coerce to regs? it might be better for enumeration use, where the
61211 * same PROP ivalue is used multiple times. Or perhaps coerce PROP further
61212 * there?
61213 */
61214 /* XXX: for simple cases like x['y'] an unnecessary LDREG is
61215 * emitted for the base value; could avoid it if we knew that
61216 * the key expression is safe (e.g. just a single literal).
61217 */
61218
61219 /* The 'left' value must not be a register bound variable
61220 * because it may be mutated during the rest of the expression
61221 * and E5.1 Section 11.2.1 specifies the order of evaluation
61222 * so that the base value is evaluated first.
61223 * See: test-bug-nested-prop-mutate.js.
61224 */
61225 duk__ivalue_totempconst(comp_ctx, left);
61226 duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, ']' terminates */
61228
61229 res->t = DUK_IVAL_PROP;
61230 duk__copy_ispec(comp_ctx, &res->x1, &res->x2); /* res.x1 -> res.x2 */
61231 duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
61232 return;
61233 }
61234 case DUK_TOK_LPAREN: {
61235 /* function call */
61236 duk_reg_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
61237 duk_int_t nargs;
61238 duk_small_uint_t call_flags = 0;
61239
61240 /*
61241 * XXX: attempt to get the call result to "next temp" whenever
61242 * possible to avoid unnecessary register shuffles.
61243 *
61244 * XXX: CSPROP (and CSREG) can overwrite the call target register, and save one temp,
61245 * if the call target is a temporary register and at the top of the temp reg "stack".
61246 */
61247
61248 /*
61249 * Setup call: target and 'this' binding. Three cases:
61250 *
61251 * 1. Identifier base (e.g. "foo()")
61252 * 2. Property base (e.g. "foo.bar()")
61253 * 3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
61254 */
61255
61256 if (left->t == DUK_IVAL_VAR) {
61257 duk_hstring *h_varname;
61258 duk_reg_t reg_varbind;
61259 duk_regconst_t rc_varname;
61260
61261 DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
61262
61263 h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
61264 DUK_ASSERT(h_varname != NULL);
61265 if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
61266 /* Potential direct eval call detected, flag the CALL
61267 * so that a run-time "direct eval" check is made and
61268 * special behavior may be triggered. Note that this
61269 * does not prevent 'eval' from being register bound.
61270 */
61271 DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
61272 "-> enabling EVALCALL flag, marking function "
61273 "as may_direct_eval"));
61274 call_flags |= DUK_BC_CALL_FLAG_EVALCALL;
61275
61276 comp_ctx->curr_func.may_direct_eval = 1;
61277 }
61278
61279 duk_dup(ctx, left->x1.valstack_idx);
61280 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61281 duk__emit_a_b(comp_ctx,
61283 (duk_regconst_t) (reg_cs + 0),
61284 (duk_regconst_t) reg_varbind);
61285 } else {
61286 duk__emit_a_b(comp_ctx,
61288 (duk_regconst_t) (reg_cs + 0),
61289 rc_varname);
61290 }
61291 } else if (left->t == DUK_IVAL_PROP) {
61292 DUK_DDD(DUK_DDDPRINT("function call with property base"));
61293
61294 duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 0); /* base */
61295 duk__ispec_toforcedreg(comp_ctx, &left->x2, reg_cs + 1); /* key */
61296 duk__emit_a_b_c(comp_ctx,
61298 (duk_regconst_t) (reg_cs + 0),
61299 (duk_regconst_t) (reg_cs + 0),
61300 (duk_regconst_t) (reg_cs + 1)); /* in-place setup */
61301 } else {
61302 DUK_DDD(DUK_DDDPRINT("function call with register base"));
61303
61304 duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
61305 duk__emit_a_b(comp_ctx,
61307 (duk_regconst_t) (reg_cs + 0),
61308 (duk_regconst_t) (reg_cs + 0)); /* in-place setup */
61309 }
61310
61311 DUK__SETTEMP(comp_ctx, reg_cs + 2);
61312 nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp" */
61313
61314 /* Tailcalls are handled by back-patching the TAILCALL flag to the
61315 * already emitted instruction later (in return statement parser).
61316 * Since A and C have a special meaning here, they cannot be "shuffled".
61317 */
61318
61319 duk__emit_a_b_c(comp_ctx,
61321 (duk_regconst_t) call_flags /*flags*/,
61322 (duk_regconst_t) reg_cs /*basereg*/,
61323 (duk_regconst_t) nargs /*numargs*/);
61324 DUK__SETTEMP(comp_ctx, reg_cs + 1); /* result in csreg */
61325
61326 res->t = DUK_IVAL_PLAIN;
61327 res->x1.t = DUK_ISPEC_REGCONST;
61328 res->x1.regconst = (duk_regconst_t) reg_cs;
61329 return;
61330 }
61331
61332 /* POSTFIX EXPRESSION */
61333
61334 case DUK_TOK_INCREMENT: {
61335 args = (DUK_OP_POSTINCR << 8) + 0;
61336 goto postincdec;
61337 }
61338 case DUK_TOK_DECREMENT: {
61339 args = (DUK_OP_POSTDECR << 8) + 0;
61340 goto postincdec;
61341 }
61342
61343 /* MULTIPLICATIVE EXPRESSION */
61344
61345 case DUK_TOK_MUL: {
61346 args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE; /* UnaryExpression */
61347 goto binary;
61348 }
61349 case DUK_TOK_DIV: {
61350 args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE; /* UnaryExpression */
61351 goto binary;
61352 }
61353 case DUK_TOK_MOD: {
61354 args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE; /* UnaryExpression */
61355 goto binary;
61356 }
61357
61358 /* ADDITIVE EXPRESSION */
61359
61360 case DUK_TOK_ADD: {
61361 args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
61362 goto binary;
61363 }
61364 case DUK_TOK_SUB: {
61365 args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
61366 goto binary;
61367 }
61368
61369 /* SHIFT EXPRESSION */
61370
61371 case DUK_TOK_ALSHIFT: {
61372 /* << */
61373 args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
61374 goto binary;
61375 }
61376 case DUK_TOK_ARSHIFT: {
61377 /* >> */
61378 args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
61379 goto binary;
61380 }
61381 case DUK_TOK_RSHIFT: {
61382 /* >>> */
61383 args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
61384 goto binary;
61385 }
61386
61387 /* RELATIONAL EXPRESSION */
61388
61389 case DUK_TOK_LT: {
61390 /* < */
61391 args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
61392 goto binary;
61393 }
61394 case DUK_TOK_GT: {
61395 args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
61396 goto binary;
61397 }
61398 case DUK_TOK_LE: {
61399 args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
61400 goto binary;
61401 }
61402 case DUK_TOK_GE: {
61403 args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
61404 goto binary;
61405 }
61406 case DUK_TOK_INSTANCEOF: {
61407 args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_INSTOF << 8) + DUK__BP_RELATIONAL;
61408 goto binary;
61409 }
61410 case DUK_TOK_IN: {
61411 args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_IN << 8) + DUK__BP_RELATIONAL;
61412 goto binary;
61413 }
61414
61415 /* EQUALITY EXPRESSION */
61416
61417 case DUK_TOK_EQ: {
61418 args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
61419 goto binary;
61420 }
61421 case DUK_TOK_NEQ: {
61422 args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
61423 goto binary;
61424 }
61425 case DUK_TOK_SEQ: {
61426 args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
61427 goto binary;
61428 }
61429 case DUK_TOK_SNEQ: {
61430 args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
61431 goto binary;
61432 }
61433
61434 /* BITWISE EXPRESSIONS */
61435
61436 case DUK_TOK_BAND: {
61437 args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
61438 goto binary;
61439 }
61440 case DUK_TOK_BXOR: {
61441 args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
61442 goto binary;
61443 }
61444 case DUK_TOK_BOR: {
61445 args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
61446 goto binary;
61447 }
61448
61449 /* LOGICAL EXPRESSIONS */
61450
61451 case DUK_TOK_LAND: {
61452 /* syntactically left-associative but parsed as right-associative */
61453 args = (1 << 8) + DUK__BP_LAND - 1;
61454 goto binary_logical;
61455 }
61456 case DUK_TOK_LOR: {
61457 /* syntactically left-associative but parsed as right-associative */
61458 args = (0 << 8) + DUK__BP_LOR - 1;
61459 goto binary_logical;
61460 }
61461
61462 /* CONDITIONAL EXPRESSION */
61463
61464 case DUK_TOK_QUESTION: {
61465 /* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
61466 * but only if it really is a temp. Nothing fancy here now.
61467 */
61468 duk_reg_t reg_temp;
61469 duk_int_t pc_jump1;
61470 duk_int_t pc_jump2;
61471
61472 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61473 duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
61474 duk__emit_if_true_skip(comp_ctx, reg_temp);
61475 pc_jump1 = duk__emit_jump_empty(comp_ctx); /* jump to false */
61476 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
61478 pc_jump2 = duk__emit_jump_empty(comp_ctx); /* jump to end */
61479 duk__patch_jump_here(comp_ctx, pc_jump1);
61480 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
61481 duk__patch_jump_here(comp_ctx, pc_jump2);
61482
61483 DUK__SETTEMP(comp_ctx, reg_temp + 1);
61484 res->t = DUK_IVAL_PLAIN;
61485 res->x1.t = DUK_ISPEC_REGCONST;
61486 res->x1.regconst = (duk_regconst_t) reg_temp;
61487 return;
61488 }
61489
61490 /* ASSIGNMENT EXPRESSION */
61491
61492 case DUK_TOK_EQUALSIGN: {
61493 /*
61494 * Assignments are right associative, allows e.g.
61495 * a = 5;
61496 * a += b = 9; // same as a += (b = 9)
61497 * -> expression value 14, a = 14, b = 9
61498 *
61499 * Right associativiness is reflected in the BP for recursion,
61500 * "-1" ensures assignment operations are allowed.
61501 *
61502 * XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
61503 */
61504 args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1; /* DUK_OP_NONE marks a 'plain' assignment */
61505 goto assign;
61506 }
61507 case DUK_TOK_ADD_EQ: {
61508 /* right associative */
61509 args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
61510 goto assign;
61511 }
61512 case DUK_TOK_SUB_EQ: {
61513 /* right associative */
61514 args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
61515 goto assign;
61516 }
61517 case DUK_TOK_MUL_EQ: {
61518 /* right associative */
61519 args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
61520 goto assign;
61521 }
61522 case DUK_TOK_DIV_EQ: {
61523 /* right associative */
61524 args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
61525 goto assign;
61526 }
61527 case DUK_TOK_MOD_EQ: {
61528 /* right associative */
61529 args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
61530 goto assign;
61531 }
61532 case DUK_TOK_ALSHIFT_EQ: {
61533 /* right associative */
61534 args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
61535 goto assign;
61536 }
61537 case DUK_TOK_ARSHIFT_EQ: {
61538 /* right associative */
61539 args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
61540 goto assign;
61541 }
61542 case DUK_TOK_RSHIFT_EQ: {
61543 /* right associative */
61544 args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
61545 goto assign;
61546 }
61547 case DUK_TOK_BAND_EQ: {
61548 /* right associative */
61549 args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
61550 goto assign;
61551 }
61552 case DUK_TOK_BOR_EQ: {
61553 /* right associative */
61554 args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
61555 goto assign;
61556 }
61557 case DUK_TOK_BXOR_EQ: {
61558 /* right associative */
61559 args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
61560 goto assign;
61561 }
61562
61563 /* COMMA */
61564
61565 case DUK_TOK_COMMA: {
61566 /* right associative */
61567
61568 duk__ivalue_toplain_ignore(comp_ctx, left); /* need side effects, not value */
61569 duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
61570
61571 /* return 'res' (of right part) as our result */
61572 return;
61573 }
61574
61575 default: {
61576 break;
61577 }
61578 }
61579
61580 DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
61582 return;
61583
61584#if 0
61585 /* XXX: shared handling for 'duk__expr_lhs'? */
61586 if (comp_ctx->curr_func.paren_level == 0 && XXX) {
61587 comp_ctx->curr_func.duk__expr_lhs = 0;
61588 }
61589#endif
61590
61591 binary:
61592 /*
61593 * Shared handling of binary operations
61594 *
61595 * args = (is_extraop << 16) + (opcode << 8) + rbp
61596 */
61597 {
61598 duk__ivalue_toplain(comp_ctx, left);
61599 duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
61600
61601 /* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
61603 DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
61604
61605 res->t = (args >> 16) ? DUK_IVAL_ARITH_EXTRAOP : DUK_IVAL_ARITH;
61606 res->op = (args >> 8) & 0xff;
61607
61608 res->x2.t = res->x1.t;
61609 res->x2.regconst = res->x1.regconst;
61610 duk_copy(ctx, res->x1.valstack_idx, res->x2.valstack_idx);
61611
61612 res->x1.t = left->x1.t;
61613 res->x1.regconst = left->x1.regconst;
61614 duk_copy(ctx, left->x1.valstack_idx, res->x1.valstack_idx);
61615
61616 DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
61617 (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
61618 return;
61619 }
61620
61621 binary_logical:
61622 /*
61623 * Shared handling for logical AND and logical OR.
61624 *
61625 * args = (truthval << 8) + rbp
61626 *
61627 * Truthval determines when to skip right-hand-side.
61628 * For logical AND truthval=1, for logical OR truthval=0.
61629 *
61630 * See doc/compiler.rst for discussion on compiling logical
61631 * AND and OR expressions. The approach here is very simplistic,
61632 * generating extra jumps and multiple evaluations of truth values,
61633 * but generates code on-the-fly with only local back-patching.
61634 *
61635 * Both logical AND and OR are syntactically left-associated.
61636 * However, logical ANDs are compiled as right associative
61637 * expressions, i.e. "A && B && C" as "A && (B && C)", to allow
61638 * skip jumps to skip over the entire tail. Similarly for logical OR.
61639 */
61640
61641 {
61642 duk_reg_t reg_temp;
61643 duk_int_t pc_jump;
61644 duk_small_uint_t args_truthval = args >> 8;
61645 duk_small_uint_t args_rbp = args & 0xff;
61646
61647 /* XXX: unoptimal use of temps, resetting */
61648
61649 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61650
61651 duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
61652 duk__emit_a_b(comp_ctx,
61654 (duk_regconst_t) args_truthval,
61655 (duk_regconst_t) reg_temp); /* skip jump conditionally */
61656 pc_jump = duk__emit_jump_empty(comp_ctx);
61657 duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
61658 duk__patch_jump_here(comp_ctx, pc_jump);
61659
61660 res->t = DUK_IVAL_PLAIN;
61661 res->x1.t = DUK_ISPEC_REGCONST;
61662 res->x1.regconst = (duk_regconst_t) reg_temp;
61663 return;
61664 }
61665
61666 assign:
61667 /*
61668 * Shared assignment expression handling
61669 *
61670 * args = (opcode << 8) + rbp
61671 *
61672 * If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
61673 * Syntactically valid left-hand-side forms which are not accepted as
61674 * left-hand-side values (e.g. as in "f() = 1") must NOT cause a
61675 * SyntaxError, but rather a run-time ReferenceError.
61676 *
61677 * When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
61678 * to a temporary first. The RHS is then evaluated. Finally, the
61679 * <op> is applied to the initial value of RHS (not the value after
61680 * RHS evaluation), and written to X. Doing so concretely generates
61681 * inefficient code so we'd like to avoid the temporary when possible.
61682 * See: https://github.com/svaarala/duktape/pull/992.
61683 *
61684 * The expression value (final LHS value, written to RHS) is
61685 * conceptually copied into a fresh temporary so that it won't
61686 * change even if the LHS/RHS values change in outer expressions.
61687 * For example, it'd be generally incorrect for the expression value
61688 * to be the RHS register binding, unless there's a guarantee that it
61689 * won't change during further expression evaluation. Using the
61690 * temporary concretely produces inefficient bytecode, so we try to
61691 * avoid the extra temporary for some known-to-be-safe cases.
61692 * Currently the only safe case we detect is a "top level assignment",
61693 * for example "x = y + z;", where the assignment expression value is
61694 * ignored.
61695 * See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
61696 */
61697
61698 {
61699 duk_small_uint_t args_op = args >> 8;
61700 duk_small_uint_t args_rbp = args & 0xff;
61701 duk_bool_t toplevel_assign;
61702
61703 /* XXX: here we need to know if 'left' is left-hand-side compatible.
61704 * That information is no longer available from current expr parsing
61705 * state; it would need to be carried into the 'left' ivalue or by
61706 * some other means.
61707 */
61708
61709 /* A top-level assignment is e.g. "x = y;". For these it's safe
61710 * to use the RHS as-is as the expression value, even if the RHS
61711 * is a reg-bound identifier. The RHS ('res') is right associative
61712 * so it has consumed all other assignment level operations; the
61713 * only relevant lower binding power construct is comma operator
61714 * which will ignore the expression value provided here. Usually
61715 * the top level assignment expression value is ignored, but it
61716 * is relevant for e.g. eval code.
61717 */
61718 toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
61719 comp_ctx->curr_func.led_count == 1); /* one operator (= assign) */
61720 DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
61721 (long) comp_ctx->curr_func.nud_count,
61722 (long) comp_ctx->curr_func.led_count,
61723 (long) toplevel_assign));
61724
61725 if (left->t == DUK_IVAL_VAR) {
61726 duk_hstring *h_varname;
61727 duk_reg_t reg_varbind;
61728 duk_regconst_t rc_varname;
61729
61730 DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE); /* LHS is already side effect free */
61731
61732 h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
61733 DUK_ASSERT(h_varname != NULL);
61734 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
61735 /* E5 Section 11.13.1 (and others for other assignments), step 4. */
61736 goto syntax_error_lvalue;
61737 }
61738 duk_dup(ctx, left->x1.valstack_idx);
61739 (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
61740
61741 if (args_op == DUK_OP_NONE) {
61742 duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
61743 if (toplevel_assign) {
61744 /* Any 'res' will do. */
61745 DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
61746 } else {
61747 /* 'res' must be a plain ivalue, and not register-bound variable. */
61748 DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
61749 if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
61750 (res->x1.regconst & DUK__CONST_MARKER) == 0 &&
61751 !DUK__ISTEMP(comp_ctx, res->x1.regconst))) {
61752 duk__ivalue_totempconst(comp_ctx, res);
61753 }
61754 }
61755 } else {
61756 /* For X <op>= Y we need to evaluate the pre-op
61757 * value of X before evaluating the RHS: the RHS
61758 * can change X, but when we do <op> we must use
61759 * the pre-op value.
61760 */
61761 duk_reg_t reg_temp;
61762
61763 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61764
61765 if (reg_varbind >= 0) {
61766 duk_reg_t reg_res;
61767 duk_reg_t reg_src;
61768 duk_int_t pc_temp_load;
61769 duk_int_t pc_before_rhs;
61770 duk_int_t pc_after_rhs;
61771
61772 if (toplevel_assign) {
61773 /* 'reg_varbind' is the operation result and can also
61774 * become the expression value for top level assignments
61775 * such as: "var x; x += y;".
61776 */
61777 DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
61778 reg_res = reg_varbind;
61779 } else {
61780 /* Not safe to use 'reg_varbind' as assignment expression
61781 * value, so go through a temp.
61782 */
61783 DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
61784 reg_res = reg_temp; /* reg_res should be smallest possible */
61785 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61786 }
61787
61788 /* Try to optimize X <op>= Y for reg-bound
61789 * variables. Detect side-effect free RHS
61790 * narrowly by seeing whether it emits code.
61791 * If not, rewind the code emitter and overwrite
61792 * the unnecessary temp reg load.
61793 */
61794
61795 pc_temp_load = duk__get_current_pc(comp_ctx);
61796 duk__emit_a_bc(comp_ctx,
61798 (duk_regconst_t) reg_temp,
61799 reg_varbind);
61800
61801 pc_before_rhs = duk__get_current_pc(comp_ctx);
61802 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
61803 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61804 pc_after_rhs = duk__get_current_pc(comp_ctx);
61805
61806 DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
61807 (long) pc_temp_load, (long) pc_before_rhs,
61808 (long) pc_after_rhs));
61809
61810 if (pc_after_rhs == pc_before_rhs) {
61811 /* Note: if the reg_temp load generated shuffling
61812 * instructions, we may need to rewind more than
61813 * one instruction, so use explicit PC computation.
61814 */
61815 DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
61816 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (pc_temp_load - pc_before_rhs) * sizeof(duk_compiler_instr));
61817 reg_src = reg_varbind;
61818 } else {
61819 DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
61820 reg_src = reg_temp;
61821 }
61822
61823 duk__emit_a_b_c(comp_ctx,
61824 args_op,
61825 (duk_regconst_t) reg_res,
61826 (duk_regconst_t) reg_src,
61827 res->x1.regconst);
61828
61829 res->x1.regconst = (duk_regconst_t) reg_res;
61830
61831 /* Ensure compact use of temps. */
61832 if (DUK__ISTEMP(comp_ctx, reg_res)) {
61833 DUK__SETTEMP(comp_ctx, reg_res + 1);
61834 }
61835 } else {
61836 /* When LHS is not register bound, always go through a
61837 * temporary. No optimization for top level assignment.
61838 */
61839
61840 duk__emit_a_bc(comp_ctx,
61842 (duk_regconst_t) reg_temp,
61843 rc_varname);
61844
61845 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
61846 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61847
61848 duk__emit_a_b_c(comp_ctx,
61849 args_op,
61850 (duk_regconst_t) reg_temp,
61851 (duk_regconst_t) reg_temp,
61852 res->x1.regconst);
61853 res->x1.regconst = (duk_regconst_t) reg_temp;
61854 }
61855
61856 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61857 }
61858
61859 /* At this point 'res' holds the potential expression value.
61860 * It can be basically any ivalue here, including a reg-bound
61861 * identifier (if code above deems it safe) or a unary/binary
61862 * operation. Operations must be resolved to a side effect free
61863 * plain value, and the side effects must happen exactly once.
61864 */
61865
61866 if (reg_varbind >= 0) {
61867 if (res->t != DUK_IVAL_PLAIN) {
61868 /* Resolve 'res' directly into the LHS binding, and use
61869 * that as the expression value if safe. If not safe,
61870 * resolve to a temp/const and copy to LHS.
61871 */
61872 if (toplevel_assign) {
61873 duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
61874 } else {
61875 duk__ivalue_totempconst(comp_ctx, res);
61876 duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
61877 duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
61878 }
61879 } else {
61880 /* Use 'res' as the expression value (it's side effect
61881 * free and may be a plain value, a register, or a
61882 * constant) and write it to the LHS binding too.
61883 */
61884 duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
61885 duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
61886 }
61887 } else {
61888 /* Only a reg fits into 'A' so coerce 'res' into a register
61889 * for PUTVAR.
61890 *
61891 * XXX: here the current A/B/C split is suboptimal: we could
61892 * just use 9 bits for reg_res (and support constants) and 17
61893 * instead of 18 bits for the varname const index.
61894 */
61895
61896 duk__ivalue_toreg(comp_ctx, res);
61897 duk__emit_a_bc(comp_ctx,
61899 res->x1.regconst,
61900 rc_varname);
61901 }
61902
61903 /* 'res' contains expression value */
61904 } else if (left->t == DUK_IVAL_PROP) {
61905 /* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
61906 duk_reg_t reg_obj;
61907 duk_regconst_t rc_key;
61908 duk_regconst_t rc_res;
61909 duk_reg_t reg_temp;
61910
61911 /* Property access expressions ('a[b]') are critical to correct
61912 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
61913 * We must make sure that the LHS target slot (base object and
61914 * key) don't change during RHS evaluation. The only concrete
61915 * problem is a register reference to a variable-bound register
61916 * (i.e., non-temp). Require temp regs for both key and base.
61917 *
61918 * Don't allow a constant for the object (even for a number
61919 * etc), as it goes into the 'A' field of the opcode.
61920 */
61921
61922 reg_obj = duk__ispec_toregconst_raw(comp_ctx,
61923 &left->x1,
61924 -1 /*forced_reg*/,
61925 DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
61926
61927 rc_key = duk__ispec_toregconst_raw(comp_ctx,
61928 &left->x2,
61929 -1 /*forced_reg*/,
61931
61932 /* Evaluate RHS only when LHS is safe. */
61933
61934 if (args_op == DUK_OP_NONE) {
61935 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
61936 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61937 rc_res = res->x1.regconst;
61938 } else {
61939 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61940 duk__emit_a_b_c(comp_ctx,
61942 (duk_regconst_t) reg_temp,
61943 (duk_regconst_t) reg_obj,
61944 rc_key);
61945
61946 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
61947 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61948
61949 duk__emit_a_b_c(comp_ctx,
61950 args_op,
61951 (duk_regconst_t) reg_temp,
61952 (duk_regconst_t) reg_temp,
61953 res->x1.regconst);
61954 rc_res = (duk_regconst_t) reg_temp;
61955 }
61956
61957 duk__emit_a_b_c(comp_ctx,
61959 (duk_regconst_t) reg_obj,
61960 rc_key,
61961 rc_res);
61962
61963 res->t = DUK_IVAL_PLAIN;
61964 res->x1.t = DUK_ISPEC_REGCONST;
61965 res->x1.regconst = rc_res;
61966 } else {
61967 /* No support for lvalues returned from new or function call expressions.
61968 * However, these must NOT cause compile-time SyntaxErrors, but run-time
61969 * ReferenceErrors. Both left and right sides of the assignment must be
61970 * evaluated before throwing a ReferenceError. For instance:
61971 *
61972 * f() = g();
61973 *
61974 * must result in f() being evaluated, then g() being evaluated, and
61975 * finally, a ReferenceError being thrown. See E5 Section 11.13.1.
61976 */
61977
61978 duk_regconst_t rc_res;
61979
61980 /* First evaluate LHS fully to ensure all side effects are out. */
61982
61983 /* Then evaluate RHS fully (its value becomes the expression value too).
61984 * Technically we'd need the side effect safety check here too, but because
61985 * we always throw using INVLHS the result doesn't matter.
61986 */
61987 rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
61988
61989 duk__emit_extraop_only(comp_ctx,
61991
61992 res->t = DUK_IVAL_PLAIN;
61993 res->x1.t = DUK_ISPEC_REGCONST;
61994 res->x1.regconst = rc_res;
61995 }
61996
61997 return;
61998 }
61999
62000 postincdec:
62001 {
62002 /*
62003 * Post-increment/decrement will return the original value as its
62004 * result value. However, even that value will be coerced using
62005 * ToNumber() which is quite awkward. Specific bytecode opcodes
62006 * are used to handle these semantics.
62007 *
62008 * Note that post increment/decrement has a "no LineTerminator here"
62009 * restriction. This is handled by duk__expr_lbp(), which forcibly terminates
62010 * the previous expression if a LineTerminator occurs before '++'/'--'.
62011 */
62012
62013 duk_reg_t reg_res;
62014 duk_small_uint_t args_op = args >> 8;
62015
62016 /* Specific assumptions for opcode numbering. */
62021
62022 reg_res = DUK__ALLOCTEMP(comp_ctx);
62023
62024 if (left->t == DUK_IVAL_VAR) {
62025 duk_hstring *h_varname;
62026 duk_reg_t reg_varbind;
62027 duk_regconst_t rc_varname;
62028
62029 h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
62030 DUK_ASSERT(h_varname != NULL);
62031
62032 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
62033 goto syntax_error;
62034 }
62035
62036 duk_dup(ctx, left->x1.valstack_idx);
62037 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
62038 duk__emit_a_bc(comp_ctx,
62039 args_op, /* e.g. DUK_OP_POSTINCR */
62040 (duk_regconst_t) reg_res,
62041 (duk_regconst_t) reg_varbind);
62042 } else {
62043 duk__emit_a_bc(comp_ctx,
62044 args_op + 4, /* e.g. DUK_OP_POSTINCV */
62045 (duk_regconst_t) reg_res,
62046 rc_varname);
62047 }
62048
62049 DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
62050 (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
62051 } else if (left->t == DUK_IVAL_PROP) {
62052 duk_reg_t reg_obj; /* allocate to reg only (not const) */
62053 duk_regconst_t rc_key;
62054
62055 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
62056 rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62057 duk__emit_a_b_c(comp_ctx,
62058 args_op + 8, /* e.g. DUK_OP_POSTINCP */
62059 (duk_regconst_t) reg_res,
62060 (duk_regconst_t) reg_obj,
62061 rc_key);
62062 } else {
62063 /* Technically return value is not needed because INVLHS will
62064 * unconditially throw a ReferenceError. Coercion is necessary
62065 * for proper semantics (consider ToNumber() called for an object).
62066 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
62067 */
62068 duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
62069 duk__emit_extraop_bc(comp_ctx,
62071 reg_res); /* for side effects, result ignored */
62072 duk__emit_extraop_only(comp_ctx,
62074 }
62076 res->t = DUK_IVAL_PLAIN;
62077 res->x1.t = DUK_ISPEC_REGCONST;
62078 res->x1.regconst = (duk_regconst_t) reg_res;
62079 DUK__SETTEMP(comp_ctx, reg_res + 1);
62080 return;
62081 }
62082
62083 syntax_error:
62085 return;
62086
62087 syntax_error_lvalue:
62089 return;
62090}
62091
62093 duk_small_int_t tok = comp_ctx->curr_token.t;
62094
62095 DUK_ASSERT(tok >= DUK_TOK_MINVAL && tok <= DUK_TOK_MAXVAL);
62097
62098 /* XXX: integrate support for this into led() instead?
62099 * Similar issue as post-increment/post-decrement.
62100 */
62101
62102 /* prevent duk__expr_led() by using a binding power less than anything valid */
62103 if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
62104 return 0;
62105 }
62106
62107 if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
62108 (comp_ctx->curr_token.lineterm)) {
62109 /* '++' or '--' in a post-increment/decrement position,
62110 * and a LineTerminator occurs between the operator and
62111 * the preceding expression. Force the previous expr
62112 * to terminate, in effect treating e.g. "a,b\n++" as
62113 * "a,b;++" (= SyntaxError).
62115 return 0;
62117
62118 return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]); /* format is bit packed */
62120
62121/*
62122 * Expression parsing.
62123 *
62124 * Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
62125 * first token of the expression. Upon exit, 'curr_tok' will be the first
62126 * token not part of the expression (e.g. semicolon terminating an expression
62127 * statement).
62128 */
62129
62130#define DUK__EXPR_RBP_MASK 0xff
62131#define DUK__EXPR_FLAG_REJECT_IN (1 << 8) /* reject 'in' token (used for for-in) */
62132#define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9) /* allow empty expression */
62133#define DUK__EXPR_FLAG_REQUIRE_INIT (1 << 10) /* require initializer for var/const */
62134
62135/* main expression parser function */
62136DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62137 duk_hthread *thr = comp_ctx->thr;
62138 duk_context *ctx = (duk_context *) thr;
62139 duk_ivalue tmp_alloc; /* 'res' is used for "left", and 'tmp' for "right" */
62140 duk_ivalue *tmp = &tmp_alloc;
62141 duk_small_uint_t rbp;
62142
62143 DUK__RECURSION_INCREASE(comp_ctx, thr);
62144
62146
62147 /* filter out flags from exprtop rbp_flags here to save space */
62148 rbp = rbp_flags & DUK__EXPR_RBP_MASK;
62149
62150 DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
62151 (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
62152 (long) comp_ctx->curr_func.paren_level));
62153
62154 DUK_MEMZERO(&tmp_alloc, sizeof(tmp_alloc));
62155 tmp->x1.valstack_idx = duk_get_top(ctx);
62156 tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
62157 duk_push_undefined(ctx);
62158 duk_push_undefined(ctx);
62159
62160 /* XXX: where to release temp regs in intermediate expressions?
62161 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
62162 * that particular expression temp regs can be forced here.
62163 */
62164
62165 /* XXX: increase ctx->expr_tokens here for every consumed token
62166 * (this would be a nice statistic)?
62167 */
62168
62169 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
62170 /* XXX: possibly incorrect handling of empty expression */
62171 DUK_DDD(DUK_DDDPRINT("empty expression"));
62172 if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
62174 }
62175 res->t = DUK_IVAL_PLAIN;
62176 res->x1.t = DUK_ISPEC_VALUE;
62177 duk_push_undefined(ctx);
62178 duk_replace(ctx, res->x1.valstack_idx);
62179 goto cleanup;
62180 }
62182 duk__advance(comp_ctx);
62183 duk__expr_nud(comp_ctx, res); /* reuse 'res' as 'left' */
62184 while (rbp < duk__expr_lbp(comp_ctx)) {
62185 duk__advance(comp_ctx);
62186 duk__expr_led(comp_ctx, res, tmp);
62187 duk__copy_ivalue(comp_ctx, tmp, res); /* tmp -> res */
62188 }
62189
62190 cleanup:
62191 /* final result is already in 'res' */
62192
62193 duk_pop_2(ctx);
62194
62195 DUK__RECURSION_DECREASE(comp_ctx, thr);
62196}
62197
62198DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62199 duk_hthread *thr = comp_ctx->thr;
62200
62201 /* Note: these variables must reside in 'curr_func' instead of the global
62202 * context: when parsing function expressions, expression parsing is nested.
62203 */
62204 comp_ctx->curr_func.nud_count = 0;
62205 comp_ctx->curr_func.led_count = 0;
62206 comp_ctx->curr_func.paren_level = 0;
62207 comp_ctx->curr_func.expr_lhs = 1;
62208 comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
62209
62210 duk__expr(comp_ctx, res, rbp_flags);
62211
62212 if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
62214 }
62215}
62216
62217/* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
62218 * and result conversions.
62219 *
62220 * Each helper needs at least 2-3 calls to make it worth while to wrap.
62221 */
62222
62223#if 0 /* unused */
62224DUK_LOCAL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62225 duk__expr(comp_ctx, res, rbp_flags);
62226 return duk__ivalue_toreg(comp_ctx, res);
62227}
62228#endif
62229
62230#if 0 /* unused */
62231DUK_LOCAL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62232 duk__expr(comp_ctx, res, rbp_flags);
62233 return duk__ivalue_totemp(comp_ctx, res);
62234}
62235#endif
62236
62237DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
62238 DUK_ASSERT(forced_reg >= 0);
62239 duk__expr(comp_ctx, res, rbp_flags);
62240 duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
62241}
62242
62244 duk__expr(comp_ctx, res, rbp_flags);
62245 return duk__ivalue_toregconst(comp_ctx, res);
62246}
62247
62248#if 0 /* unused */
62249DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62250 duk__expr(comp_ctx, res, rbp_flags);
62251 return duk__ivalue_totempconst(comp_ctx, res);
62252}
62253#endif
62254
62256 duk__expr(comp_ctx, res, rbp_flags);
62257 duk__ivalue_toplain(comp_ctx, res);
62258}
62259
62261 duk__expr(comp_ctx, res, rbp_flags);
62262 duk__ivalue_toplain_ignore(comp_ctx, res);
62263}
62264
62266 duk__exprtop(comp_ctx, res, rbp_flags);
62267 return duk__ivalue_toreg(comp_ctx, res);
62268}
62269
62270#if 0 /* unused */
62271DUK_LOCAL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62272 duk__exprtop(comp_ctx, res, rbp_flags);
62273 return duk__ivalue_totemp(comp_ctx, res);
62274}
62275#endif
62276
62277DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
62278 DUK_ASSERT(forced_reg >= 0);
62279 duk__exprtop(comp_ctx, res, rbp_flags);
62280 duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
62281}
62282
62284 duk__exprtop(comp_ctx, res, rbp_flags);
62285 return duk__ivalue_toregconst(comp_ctx, res);
62286}
62287
62288#if 0 /* unused */
62289DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
62290 duk__exprtop(comp_ctx, res, rbp_flags);
62291 duk__ivalue_toplain_ignore(comp_ctx, res);
62292}
62293#endif
62294
62295/*
62296 * Parse an individual source element (top level statement) or a statement.
62297 *
62298 * Handles labeled statements automatically (peeling away labels before
62299 * parsing an expression that follows the label(s)).
62300 *
62301 * Upon entry, 'curr_tok' contains the first token of the statement (parsed
62302 * in "allow regexp literal" mode). Upon exit, 'curr_tok' contains the first
62303 * token following the statement (if the statement has a terminator, this is
62304 * the token after the terminator).
62305 */
62307#ifdef DUK__HAS_VAL
62308#undef DUK__HAS_VAL
62309#endif
62310#ifdef DUK__HAS_TERM
62311#undef DUK__HAS_TERM
62312#endif
62313#ifdef DUK__ALLOW_AUTO_SEMI_ALWAYS
62314#undef DUK__ALLOW_AUTO_SEMI_ALWAYS
62315#endif
62316#ifdef DUK__STILL_PROLOGUE
62317#undef DUK__STILL_PROLOGUE
62318#endif
62319#ifdef DUK__IS_TERMINAL
62320#undef DUK__IS_TERMINAL
62321#endif
62322
62323#define DUK__HAS_VAL (1 << 0) /* stmt has non-empty value */
62324#define DUK__HAS_TERM (1 << 1) /* stmt has explicit/implicit semicolon terminator */
62325#define DUK__ALLOW_AUTO_SEMI_ALWAYS (1 << 2) /* allow automatic semicolon even without lineterm (compatibility) */
62326#define DUK__STILL_PROLOGUE (1 << 3) /* statement does not terminate directive prologue */
62327#define DUK__IS_TERMINAL (1 << 4) /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
62328
62329/* Parse a single variable declaration (e.g. "i" or "i=10"). A leading 'var'
62330 * has already been eaten. These is no return value in 'res', it is used only
62331 * as a temporary.
62332 *
62333 * When called from 'for-in' statement parser, the initializer expression must
62334 * not allow the 'in' token. The caller supply additional expression parsing
62335 * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
62336 *
62337 * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
62338 * the identifier is bound:
62339 *
62340 * If register bound: out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
62341 * If not register bound: out_reg_varbind < 0, out_rc_varname >= 0
62342 *
62343 * These allow the caller to use the variable for further assignment, e.g.
62344 * as is done in 'for-in' parsing.
62345 */
62346
62347DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
62348 duk_hthread *thr = comp_ctx->thr;
62349 duk_context *ctx = (duk_context *) thr;
62350 duk_hstring *h_varname;
62351 duk_reg_t reg_varbind;
62352 duk_regconst_t rc_varname;
62353
62354 /* assume 'var' has been eaten */
62355
62356 /* Note: Identifier rejects reserved words */
62357 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
62358 goto syntax_error;
62359 }
62360 h_varname = comp_ctx->curr_token.str1;
62361
62362 DUK_ASSERT(h_varname != NULL);
62363
62364 /* strict mode restrictions (E5 Section 12.2.1) */
62365 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
62366 goto syntax_error;
62367 }
62368
62369 /* register declarations in first pass */
62370 if (comp_ctx->curr_func.in_scanning) {
62371 duk_uarridx_t n;
62372 DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
62373 (duk_heaphdr *) h_varname));
62374 n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
62375 duk_push_hstring(ctx, h_varname);
62376 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
62377 duk_push_int(ctx, DUK_DECL_TYPE_VAR + (0 << 8));
62378 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
62379 }
62380
62381 duk_push_hstring(ctx, h_varname); /* push before advancing to keep reachable */
62382
62383 /* register binding lookup is based on varmap (even in first pass) */
62384 duk_dup_top(ctx);
62385 (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
62386
62387 duk__advance(comp_ctx); /* eat identifier */
62388
62389 if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
62390 duk__advance(comp_ctx);
62391
62392 DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
62393 (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
62394
62395 duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/); /* AssignmentExpression */
62396
62397 if (reg_varbind >= 0) {
62398 duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
62399 } else {
62400 duk_reg_t reg_val;
62401 reg_val = duk__ivalue_toreg(comp_ctx, res);
62402 duk__emit_a_bc(comp_ctx,
62404 (duk_regconst_t) reg_val,
62405 rc_varname);
62406 }
62407 } else {
62409 /* Used for minimal 'const': initializer required. */
62410 goto syntax_error;
62411 }
62412 }
62413
62414 duk_pop(ctx); /* pop varname */
62415
62416 *out_rc_varname = rc_varname;
62417 *out_reg_varbind = reg_varbind;
62418
62419 return;
62420
62421 syntax_error:
62423}
62424
62426 duk_reg_t reg_varbind;
62427 duk_regconst_t rc_varname;
62428
62429 duk__advance(comp_ctx); /* eat 'var' */
62430
62431 for (;;) {
62432 /* rc_varname and reg_varbind are ignored here */
62433 duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
62434
62435 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
62436 break;
62437 }
62438 duk__advance(comp_ctx);
62439 }
62440}
62441
62442DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
62443 duk_hthread *thr = comp_ctx->thr;
62444 duk_context *ctx = (duk_context *) thr;
62445 duk_int_t pc_v34_lhs; /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
62446 duk_reg_t temp_reset; /* knock back "next temp" to this whenever possible */
62447 duk_reg_t reg_temps; /* preallocated temporaries (2) for variants 3 and 4 */
62448
62449 DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
62450
62451 /* Two temporaries are preallocated here for variants 3 and 4 which need
62452 * registers which are never clobbered by expressions in the loop
62453 * (concretely: for the enumerator object and the next enumerated value).
62454 * Variants 1 and 2 "release" these temps.
62455 */
62456
62457 reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
62458
62459 temp_reset = DUK__GETTEMP(comp_ctx);
62460
62461 /*
62462 * For/for-in main variants are:
62463 *
62464 * 1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
62465 * 2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
62466 * 3. for (LeftHandSideExpression in Expression) Statement
62467 * 4. for (var VariableDeclarationNoIn in Expression) Statement
62468 *
62469 * Parsing these without arbitrary lookahead or backtracking is relatively
62470 * tricky but we manage to do so for now.
62471 *
62472 * See doc/compiler.rst for a detailed discussion of control flow
62473 * issues, evaluation order issues, etc.
62474 */
62475
62476 duk__advance(comp_ctx); /* eat 'for' */
62478
62479 DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
62480
62481 /* a label site has been emitted by duk__parse_stmt() automatically
62482 * (it will also emit the ENDLABEL).
62483 */
62484
62485 if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
62486 /*
62487 * Variant 2 or 4
62488 */
62489
62490 duk_reg_t reg_varbind; /* variable binding register if register-bound (otherwise < 0) */
62491 duk_regconst_t rc_varname; /* variable name reg/const, if variable not register-bound */
62492
62493 duk__advance(comp_ctx); /* eat 'var' */
62494 duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
62495 DUK__SETTEMP(comp_ctx, temp_reset);
62496
62497 if (comp_ctx->curr_token.t == DUK_TOK_IN) {
62498 /*
62499 * Variant 4
62500 */
62501
62502 DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
62503 pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here */
62504 if (reg_varbind >= 0) {
62505 duk__emit_a_bc(comp_ctx,
62507 (duk_regconst_t) reg_varbind,
62508 (duk_regconst_t) (reg_temps + 0));
62509 } else {
62510 duk__emit_a_bc(comp_ctx,
62512 (duk_regconst_t) (reg_temps + 0),
62513 rc_varname);
62514 }
62515 goto parse_3_or_4;
62516 } else {
62517 /*
62518 * Variant 2
62519 */
62520
62521 DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
62522 for (;;) {
62523 /* more initializers */
62524 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
62525 break;
62526 }
62527 DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
62528
62529 duk__advance(comp_ctx); /* eat comma */
62530 duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
62531 }
62532 goto parse_1_or_2;
62533 }
62534 } else {
62535 /*
62536 * Variant 1 or 3
62537 */
62538
62539 pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here (variant 3) */
62540
62541 /* Note that duk__exprtop() here can clobber any reg above current temp_next,
62542 * so any loop variables (e.g. enumerator) must be "preallocated".
62543 */
62544
62545 /* don't coerce yet to a plain value (variant 3 needs special handling) */
62546 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression */
62547 if (comp_ctx->curr_token.t == DUK_TOK_IN) {
62548 /*
62549 * Variant 3
62550 */
62551
62552 /* XXX: need to determine LHS type, and check that it is LHS compatible */
62553 DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
62554 if (duk__expr_is_empty(comp_ctx)) {
62555 goto syntax_error; /* LeftHandSideExpression does not allow empty expression */
62556 }
62557
62558 if (res->t == DUK_IVAL_VAR) {
62559 duk_reg_t reg_varbind;
62560 duk_regconst_t rc_varname;
62561
62562 duk_dup(ctx, res->x1.valstack_idx);
62563 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
62564 duk__emit_a_bc(comp_ctx,
62566 (duk_regconst_t) reg_varbind,
62567 (duk_regconst_t) (reg_temps + 0));
62568 } else {
62569 duk__emit_a_bc(comp_ctx,
62571 (duk_regconst_t) (reg_temps + 0),
62572 rc_varname);
62573 }
62574 } else if (res->t == DUK_IVAL_PROP) {
62575 /* Don't allow a constant for the object (even for a number etc), as
62576 * it goes into the 'A' field of the opcode.
62577 */
62578 duk_reg_t reg_obj;
62579 duk_regconst_t rc_key;
62580 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
62581 rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62582 duk__emit_a_b_c(comp_ctx,
62584 (duk_regconst_t) reg_obj,
62585 rc_key,
62586 (duk_regconst_t) (reg_temps + 0));
62587 } else {
62588 duk__ivalue_toplain_ignore(comp_ctx, res); /* just in case */
62589 duk__emit_extraop_only(comp_ctx,
62591 }
62592 goto parse_3_or_4;
62593 } else {
62594 /*
62595 * Variant 1
62596 */
62597
62598 DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
62599 duk__ivalue_toplain_ignore(comp_ctx, res);
62600 goto parse_1_or_2;
62601 }
62602 }
62603
62604 parse_1_or_2:
62605 /*
62606 * Parse variant 1 or 2. The first part expression (which differs
62607 * in the variants) has already been parsed and its code emitted.
62608 *
62609 * reg_temps + 0: unused
62610 * reg_temps + 1: unused
62611 */
62612 {
62613 duk_regconst_t rc_cond;
62614 duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
62615 duk_int_t pc_jumpto_l3, pc_jumpto_l4;
62616 duk_bool_t expr_c_empty;
62617
62618 DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
62619
62620 /* "release" preallocated temps since we won't need them */
62621 temp_reset = reg_temps + 0;
62622 DUK__SETTEMP(comp_ctx, temp_reset);
62623
62625
62626 pc_l1 = duk__get_current_pc(comp_ctx);
62627 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
62628 if (duk__expr_is_empty(comp_ctx)) {
62629 /* no need to coerce */
62630 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
62631 pc_jumpto_l4 = -1; /* omitted */
62632 } else {
62633 rc_cond = duk__ivalue_toregconst(comp_ctx, res);
62634 duk__emit_if_false_skip(comp_ctx, rc_cond);
62635 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
62636 pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx); /* to exit */
62637 }
62638 DUK__SETTEMP(comp_ctx, temp_reset);
62639
62641
62642 pc_l2 = duk__get_current_pc(comp_ctx);
62643 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
62644 if (duk__expr_is_empty(comp_ctx)) {
62645 /* no need to coerce */
62646 expr_c_empty = 1;
62647 /* JUMP L1 omitted */
62648 } else {
62649 duk__ivalue_toplain_ignore(comp_ctx, res);
62650 expr_c_empty = 0;
62651 duk__emit_jump(comp_ctx, pc_l1);
62652 }
62653 DUK__SETTEMP(comp_ctx, temp_reset);
62654
62656
62657 pc_l3 = duk__get_current_pc(comp_ctx);
62658 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
62659 if (expr_c_empty) {
62660 duk__emit_jump(comp_ctx, pc_l1);
62661 } else {
62662 duk__emit_jump(comp_ctx, pc_l2);
62663 }
62664 /* temp reset is not necessary after duk__parse_stmt(), which already does it */
62665
62666 pc_l4 = duk__get_current_pc(comp_ctx);
62667
62668 DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
62669 "break: %ld->%ld, continue: %ld->%ld",
62670 (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
62671 (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
62672
62673 duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
62674 duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
62675 duk__patch_jump(comp_ctx,
62676 pc_label_site + 1,
62677 pc_l4); /* break jump */
62678 duk__patch_jump(comp_ctx,
62679 pc_label_site + 2,
62680 expr_c_empty ? pc_l1 : pc_l2); /* continue jump */
62681 }
62682 goto finished;
62683
62684 parse_3_or_4:
62685 /*
62686 * Parse variant 3 or 4.
62687 *
62688 * For variant 3 (e.g. "for (A in C) D;") the code for A (except the
62689 * final property/variable write) has already been emitted. The first
62690 * instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
62691 * there to satisfy control flow needs.
62692 *
62693 * For variant 4, if the variable declaration had an initializer
62694 * (e.g. "for (var A = B in C) D;") the code for the assignment
62695 * (B) has already been emitted.
62696 *
62697 * Variables set before entering here:
62698 *
62699 * pc_v34_lhs: insert a "JUMP L2" here (see doc/compiler.rst example).
62700 * reg_temps + 0: iteration target value (written to LHS)
62701 * reg_temps + 1: enumerator object
62702 */
62703 {
62704 duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
62705 duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
62706 duk_reg_t reg_target;
62707
62708 DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
62709
62710 DUK__SETTEMP(comp_ctx, temp_reset);
62711
62712 /* First we need to insert a jump in the middle of previously
62713 * emitted code to get the control flow right. No jumps can
62714 * cross the position where the jump is inserted. See doc/compiler.rst
62715 * for discussion on the intricacies of control flow and side effects
62716 * for variants 3 and 4.
62717 */
62718
62719 duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
62720 pc_jumpto_l2 = pc_v34_lhs; /* inserted jump */
62721 pc_l1 = pc_v34_lhs + 1; /* +1, right after inserted jump */
62722
62723 /* The code for writing reg_temps + 0 to the left hand side has already
62724 * been emitted.
62725 */
62726
62727 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* -> loop body */
62728
62729 duk__advance(comp_ctx); /* eat 'in' */
62730
62731 /* Parse enumeration target and initialize enumerator. For 'null' and 'undefined',
62732 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
62733 * (E5 Section 12.6.4, step 3). Note that INITENUM requires the value to be in a
62734 * register (constant not allowed).
62735 */
62736
62737 pc_l2 = duk__get_current_pc(comp_ctx);
62738 reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression */
62739 duk__emit_extraop_b_c(comp_ctx,
62741 (duk_regconst_t) (reg_temps + 1),
62742 (duk_regconst_t) reg_target);
62743 pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
62744 DUK__SETTEMP(comp_ctx, temp_reset);
62745
62747
62748 pc_l3 = duk__get_current_pc(comp_ctx);
62749 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
62750 /* temp reset is not necessary after duk__parse_stmt(), which already does it */
62751
62752 /* NEXTENUM needs a jump slot right after the main opcode.
62753 * We need the code emitter to reserve the slot: if there's
62754 * target shuffling, the target shuffle opcodes must happen
62755 * after the jump slot (for NEXTENUM the shuffle opcodes are
62756 * not needed if the enum is finished).
62757 */
62758 pc_l4 = duk__get_current_pc(comp_ctx);
62759 duk__emit_extraop_b_c(comp_ctx,
62761 (duk_regconst_t) (reg_temps + 0),
62762 (duk_regconst_t) (reg_temps + 1));
62763 pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc; /* NEXTENUM jump slot: executed when enum finished */
62764 duk__emit_jump(comp_ctx, pc_l1); /* jump to next loop, using reg_v34_iter as iterated value */
62765
62766 pc_l5 = duk__get_current_pc(comp_ctx);
62767
62768 /* XXX: since the enumerator may be a memory expensive object,
62769 * perhaps clear it explicitly here? If so, break jump must
62770 * go through this clearing operation.
62771 */
62772
62773 DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
62774 "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
62775 "break: %ld->%ld, continue: %ld->%ld",
62776 (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
62777 (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
62778 (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
62779
62780 duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
62781 duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
62782 duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
62783 duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
62784 duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5); /* break jump */
62785 duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4); /* continue jump */
62786 }
62787 goto finished;
62788
62789 finished:
62790 DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
62791 return;
62792
62793 syntax_error:
62795}
62796
62797DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
62798 duk_hthread *thr = comp_ctx->thr;
62799 duk_reg_t temp_at_loop;
62800 duk_regconst_t rc_switch; /* reg/const for switch value */
62801 duk_regconst_t rc_case; /* reg/const for case value */
62802 duk_reg_t reg_temp; /* general temp register */
62803 duk_int_t pc_prevcase = -1;
62804 duk_int_t pc_prevstmt = -1;
62805 duk_int_t pc_default = -1; /* -1 == not set, -2 == pending (next statement list) */
62806
62807 /* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
62808
62809 /*
62810 * Switch is pretty complicated because of several conflicting concerns:
62811 *
62812 * - Want to generate code without an intermediate representation,
62813 * i.e., in one go
62814 *
62815 * - Case selectors are expressions, not values, and may thus e.g. throw
62816 * exceptions (which causes evaluation order concerns)
62817 *
62818 * - Evaluation semantics of case selectors and default clause need to be
62819 * carefully implemented to provide correct behavior even with case value
62820 * side effects
62821 *
62822 * - Fall through case and default clauses; avoiding dead JUMPs if case
62823 * ends with an unconditional jump (a break or a continue)
62824 *
62825 * - The same case value may occur multiple times, but evaluation rules
62826 * only process the first match before switching to a "propagation" mode
62827 * where case values are no longer evaluated
62828 *
62829 * See E5 Section 12.11. Also see doc/compiler.rst for compilation
62830 * discussion.
62831 */
62832
62833 duk__advance(comp_ctx);
62835 rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
62838
62839 DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
62840
62841 temp_at_loop = DUK__GETTEMP(comp_ctx);
62842
62843 for (;;) {
62844 duk_int_t num_stmts;
62845 duk_small_int_t tok;
62846
62847 /* sufficient for keeping temp reg numbers in check */
62848 DUK__SETTEMP(comp_ctx, temp_at_loop);
62849
62850 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
62851 break;
62852 }
62853
62854 /*
62855 * Parse a case or default clause.
62856 */
62857
62858 if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
62859 /*
62860 * Case clause.
62861 *
62862 * Note: cannot use reg_case as a temp register (for SEQ target)
62863 * because it may be a constant.
62864 */
62865
62866 duk__patch_jump_here(comp_ctx, pc_prevcase); /* chain jumps for case
62867 * evaluation and checking
62868 */
62869
62870 duk__advance(comp_ctx);
62871 rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
62873
62874 reg_temp = DUK__ALLOCTEMP(comp_ctx);
62875 duk__emit_a_b_c(comp_ctx,
62876 DUK_OP_SEQ,
62877 (duk_regconst_t) reg_temp,
62878 rc_switch,
62879 rc_case);
62880 duk__emit_if_true_skip(comp_ctx, (duk_regconst_t) reg_temp);
62881
62882 /* jump to next case clause */
62883 pc_prevcase = duk__emit_jump_empty(comp_ctx); /* no match, next case */
62884
62885 /* statements go here (if any) on next loop */
62886 } else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
62887 /*
62888 * Default clause.
62889 */
62890
62891 if (pc_default >= 0) {
62892 goto syntax_error;
62893 }
62894 duk__advance(comp_ctx);
62896
62897 /* Fix for https://github.com/svaarala/duktape/issues/155:
62898 * If 'default' is first clause (detected by pc_prevcase < 0)
62899 * we need to ensure we stay in the matching chain.
62900 */
62901 if (pc_prevcase < 0) {
62902 DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
62903 pc_prevcase = duk__emit_jump_empty(comp_ctx);
62904 }
62905
62906 /* default clause matches next statement list (if any) */
62907 pc_default = -2;
62908 } else {
62909 /* Code is not accepted before the first case/default clause */
62910 goto syntax_error;
62911 }
62912
62913 /*
62914 * Parse code after the clause. Possible terminators are
62915 * 'case', 'default', and '}'.
62916 *
62917 * Note that there may be no code at all, not even an empty statement,
62918 * between case clauses. This must be handled just like an empty statement
62919 * (omitting seemingly pointless JUMPs), to avoid situations like
62920 * test-bug-case-fallthrough.js.
62921 */
62922
62923 num_stmts = 0;
62924 if (pc_default == -2) {
62925 pc_default = duk__get_current_pc(comp_ctx);
62926 }
62927
62928 /* Note: this is correct even for default clause statements:
62929 * they participate in 'fall-through' behavior even if the
62930 * default clause is in the middle.
62931 */
62932 duk__patch_jump_here(comp_ctx, pc_prevstmt); /* chain jumps for 'fall-through'
62933 * after a case matches.
62934 */
62935
62936 for (;;) {
62937 tok = comp_ctx->curr_token.t;
62938 if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
62939 tok == DUK_TOK_RCURLY) {
62940 break;
62941 }
62942 num_stmts++;
62943 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
62944 }
62945
62946 /* fall-through jump to next code of next case (backpatched) */
62947 pc_prevstmt = duk__emit_jump_empty(comp_ctx);
62948
62949 /* XXX: would be nice to omit this jump when the jump is not
62950 * reachable, at least in the obvious cases (such as the case
62951 * ending with a 'break'.
62952 *
62953 * Perhaps duk__parse_stmt() could provide some info on whether
62954 * the statement is a "dead end"?
62955 *
62956 * If implemented, just set pc_prevstmt to -1 when not needed.
62957 */
62958 }
62959
62960 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
62961 duk__advance(comp_ctx);
62962
62963 /* default case control flow patchup; note that if pc_prevcase < 0
62964 * (i.e. no case clauses), control enters default case automatically.
62965 */
62966 if (pc_default >= 0) {
62967 /* default case exists: go there if no case matches */
62968 duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
62969 } else {
62970 /* default case does not exist, or no statements present
62971 * after default case: finish case evaluation
62972 */
62973 duk__patch_jump_here(comp_ctx, pc_prevcase);
62974 }
62975
62976 /* fall-through control flow patchup; note that pc_prevstmt may be
62977 * < 0 (i.e. no case clauses), in which case this is a no-op.
62978 */
62979 duk__patch_jump_here(comp_ctx, pc_prevstmt);
62980
62981 /* continue jump not patched, an INVALID opcode remains there */
62982 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
62983
62984 /* Note: 'fast' breaks will jump to pc_label_site + 1, which will
62985 * then jump here. The double jump will be eliminated by a
62986 * peephole pass, resulting in an optimal jump here. The label
62987 * site jumps will remain in bytecode and will waste code size.
62988 */
62989
62990 return;
62991
62992 syntax_error:
62994}
62995
62997 duk_reg_t temp_reset;
62998 duk_regconst_t rc_cond;
62999 duk_int_t pc_jump_false;
63000
63001 DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
63002
63003 temp_reset = DUK__GETTEMP(comp_ctx);
63004
63005 duk__advance(comp_ctx); /* eat 'if' */
63007
63008 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63009 duk__emit_if_true_skip(comp_ctx, rc_cond);
63010 pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */
63011 DUK__SETTEMP(comp_ctx, temp_reset);
63012
63014
63015 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63016
63017 /* The 'else' ambiguity is resolved by 'else' binding to the innermost
63018 * construct, so greedy matching is correct here.
63019 */
63020
63021 if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
63022 duk_int_t pc_jump_end;
63023
63024 DUK_DDD(DUK_DDDPRINT("if has else part"));
63025
63026 duk__advance(comp_ctx);
63027
63028 pc_jump_end = duk__emit_jump_empty(comp_ctx); /* jump from true part to end */
63029 duk__patch_jump_here(comp_ctx, pc_jump_false);
63030
63031 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63032
63033 duk__patch_jump_here(comp_ctx, pc_jump_end);
63034 } else {
63035 DUK_DDD(DUK_DDDPRINT("if does not have else part"));
63036
63037 duk__patch_jump_here(comp_ctx, pc_jump_false);
63038 }
63039
63040 DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
63041}
63042
63043DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
63044 duk_regconst_t rc_cond;
63045 duk_int_t pc_start;
63046
63047 DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
63048
63049 duk__advance(comp_ctx); /* eat 'do' */
63050
63051 pc_start = duk__get_current_pc(comp_ctx);
63052 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63053 duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
63054
63057
63058 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63059 duk__emit_if_false_skip(comp_ctx, rc_cond);
63060 duk__emit_jump(comp_ctx, pc_start);
63061 /* no need to reset temps, as we're finished emitting code */
63062
63064
63065 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
63066
63067 DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
63068}
63069
63070DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
63071 duk_reg_t temp_reset;
63072 duk_regconst_t rc_cond;
63073 duk_int_t pc_start;
63074 duk_int_t pc_jump_false;
63075
63076 DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
63077
63078 temp_reset = DUK__GETTEMP(comp_ctx);
63079
63080 duk__advance(comp_ctx); /* eat 'while' */
63081
63083
63084 pc_start = duk__get_current_pc(comp_ctx);
63085 duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
63087 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63088 duk__emit_if_true_skip(comp_ctx, rc_cond);
63089 pc_jump_false = duk__emit_jump_empty(comp_ctx);
63090 DUK__SETTEMP(comp_ctx, temp_reset);
63091
63093
63094 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63095 duk__emit_jump(comp_ctx, pc_start);
63096
63097 duk__patch_jump_here(comp_ctx, pc_jump_false);
63098 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
63099
63100 DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
63101}
63102
63104 duk_hthread *thr = comp_ctx->thr;
63105 duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
63106 duk_int_t label_id;
63107 duk_int_t label_catch_depth;
63108 duk_int_t label_pc; /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
63109 duk_bool_t label_is_closest;
63110
63111 DUK_UNREF(res);
63112
63113 duk__advance(comp_ctx); /* eat 'break' or 'continue' */
63114
63115 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
63116 comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
63117 comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
63118 /* break/continue without label */
63119
63120 duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
63121 } else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
63122 /* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
63123 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
63124 duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
63125 duk__advance(comp_ctx);
63126 } else {
63128 }
63129
63130 /* Use a fast break/continue when possible. A fast break/continue is
63131 * just a jump to the LABEL break/continue jump slot, which then jumps
63132 * to an appropriate place (for break, going through ENDLABEL correctly).
63133 * The peephole optimizer will optimize the jump to a direct one.
63134 */
63135
63136 if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
63137 label_is_closest) {
63138 DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
63139 "label_catch_depth=%ld, catch_depth=%ld "
63140 "-> use fast variant (direct jump)",
63141 (long) is_break, (long) label_id, (long) label_is_closest,
63142 (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
63143
63144 duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
63145 } else {
63146 DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
63147 "label_catch_depth=%ld, catch_depth=%ld "
63148 "-> use slow variant (longjmp)",
63149 (long) is_break, (long) label_id, (long) label_is_closest,
63150 (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
63151
63152 duk__emit_extraop_bc(comp_ctx,
63154 (duk_regconst_t) label_id);
63155 }
63156}
63157
63159 duk_hthread *thr = comp_ctx->thr;
63160 duk_regconst_t rc_val;
63161 duk_small_uint_t ret_flags;
63162
63163 duk__advance(comp_ctx); /* eat 'return' */
63164
63165 /* A 'return' statement is only allowed inside an actual function body,
63166 * not as part of eval or global code.
63167 */
63168 if (!comp_ctx->curr_func.is_function) {
63170 }
63171
63172 ret_flags = 0;
63173
63174 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
63175 comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
63176 comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
63177 DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
63178 rc_val = 0;
63179 } else {
63180 duk_int_t pc_before_expr;
63181 duk_int_t pc_after_expr;
63182
63183 DUK_DDD(DUK_DDDPRINT("return with a value"));
63184
63185 DUK_UNREF(pc_before_expr);
63186 DUK_UNREF(pc_after_expr);
63187
63188 pc_before_expr = duk__get_current_pc(comp_ctx);
63189 rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63190 pc_after_expr = duk__get_current_pc(comp_ctx);
63191
63192 /* Tail call check: if last opcode emitted was CALL(I), and
63193 * the context allows it, change the CALL(I) to a tail call.
63194 * This doesn't guarantee that a tail call will be allowed at
63195 * runtime, so the RETURN must still be emitted. (Duktape
63196 * 0.10.0 avoided this and simulated a RETURN if a tail call
63197 * couldn't be used at runtime; but this didn't work
63198 * correctly with a thread yield/resume, see
63199 * test-bug-tailcall-thread-yield-resume.js for discussion.)
63200 *
63201 * In addition to the last opcode being CALL, we also need to
63202 * be sure that 'rc_val' is the result register of the CALL(I).
63203 * For instance, for the expression 'return 0, (function ()
63204 * { return 1; }), 2' the last opcode emitted is CALL (no
63205 * bytecode is emitted for '2') but 'rc_val' indicates
63206 * constant '2'. Similarly if '2' is replaced by a register
63207 * bound variable, no opcodes are emitted but tail call would
63208 * be incorrect.
63209 *
63210 * This is tricky and easy to get wrong. It would be best to
63211 * track enough expression metadata to check that 'rc_val' came
63212 * from that last CALL instruction. We don't have that metadata
63213 * now, so we check that 'rc_val' is a temporary register result
63214 * (not a constant or a register bound variable). There should
63215 * be no way currently for 'rc_val' to be a temporary for an
63216 * expression following the CALL instruction without emitting
63217 * some opcodes following the CALL. This proxy check is used
63218 * below.
63219 *
63220 * See: test-bug-comma-expr-gh131.js.
63221 *
63222 * The non-standard 'caller' property disables tail calls
63223 * because they pose some special cases which haven't been
63224 * fixed yet.
63225 */
63226
63227#if defined(DUK_USE_TAILCALL)
63228 if (comp_ctx->curr_func.catch_depth == 0 && /* no catchers */
63229 pc_after_expr > pc_before_expr) { /* at least one opcode emitted */
63230 duk_compiler_instr *instr;
63232
63233 instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
63234 DUK_ASSERT(instr != NULL);
63235
63236 op = (duk_small_uint_t) DUK_DEC_OP(instr->ins);
63237 if ((op == DUK_OP_CALL || op == DUK_OP_CALLI) &&
63238 DUK__ISTEMP(comp_ctx, rc_val) /* see above */) {
63239 DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
63240 "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
63241 "and last instruction is a CALL "
63242 "-> set TAILCALL flag"));
63243 /* Just flip the single bit. */
63245 }
63246 }
63247#endif /* DUK_USE_TAILCALL */
63248
63250 }
63251
63252 duk__emit_a_b(comp_ctx,
63254 (duk_regconst_t) ret_flags /*flags*/,
63255 rc_val /*reg*/);
63256}
63257
63259 duk_reg_t reg_val;
63260
63261 duk__advance(comp_ctx); /* eat 'throw' */
63262
63263 /* Unlike break/continue, throw statement does not allow an empty value. */
63264
63265 if (comp_ctx->curr_token.lineterm) {
63267 }
63268
63269 reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63270 duk__emit_extraop_bc(comp_ctx,
63272 (duk_regconst_t) reg_val);
63273}
63274
63276 duk_hthread *thr = comp_ctx->thr;
63277 duk_context *ctx = (duk_context *) thr;
63278 duk_reg_t reg_catch; /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
63279 duk_regconst_t rc_varname = 0;
63280 duk_small_uint_t trycatch_flags = 0;
63281 duk_int_t pc_ldconst = -1;
63282 duk_int_t pc_trycatch = -1;
63283 duk_int_t pc_catch = -1;
63284 duk_int_t pc_finally = -1;
63285
63286 DUK_UNREF(res);
63287
63288 /*
63289 * See the following documentation for discussion:
63290 *
63291 * doc/execution.rst: control flow details
63292 *
63293 * Try, catch, and finally "parts" are Blocks, not Statements, so
63294 * they must always be delimited by curly braces. This is unlike e.g.
63295 * the if statement, which accepts any Statement. This eliminates any
63296 * questions of matching parts of nested try statements. The Block
63297 * parsing is implemented inline here (instead of calling out).
63298 *
63299 * Finally part has a 'let scoped' variable, which requires a few kinks
63300 * here.
63301 */
63302
63303 comp_ctx->curr_func.catch_depth++;
63304
63305 duk__advance(comp_ctx); /* eat 'try' */
63306
63307 reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
63308
63309 /* The target for this LDCONST may need output shuffling, but we assume
63310 * that 'pc_ldconst' will be the LDCONST that we can patch later. This
63311 * should be the case because there's no input shuffling. (If there's
63312 * no catch clause, this LDCONST will be replaced with a NOP.)
63313 */
63314 pc_ldconst = duk__get_current_pc(comp_ctx);
63315 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
63316
63317 pc_trycatch = duk__get_current_pc(comp_ctx);
63318 duk__emit_invalid(comp_ctx); /* TRYCATCH, cannot emit now (not enough info) */
63319 duk__emit_invalid(comp_ctx); /* jump for 'catch' case */
63320 duk__emit_invalid(comp_ctx); /* jump for 'finally' case or end (if no finally) */
63321
63322 /* try part */
63324 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63325 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63326 duk__emit_extraop_only(comp_ctx,
63328
63329 if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
63330 /*
63331 * The catch variable must be updated to reflect the new allocated
63332 * register for the duration of the catch clause. We need to store
63333 * and restore the original value for the varmap entry (if any).
63334 */
63335
63336 /*
63337 * Note: currently register bindings must be fixed for the entire
63338 * function. So, even though the catch variable is in a register
63339 * we know, we must use an explicit environment record and slow path
63340 * accesses to read/write the catch binding to make closures created
63341 * within the catch clause work correctly. This restriction should
63342 * be fixable (at least in common cases) later.
63343 *
63344 * See: test-bug-catch-binding-2.js.
63345 *
63346 * XXX: improve to get fast path access to most catch clauses.
63347 */
63348
63349 duk_hstring *h_var;
63350 duk_int_t varmap_value; /* for storing/restoring the varmap binding for catch variable */
63351
63352 DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(ctx)));
63353
63354 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
63355
63356 pc_catch = duk__get_current_pc(comp_ctx);
63357
63358 duk__advance(comp_ctx);
63360
63361 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
63362 /* Identifier, i.e. don't allow reserved words */
63363 goto syntax_error;
63364 }
63365 h_var = comp_ctx->curr_token.str1;
63366 DUK_ASSERT(h_var != NULL);
63367
63368 duk_push_hstring(ctx, h_var); /* keep in on valstack, use borrowed ref below */
63369
63370 if (comp_ctx->curr_func.is_strict &&
63371 ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
63372 (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
63373 DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
63374 goto syntax_error;
63375 }
63376
63377 duk_dup_top(ctx);
63378 rc_varname = duk__getconst(comp_ctx);
63379 DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
63380 (unsigned long) rc_varname, (long) rc_varname));
63381
63382 duk__advance(comp_ctx);
63384
63386
63387 DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
63388 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63389
63390 duk_dup_top(ctx);
63391 duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
63392 if (duk_is_undefined(ctx, -1)) {
63393 varmap_value = -2;
63394 } else if (duk_is_null(ctx, -1)) {
63395 varmap_value = -1;
63396 } else {
63397 DUK_ASSERT(duk_is_number(ctx, -1));
63398 varmap_value = duk_get_int(ctx, -1);
63399 DUK_ASSERT(varmap_value >= 0);
63400 }
63401 duk_pop(ctx);
63402
63403#if 0
63404 /* It'd be nice to do something like this - but it doesn't
63405 * work for closures created inside the catch clause.
63406 */
63407 duk_dup_top(ctx);
63408 duk_push_int(ctx, (duk_int_t) (reg_catch + 0));
63409 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63410#endif
63411 duk_dup_top(ctx);
63412 duk_push_null(ctx);
63413 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63414
63415 duk__emit_a_bc(comp_ctx,
63417 (duk_regconst_t) (reg_catch + 0) /*value*/,
63418 rc_varname /*varname*/);
63419
63420 DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
63421 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63422
63423 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63424 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63425
63426 if (varmap_value == -2) {
63427 /* not present */
63428 duk_del_prop(ctx, comp_ctx->curr_func.varmap_idx);
63429 } else {
63430 if (varmap_value == -1) {
63431 duk_push_null(ctx);
63432 } else {
63433 DUK_ASSERT(varmap_value >= 0);
63434 duk_push_int(ctx, varmap_value);
63435 }
63436 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63437 }
63438 /* varname is popped by above code */
63439
63440 DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
63441 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63442
63443 duk__emit_extraop_only(comp_ctx,
63445
63446 /*
63447 * XXX: for now, indicate that an expensive catch binding
63448 * declarative environment is always needed. If we don't
63449 * need it, we don't need the const_varname either.
63450 */
63451
63452 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
63453
63454 DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(ctx)));
63455 }
63456
63457 if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
63458 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
63459
63460 pc_finally = duk__get_current_pc(comp_ctx);
63461
63462 duk__advance(comp_ctx);
63463
63465 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63466 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63467 duk__emit_extraop_b(comp_ctx,
63469 reg_catch); /* rethrow */
63470 }
63471
63472 if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
63473 !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
63474 /* must have catch and/or finally */
63475 goto syntax_error;
63476 }
63477
63478 /* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
63479 * will replace the LDCONST with a NOP. For any actual constant (including
63480 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
63481 */
63482
63483 duk__patch_trycatch(comp_ctx,
63484 pc_ldconst,
63485 pc_trycatch,
63486 reg_catch,
63487 rc_varname,
63488 trycatch_flags);
63489
63490 if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
63491 DUK_ASSERT(pc_catch >= 0);
63492 duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
63494
63495 if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
63496 DUK_ASSERT(pc_finally >= 0);
63497 duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
63498 } else {
63499 /* without finally, the second jump slot is used to jump to end of stmt */
63500 duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
63501 }
63502
63503 comp_ctx->curr_func.catch_depth--;
63504 return;
63505
63506 syntax_error:
63508}
63509
63511 duk_int_t pc_trycatch;
63512 duk_int_t pc_finished;
63513 duk_reg_t reg_catch;
63514 duk_small_uint_t trycatch_flags;
63515
63516 if (comp_ctx->curr_func.is_strict) {
63518 }
63519
63520 comp_ctx->curr_func.catch_depth++;
63521
63522 duk__advance(comp_ctx); /* eat 'with' */
63523
63524 reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
63525
63527 duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
63529
63530 pc_trycatch = duk__get_current_pc(comp_ctx);
63531 trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
63532 duk__emit_a_bc(comp_ctx,
63534 (duk_regconst_t) trycatch_flags /*a*/,
63535 (duk_regconst_t) reg_catch /*bc*/);
63536 duk__emit_invalid(comp_ctx); /* catch jump */
63537 duk__emit_invalid(comp_ctx); /* finished jump */
63538
63539 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63540 duk__emit_extraop_only(comp_ctx,
63542
63543 pc_finished = duk__get_current_pc(comp_ctx);
63544
63545 duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
63546
63547 comp_ctx->curr_func.catch_depth--;
63548}
63549
63551 /* if a site already exists, nop: max one label site per statement */
63552 if (label_id >= 0) {
63553 return label_id;
63554 }
63555
63556 label_id = comp_ctx->curr_func.label_next++;
63557 DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
63558
63559 duk__emit_extraop_bc(comp_ctx,
63561 (duk_regconst_t) label_id);
63562 duk__emit_invalid(comp_ctx);
63563 duk__emit_invalid(comp_ctx);
63564
63565 return label_id;
63566}
63567
63568/* Parse a single statement.
63569 *
63570 * Creates a label site (with an empty label) automatically for iteration
63571 * statements. Also "peels off" any label statements for explicit labels.
63572 */
63573DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
63574 duk_hthread *thr = comp_ctx->thr;
63575 duk_context *ctx = (duk_context *) thr;
63576 duk_bool_t dir_prol_at_entry; /* directive prologue status at entry */
63577 duk_reg_t temp_at_entry;
63578 duk_uarridx_t labels_len_at_entry;
63579 duk_int_t pc_at_entry; /* assumed to also be PC of "LABEL" */
63580 duk_int_t stmt_id;
63581 duk_small_uint_t stmt_flags = 0;
63582 duk_int_t label_id = -1;
63583 duk_small_uint_t tok;
63584
63585 DUK__RECURSION_INCREASE(comp_ctx, thr);
63586
63587 temp_at_entry = DUK__GETTEMP(comp_ctx);
63588 pc_at_entry = duk__get_current_pc(comp_ctx);
63589 labels_len_at_entry = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.labelnames_idx);
63590 stmt_id = comp_ctx->curr_func.stmt_next++;
63591 dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
63592
63593 DUK_UNREF(stmt_id);
63594
63595 DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
63596 "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
63597 (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
63598 (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
63599 (long) comp_ctx->curr_func.catch_depth));
63600
63601 /* The directive prologue flag is cleared by default so that it is
63602 * unset for any recursive statement parsing. It is only "revived"
63603 * if a directive is detected. (We could also make directives only
63604 * allowed if 'allow_source_elem' was true.)
63605 */
63606 comp_ctx->curr_func.in_directive_prologue = 0;
63607
63608 retry_parse:
63609
63610 DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
63611 (long) stmt_id, (long) label_id, (long) allow_source_elem,
63612 (long) comp_ctx->curr_func.catch_depth));
63613
63614 /*
63615 * Detect iteration statements; if encountered, establish an
63616 * empty label.
63617 */
63618
63619 tok = comp_ctx->curr_token.t;
63620 if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
63621 tok == DUK_TOK_SWITCH) {
63622 DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
63623
63624 label_id = duk__stmt_label_site(comp_ctx, label_id);
63625 duk__add_label(comp_ctx,
63627 pc_at_entry /*pc_label*/,
63628 label_id);
63629 }
63630
63631 /*
63632 * Main switch for statement / source element type.
63633 */
63634
63635 switch (comp_ctx->curr_token.t) {
63636 case DUK_TOK_FUNCTION: {
63637 /*
63638 * Function declaration, function expression, or (non-standard)
63639 * function statement.
63640 *
63641 * The E5 specification only allows function declarations at
63642 * the top level (in "source elements"). An ExpressionStatement
63643 * is explicitly not allowed to begin with a "function" keyword
63644 * (E5 Section 12.4). Hence any non-error semantics for such
63645 * non-top-level statements are non-standard. Duktape semantics
63646 * for function statements are modelled after V8, see
63647 * test-dev-func-decl-outside-top.js.
63648 */
63649
63650#if defined(DUK_USE_NONSTD_FUNC_STMT)
63651 /* Lenient: allow function declarations outside top level in
63652 * non-strict mode but reject them in strict mode.
63653 */
63654 if (allow_source_elem || !comp_ctx->curr_func.is_strict)
63655#else /* DUK_USE_NONSTD_FUNC_STMT */
63656 /* Strict: never allow function declarations outside top level. */
63657 if (allow_source_elem)
63658#endif /* DUK_USE_NONSTD_FUNC_STMT */
63659 {
63660 /* FunctionDeclaration: not strictly a statement but handled as such.
63661 *
63662 * O(depth^2) parse count for inner functions is handled by recording a
63663 * lexer offset on the first compilation pass, so that the function can
63664 * be efficiently skipped on the second pass. This is encapsulated into
63665 * duk__parse_func_like_fnum().
63666 */
63667
63668 duk_int_t fnum;
63669
63670 DUK_DDD(DUK_DDDPRINT("function declaration statement"));
63671
63672 duk__advance(comp_ctx); /* eat 'function' */
63673 fnum = duk__parse_func_like_fnum(comp_ctx, 1 /*is_decl*/, 0 /*is_setget*/);
63674
63675 if (comp_ctx->curr_func.in_scanning) {
63676 duk_uarridx_t n;
63677 duk_hstring *h_funcname;
63678
63679 duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, fnum * 3);
63680 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME); /* -> [ ... func name ] */
63681 h_funcname = duk_get_hstring(ctx, -1);
63682 DUK_ASSERT(h_funcname != NULL);
63683
63684 DUK_DDD(DUK_DDDPRINT("register function declaration %!O in pass 1, fnum %ld",
63685 (duk_heaphdr *) h_funcname, (long) fnum));
63686 n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
63687 duk_push_hstring(ctx, h_funcname);
63688 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
63689 duk_push_int(ctx, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
63690 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
63691
63692 duk_pop_n(ctx, 2);
63693 }
63694
63695 /* no statement value (unlike function expression) */
63696 stmt_flags = 0;
63697 break;
63698 } else {
63700 }
63701 break;
63702 }
63703 case DUK_TOK_LCURLY: {
63704 DUK_DDD(DUK_DDDPRINT("block statement"));
63705 duk__advance(comp_ctx);
63706 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63707 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63708 if (label_id >= 0) {
63709 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
63710 }
63711 stmt_flags = 0;
63712 break;
63713 }
63714 case DUK_TOK_CONST: {
63715 DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
63716 duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
63717 stmt_flags = DUK__HAS_TERM;
63718 break;
63719 }
63720 case DUK_TOK_VAR: {
63721 DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
63722 duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
63723 stmt_flags = DUK__HAS_TERM;
63724 break;
63725 }
63726 case DUK_TOK_SEMICOLON: {
63727 /* empty statement with an explicit semicolon */
63728 DUK_DDD(DUK_DDDPRINT("empty statement"));
63729 stmt_flags = DUK__HAS_TERM;
63730 break;
63731 }
63732 case DUK_TOK_IF: {
63733 DUK_DDD(DUK_DDDPRINT("if statement"));
63734 duk__parse_if_stmt(comp_ctx, res);
63735 if (label_id >= 0) {
63736 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
63737 }
63738 stmt_flags = 0;
63739 break;
63740 }
63741 case DUK_TOK_DO: {
63742 /*
63743 * Do-while statement is mostly trivial, but there is special
63744 * handling for automatic semicolon handling (triggered by the
63745 * DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
63746 *
63747 * https://bugs.ecmascript.org/show_bug.cgi?id=8
63748 *
63749 * See doc/compiler.rst for details.
63750 */
63751 DUK_DDD(DUK_DDDPRINT("do statement"));
63752 DUK_ASSERT(label_id >= 0);
63753 duk__update_label_flags(comp_ctx,
63754 label_id,
63756 duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
63757 stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS; /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
63758 break;
63759 }
63760 case DUK_TOK_WHILE: {
63761 DUK_DDD(DUK_DDDPRINT("while statement"));
63762 DUK_ASSERT(label_id >= 0);
63763 duk__update_label_flags(comp_ctx,
63764 label_id,
63766 duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
63767 stmt_flags = 0;
63768 break;
63769 }
63770 case DUK_TOK_FOR: {
63771 /*
63772 * For/for-in statement is complicated to parse because
63773 * determining the statement type (three-part for vs. a
63774 * for-in) requires potential backtracking.
63775 *
63776 * See the helper for the messy stuff.
63777 */
63778 DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
63779 DUK_ASSERT(label_id >= 0);
63780 duk__update_label_flags(comp_ctx,
63781 label_id,
63783 duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
63784 stmt_flags = 0;
63785 break;
63786 }
63787 case DUK_TOK_CONTINUE:
63788 case DUK_TOK_BREAK: {
63789 DUK_DDD(DUK_DDDPRINT("break/continue statement"));
63790 duk__parse_break_or_continue_stmt(comp_ctx, res);
63791 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
63792 break;
63793 }
63794 case DUK_TOK_RETURN: {
63795 DUK_DDD(DUK_DDDPRINT("return statement"));
63796 duk__parse_return_stmt(comp_ctx, res);
63797 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
63798 break;
63799 }
63800 case DUK_TOK_WITH: {
63801 DUK_DDD(DUK_DDDPRINT("with statement"));
63802 comp_ctx->curr_func.with_depth++;
63803 duk__parse_with_stmt(comp_ctx, res);
63804 if (label_id >= 0) {
63805 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
63806 }
63807 comp_ctx->curr_func.with_depth--;
63808 stmt_flags = 0;
63809 break;
63810 }
63811 case DUK_TOK_SWITCH: {
63812 /*
63813 * The switch statement is pretty messy to compile.
63814 * See the helper for details.
63815 */
63816 DUK_DDD(DUK_DDDPRINT("switch statement"));
63817 DUK_ASSERT(label_id >= 0);
63818 duk__update_label_flags(comp_ctx,
63819 label_id,
63820 DUK_LABEL_FLAG_ALLOW_BREAK); /* don't allow continue */
63821 duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
63822 stmt_flags = 0;
63823 break;
63824 }
63825 case DUK_TOK_THROW: {
63826 DUK_DDD(DUK_DDDPRINT("throw statement"));
63827 duk__parse_throw_stmt(comp_ctx, res);
63828 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
63829 break;
63830 }
63831 case DUK_TOK_TRY: {
63832 DUK_DDD(DUK_DDDPRINT("try statement"));
63833 duk__parse_try_stmt(comp_ctx, res);
63834 stmt_flags = 0;
63835 break;
63836 }
63837 case DUK_TOK_DEBUGGER: {
63838 duk__advance(comp_ctx);
63839#if defined(DUK_USE_DEBUGGER_SUPPORT)
63840 DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
63842#else
63843 DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
63844#endif
63845 stmt_flags = DUK__HAS_TERM;
63846 break;
63847 }
63848 default: {
63849 /*
63850 * Else, must be one of:
63851 * - ExpressionStatement, possibly a directive (String)
63852 * - LabelledStatement (Identifier followed by ':')
63853 *
63854 * Expressions beginning with 'function' keyword are covered by a case
63855 * above (such expressions are not allowed in standard E5 anyway).
63856 * Also expressions starting with '{' are interpreted as block
63857 * statements. See E5 Section 12.4.
63858 *
63859 * Directive detection is tricky; see E5 Section 14.1 on directive
63860 * prologue. A directive is an expression statement with a single
63861 * string literal and an explicit or automatic semicolon. Escape
63862 * characters are significant and no parens etc are allowed:
63863 *
63864 * 'use strict'; // valid 'use strict' directive
63865 * 'use\u0020strict'; // valid directive, not a 'use strict' directive
63866 * ('use strict'); // not a valid directive
63867 *
63868 * The expression is determined to consist of a single string literal
63869 * based on duk__expr_nud() and duk__expr_led() call counts. The string literal
63870 * of a 'use strict' directive is determined to lack any escapes based
63871 * num_escapes count from the lexer. Note that other directives may be
63872 * allowed to contain escapes, so a directive with escapes does not
63873 * terminate a directive prologue.
63874 *
63875 * We rely on the fact that the expression parser will not emit any
63876 * code for a single token expression. However, it will generate an
63877 * intermediate value which we will then successfully ignore.
63878 *
63879 * A similar approach is used for labels.
63880 */
63881
63882 duk_bool_t single_token;
63883
63884 DUK_DDD(DUK_DDDPRINT("expression statement"));
63885 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63886
63887 single_token = (comp_ctx->curr_func.nud_count == 1 && /* one token */
63888 comp_ctx->curr_func.led_count == 0); /* no operators */
63889
63890 if (single_token &&
63891 comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
63892 comp_ctx->curr_token.t == DUK_TOK_COLON) {
63893 /*
63894 * Detected label
63895 */
63896
63897 duk_hstring *h_lab;
63898
63899 /* expected ival */
63900 DUK_ASSERT(res->t == DUK_IVAL_VAR);
63901 DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
63903 h_lab = comp_ctx->prev_token.str1;
63904 DUK_ASSERT(h_lab != NULL);
63905
63906 DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
63907 (duk_heaphdr *) h_lab));
63908
63909 duk__advance(comp_ctx); /* eat colon */
63910
63911 label_id = duk__stmt_label_site(comp_ctx, label_id);
63912
63913 duk__add_label(comp_ctx,
63914 h_lab,
63915 pc_at_entry /*pc_label*/,
63916 label_id);
63917
63918 /* a statement following a label cannot be a source element
63919 * (a function declaration).
63920 */
63921 allow_source_elem = 0;
63922
63923 DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
63924 goto retry_parse;
63925 }
63926
63927 stmt_flags = 0;
63928
63929 if (dir_prol_at_entry && /* still in prologue */
63930 single_token && /* single string token */
63931 comp_ctx->prev_token.t == DUK_TOK_STRING) {
63932 /*
63933 * Detected a directive
63934 */
63935 duk_hstring *h_dir;
63936
63937 /* expected ival */
63938 DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
63939 DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
63941 h_dir = comp_ctx->prev_token.str1;
63942 DUK_ASSERT(h_dir != NULL);
63943
63944 DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
63945
63946 stmt_flags |= DUK__STILL_PROLOGUE;
63947
63948 /* Note: escaped characters differentiate directives */
63949
63950 if (comp_ctx->prev_token.num_escapes > 0) {
63951 DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
63952 "but we ignore such directives"));
63953 } else {
63954 /*
63955 * The length comparisons are present to handle
63956 * strings like "use strict\u0000foo" as required.
63957 */
63958
63959 if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
63960 DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict", 10) == 0) {
63961#if defined(DUK_USE_STRICT_DECL)
63962 DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
63963 (long) comp_ctx->curr_func.is_strict, (long) 1));
63964 comp_ctx->curr_func.is_strict = 1;
63965#else
63966 DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
63967#endif
63968 } else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
63969 DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail", 14) == 0) {
63970 DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
63971 (long) comp_ctx->curr_func.is_notail, (long) 1));
63972 comp_ctx->curr_func.is_notail = 1;
63973 } else {
63974 DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
63975 "directive prologue", (duk_hobject *) h_dir));
63976 }
63977 }
63978 } else {
63979 DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
63980 "prologue terminated if still active"));
63981 }
63982
63983 stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
63984 }
63985 } /* end switch (tok) */
63986
63987 /*
63988 * Statement value handling.
63989 *
63990 * Global code and eval code has an implicit return value
63991 * which comes from the last statement with a value
63992 * (technically a non-"empty" continuation, which is
63993 * different from an empty statement).
63994 *
63995 * Since we don't know whether a later statement will
63996 * override the value of the current statement, we need
63997 * to coerce the statement value to a register allocated
63998 * for implicit return values. In other cases we need
63999 * to coerce the statement value to a plain value to get
64000 * any side effects out (consider e.g. "foo.bar;").
64001 */
64002
64003 /* XXX: what about statements which leave a half-cooked value in 'res'
64004 * but have no stmt value? Any such statements?
64005 */
64006
64007 if (stmt_flags & DUK__HAS_VAL) {
64008 duk_reg_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
64009 if (reg_stmt_value >= 0) {
64010 duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
64011 } else {
64012 duk__ivalue_toplain_ignore(comp_ctx, res);
64013 }
64014 } else {
64015 ;
64016 }
64017
64018 /*
64019 * Statement terminator check, including automatic semicolon
64020 * handling. After this step, 'curr_tok' should be the first
64021 * token after a possible statement terminator.
64022 */
64023
64024 if (stmt_flags & DUK__HAS_TERM) {
64025 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
64026 DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
64027 duk__advance(comp_ctx);
64028 } else {
64029 if (comp_ctx->curr_token.allow_auto_semi) {
64030 DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
64031 } else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
64032 /* XXX: make this lenience dependent on flags or strictness? */
64033 DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
64034 "even though no lineterm present before next token)"));
64035 } else {
64037 }
64038 }
64039 } else {
64040 DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
64041 }
64042
64043 /*
64044 * Directive prologue tracking.
64045 */
64046
64047 if (stmt_flags & DUK__STILL_PROLOGUE) {
64048 DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
64049 comp_ctx->curr_func.in_directive_prologue = 1;
64050 }
64051
64052 /*
64053 * Cleanups (all statement parsing flows through here).
64054 *
64055 * Pop label site and reset labels. Reset 'next temp' to value at
64056 * entry to reuse temps.
64057 */
64058
64059 if (label_id >= 0) {
64060 duk__emit_extraop_bc(comp_ctx,
64062 (duk_regconst_t) label_id);
64063 }
64064
64065 DUK__SETTEMP(comp_ctx, temp_at_entry);
64066
64067 duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
64068
64069 /* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
64070
64071 DUK__RECURSION_DECREASE(comp_ctx, thr);
64073
64074#undef DUK__HAS_VAL
64075#undef DUK__HAS_TERM
64076#undef DUK__ALLOW_AUTO_SEMI_ALWAYS
64077
64078/*
64079 * Parse a statement list.
64080 *
64081 * Handles automatic semicolon insertion and implicit return value.
64082 *
64083 * Upon entry, 'curr_tok' should contain the first token of the first
64084 * statement (parsed in the "allow regexp literal" mode). Upon exit,
64085 * 'curr_tok' contains the token following the statement list terminator
64086 * (EOF or closing brace).
64087 */
64088
64089DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
64090 duk_hthread *thr = comp_ctx->thr;
64091 duk_context *ctx = (duk_context *) thr;
64092 duk_ivalue res_alloc;
64093 duk_ivalue *res = &res_alloc;
64094
64095 /* Setup state. Initial ivalue is 'undefined'. */
64096
64098
64099 /* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
64100 * intermediate values suffice for parsing of each function. Nesting is needed
64101 * for nested functions (which may occur inside expressions).
64102 */
64103
64104 DUK_MEMZERO(&res_alloc, sizeof(res_alloc));
64105 res->t = DUK_IVAL_PLAIN;
64106 res->x1.t = DUK_ISPEC_VALUE;
64107 res->x1.valstack_idx = duk_get_top(ctx);
64108 res->x2.valstack_idx = res->x1.valstack_idx + 1;
64109 duk_push_undefined(ctx);
64110 duk_push_undefined(ctx);
64111
64112 /* Parse statements until a closing token (EOF or '}') is found. */
64113
64114 for (;;) {
64115 /* Check whether statement list ends. */
64116
64117 if (expect_eof) {
64118 if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
64119 break;
64120 }
64121 } else {
64122 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
64123 break;
64124 }
64125 }
64126
64127 /* Check statement type based on the first token type.
64128 *
64129 * Note: expression parsing helpers expect 'curr_tok' to
64130 * contain the first token of the expression upon entry.
64131 */
64132
64133 DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
64134
64135 duk__parse_stmt(comp_ctx, res, allow_source_elem);
64136 }
64137
64138 duk__advance(comp_ctx);
64139
64140 /* Tear down state. */
64141
64142 duk_pop_2(ctx);
64143}
64144
64145/*
64146 * Declaration binding instantiation conceptually happens when calling a
64147 * function; for us it essentially means that function prologue. The
64148 * conceptual process is described in E5 Section 10.5.
64149 *
64150 * We need to keep track of all encountered identifiers to (1) create an
64151 * identifier-to-register map ("varmap"); and (2) detect duplicate
64152 * declarations. Identifiers which are not bound to registers still need
64153 * to be tracked for detecting duplicates. Currently such identifiers
64154 * are put into the varmap with a 'null' value, which is later cleaned up.
64155 *
64156 * To support functions with a large number of variable and function
64157 * declarations, registers are not allocated beyond a certain limit;
64158 * after that limit, variables and functions need slow path access.
64159 * Arguments are currently always register bound, which imposes a hard
64160 * (and relatively small) argument count limit.
64161 *
64162 * Some bindings in E5 are not configurable (= deletable) and almost all
64163 * are mutable (writable). Exceptions are:
64164 *
64165 * - The 'arguments' binding, established only if no shadowing argument
64166 * or function declaration exists. We handle 'arguments' creation
64167 * and binding through an explicit slow path environment record.
64168 *
64169 * - The "name" binding for a named function expression. This is also
64170 * handled through an explicit slow path environment record.
64171 */
64172
64173/* XXX: add support for variables to not be register bound always, to
64174 * handle cases with a very large number of variables?
64175 */
64176
64178 duk_hthread *thr = comp_ctx->thr;
64179 duk_context *ctx = (duk_context *) thr;
64180 duk_hstring *h_name;
64181 duk_bool_t configurable_bindings;
64182 duk_uarridx_t num_args;
64183 duk_uarridx_t num_decls;
64184 duk_regconst_t rc_name;
64185 duk_small_uint_t declvar_flags;
64186 duk_uarridx_t i;
64187#ifdef DUK_USE_ASSERTIONS
64188 duk_idx_t entry_top;
64189#endif
64190
64191#ifdef DUK_USE_ASSERTIONS
64192 entry_top = duk_get_top(ctx);
64193#endif
64194
64195 /*
64196 * Preliminaries
64197 */
64198
64199 configurable_bindings = comp_ctx->curr_func.is_eval;
64200 DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
64201
64202 /* varmap is already in comp_ctx->curr_func.varmap_idx */
64203
64204 /*
64205 * Function formal arguments, always bound to registers
64206 * (there's no support for shuffling them now).
64207 */
64208
64209 num_args = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
64210 DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
64211 /* XXX: check num_args */
64212
64213 for (i = 0; i < num_args; i++) {
64214 duk_get_prop_index(ctx, comp_ctx->curr_func.argnames_idx, i);
64215 h_name = duk_get_hstring(ctx, -1);
64216 DUK_ASSERT(h_name != NULL);
64217
64218 if (comp_ctx->curr_func.is_strict) {
64219 if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
64220 DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
64221 goto error_argname;
64222 }
64223 duk_dup_top(ctx);
64224 if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64225 DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
64226 goto error_argname;
64227 }
64228
64229 /* Ensure argument name is not a reserved word in current
64230 * (final) strictness. Formal argument parsing may not
64231 * catch reserved names if strictness changes during
64232 * parsing.
64233 *
64234 * We only need to do this in strict mode because non-strict
64235 * keyword are always detected in formal argument parsing.
64236 */
64237
64239 goto error_argname;
64240 }
64241 }
64242
64243 /* overwrite any previous binding of the same name; the effect is
64244 * that last argument of a certain name wins.
64245 */
64246
64247 /* only functions can have arguments */
64248 DUK_ASSERT(comp_ctx->curr_func.is_function);
64249 duk_push_uarridx(ctx, i); /* -> [ ... name index ] */
64250 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
64251
64252 /* no code needs to be emitted, the regs already have values */
64253 }
64254
64255 /* use temp_next for tracking register allocations */
64256 DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_reg_t) num_args);
64257
64258 /*
64259 * After arguments, allocate special registers (like shuffling temps)
64260 */
64261
64262 if (out_stmt_value_reg) {
64263 *out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
64264 }
64265 if (comp_ctx->curr_func.needs_shuffle) {
64266 duk_reg_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
64267 comp_ctx->curr_func.shuffle1 = shuffle_base;
64268 comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
64269 comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
64270 DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
64271 (long) comp_ctx->curr_func.shuffle1,
64272 (long) comp_ctx->curr_func.shuffle2,
64273 (long) comp_ctx->curr_func.shuffle3));
64274 }
64275 if (comp_ctx->curr_func.temp_next > 0x100) {
64276 DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
64277 goto error_outofregs;
64278 }
64279
64280 /*
64281 * Function declarations
64282 */
64283
64284 num_decls = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
64285 DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
64286 (long) num_decls,
64287 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.decls_idx)));
64288 for (i = 0; i < num_decls; i += 2) {
64289 duk_int_t decl_type;
64290 duk_int_t fnum;
64291
64292 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
64293 decl_type = duk_to_int(ctx, -1);
64294 fnum = decl_type >> 8; /* XXX: macros */
64295 decl_type = decl_type & 0xff;
64296 duk_pop(ctx);
64297
64298 if (decl_type != DUK_DECL_TYPE_FUNC) {
64299 continue;
64300 }
64301
64302 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
64303
64304 /* XXX: spilling */
64305 if (comp_ctx->curr_func.is_function) {
64306 duk_reg_t reg_bind;
64307 duk_dup_top(ctx);
64308 if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64309 /* shadowed; update value */
64310 duk_dup_top(ctx);
64311 duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
64312 reg_bind = duk_to_int(ctx, -1); /* [ ... name reg_bind ] */
64313 duk__emit_a_bc(comp_ctx,
64315 (duk_regconst_t) reg_bind,
64316 (duk_regconst_t) fnum);
64317 } else {
64318 /* function: always register bound */
64319 reg_bind = DUK__ALLOCTEMP(comp_ctx);
64320 duk__emit_a_bc(comp_ctx,
64322 (duk_regconst_t) reg_bind,
64323 (duk_regconst_t) fnum);
64324 duk_push_int(ctx, (duk_int_t) reg_bind);
64325 }
64326 } else {
64327 /* Function declaration for global/eval code is emitted even
64328 * for duplicates, because of E5 Section 10.5, step 5.e of
64329 * E5.1 (special behavior for variable bound to global object).
64330 *
64331 * DECLVAR will not re-declare a variable as such, but will
64332 * update the binding value.
64333 */
64334
64335 duk_reg_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
64336 duk_dup_top(ctx);
64337 rc_name = duk__getconst(comp_ctx);
64338 duk_push_null(ctx);
64339
64340 duk__emit_a_bc(comp_ctx,
64342 (duk_regconst_t) reg_temp,
64343 (duk_regconst_t) fnum);
64344
64345 declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
64348
64349 if (configurable_bindings) {
64350 declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
64351 }
64352
64353 duk__emit_a_b_c(comp_ctx,
64355 (duk_regconst_t) declvar_flags /*flags*/,
64356 rc_name /*name*/,
64357 (duk_regconst_t) reg_temp /*value*/);
64358
64359 DUK__SETTEMP(comp_ctx, reg_temp); /* forget temp */
64360 }
64361
64362 DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
64363 (duk_tval *) duk_get_tval(ctx, -2),
64364 (duk_tval *) duk_get_tval(ctx, -1)));
64365
64366 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
64367 }
64368
64369 /*
64370 * 'arguments' binding is special; if a shadowing argument or
64371 * function declaration exists, an arguments object will
64372 * definitely not be needed, regardless of whether the identifier
64373 * 'arguments' is referenced inside the function body.
64374 */
64375
64377 DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
64378 "-> arguments object creation can be skipped"));
64379 comp_ctx->curr_func.is_arguments_shadowed = 1;
64380 }
64381
64382 /*
64383 * Variable declarations.
64384 *
64385 * Unlike function declarations, variable declaration values don't get
64386 * assigned on entry. If a binding of the same name already exists, just
64387 * ignore it silently.
64388 */
64389
64390 for (i = 0; i < num_decls; i += 2) {
64391 duk_int_t decl_type;
64392
64393 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
64394 decl_type = duk_to_int(ctx, -1);
64395 decl_type = decl_type & 0xff;
64396 duk_pop(ctx);
64397
64398 if (decl_type != DUK_DECL_TYPE_VAR) {
64399 continue;
64400 }
64401
64402 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
64403
64404 if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64405 /* shadowed, ignore */
64406 } else {
64407 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
64408 h_name = duk_get_hstring(ctx, -1);
64409 DUK_ASSERT(h_name != NULL);
64410
64411 if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
64412 !comp_ctx->curr_func.is_arguments_shadowed) {
64413 /* E5 Section steps 7-8 */
64414 DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
64415 "but appears as a variable declaration -> treat as "
64416 "a no-op for variable declaration purposes"));
64417 duk_pop(ctx);
64418 continue;
64419 }
64420
64421 /* XXX: spilling */
64422 if (comp_ctx->curr_func.is_function) {
64423 duk_reg_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
64424 /* no need to init reg, it will be undefined on entry */
64425 duk_push_int(ctx, (duk_int_t) reg_bind);
64426 } else {
64427 duk_dup_top(ctx);
64428 rc_name = duk__getconst(comp_ctx);
64429 duk_push_null(ctx);
64430
64431 declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
64434 if (configurable_bindings) {
64435 declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
64436 }
64437
64438 duk__emit_a_b_c(comp_ctx,
64440 (duk_regconst_t) declvar_flags /*flags*/,
64441 rc_name /*name*/,
64442 (duk_regconst_t) 0 /*value*/);
64443 }
64444
64445 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
64446 }
64447 }
64448
64449 /*
64450 * Wrap up
64451 */
64452
64453 DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
64454 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx),
64455 (long) comp_ctx->curr_func.is_arguments_shadowed));
64456
64457 DUK_ASSERT_TOP(ctx, entry_top);
64458 return;
64459
64460 error_outofregs:
64463 return;
64464
64465 error_argname:
64468 return;
64469}
64470
64471/*
64472 * Parse a function-body-like expression (FunctionBody or Program
64473 * in E5 grammar) using a two-pass parse. The productions appear
64474 * in the following contexts:
64475 *
64476 * - function expression
64477 * - function statement
64478 * - function declaration
64479 * - getter in object literal
64480 * - setter in object literal
64481 * - global code
64482 * - eval code
64483 * - Function constructor body
64484 *
64485 * This function only parses the statement list of the body; the argument
64486 * list and possible function name must be initialized by the caller.
64487 * For instance, for Function constructor, the argument names are originally
64488 * on the value stack. The parsing of statements ends either at an EOF or
64489 * a closing brace; this is controlled by an input flag.
64490 *
64491 * Note that there are many differences affecting parsing and even code
64492 * generation:
64493 *
64494 * - Global and eval code have an implicit return value generated
64495 * by the last statement; function code does not
64496 *
64497 * - Global code, eval code, and Function constructor body end in
64498 * an EOF, other bodies in a closing brace ('}')
64499 *
64500 * Upon entry, 'curr_tok' is ignored and the function will pull in the
64501 * first token on its own. Upon exit, 'curr_tok' is the terminating
64502 * token (EOF or closing brace).
64503 */
64504
64505DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token) {
64506 duk_compiler_func *func;
64507 duk_hthread *thr;
64508 duk_context *ctx;
64509 duk_reg_t reg_stmt_value = -1;
64510 duk_lexer_point lex_pt;
64511 duk_reg_t temp_first;
64512 duk_small_int_t compile_round = 1;
64513
64514 DUK_ASSERT(comp_ctx != NULL);
64515
64516 thr = comp_ctx->thr;
64517 ctx = (duk_context *) thr;
64518 DUK_ASSERT(thr != NULL);
64519
64520 func = &comp_ctx->curr_func;
64521 DUK_ASSERT(func != NULL);
64522
64523 DUK__RECURSION_INCREASE(comp_ctx, thr);
64524
64526
64527 /*
64528 * Store lexer position for a later rewind
64529 */
64530
64531 DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
64532
64533 /*
64534 * Program code (global and eval code) has an implicit return value
64535 * from the last statement value (e.g. eval("1; 2+3;") returns 3).
64536 * This is not the case with functions. If implicit statement return
64537 * value is requested, all statements are coerced to a register
64538 * allocated here, and used in the implicit return statement below.
64539 */
64540
64541 /* XXX: this is pointless here because pass 1 is throw-away */
64542 if (implicit_return_value) {
64543 reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
64544
64545 /* If an implicit return value is needed by caller, it must be
64546 * initialized to 'undefined' because we don't know whether any
64547 * non-empty (where "empty" is a continuation type, and different
64548 * from an empty statement) statements will be executed.
64549 *
64550 * However, since 1st pass is a throwaway one, no need to emit
64551 * it here.
64552 */
64553#if 0
64554 duk__emit_extraop_bc(comp_ctx,
64556 0);
64557#endif
64558 }
64559
64560 /*
64561 * First pass.
64562 *
64563 * Gather variable/function declarations needed for second pass.
64564 * Code generated is dummy and discarded.
64565 */
64566
64567 func->in_directive_prologue = 1;
64568 func->in_scanning = 1;
64569 func->may_direct_eval = 0;
64570 func->id_access_arguments = 0;
64571 func->id_access_slow = 0;
64572 func->reg_stmt_value = reg_stmt_value;
64573#if defined(DUK_USE_DEBUGGER_SUPPORT)
64574 func->min_line = DUK_INT_MAX;
64575 func->max_line = 0;
64576#endif
64577
64578 /* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
64579 if (expect_token >= 0) {
64580 /* Eating a left curly; regexp mode is allowed by left curly
64581 * based on duk__token_lbp[] automatically.
64582 */
64583 DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
64585 duk__advance_expect(comp_ctx, expect_token);
64586 } else {
64587 /* Need to set curr_token.t because lexing regexp mode depends on current
64588 * token type. Zero value causes "allow regexp" mode.
64589 */
64590 comp_ctx->curr_token.t = 0;
64591 duk__advance(comp_ctx);
64592 }
64593
64594 DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
64595 duk__parse_stmts(comp_ctx,
64596 1, /* allow source elements */
64597 expect_eof); /* expect EOF instead of } */
64598 DUK_DDD(DUK_DDDPRINT("end 1st pass"));
64599
64600 /*
64601 * Second (and possibly third) pass.
64602 *
64603 * Generate actual code. In most cases the need for shuffle
64604 * registers is detected during pass 1, but in some corner cases
64605 * we'll only detect it during pass 2 and a third pass is then
64606 * needed (see GH-115).
64607 */
64608
64609 for (;;) {
64610 duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
64611 compile_round++;
64612
64613 /*
64614 * Rewind lexer.
64615 *
64616 * duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
64617 * literal" mode with current strictness.
64618 *
64619 * curr_token line number info should be initialized for pass 2 before
64620 * generating prologue, to ensure prologue bytecode gets nice line numbers.
64621 */
64622
64623 DUK_DDD(DUK_DDDPRINT("rewind lexer"));
64624 DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
64625 comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
64626 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
64627 duk__advance(comp_ctx);
64628
64629 /*
64630 * Reset function state and perform register allocation, which creates
64631 * 'varmap' for second pass. Function prologue for variable declarations,
64632 * binding value initializations etc is emitted as a by-product.
64633 *
64634 * Strict mode restrictions for duplicate and invalid argument
64635 * names are checked here now that we know whether the function
64636 * is actually strict. See: test-dev-strict-mode-boundary.js.
64637 *
64638 * Inner functions are compiled during pass 1 and are not reset.
64639 */
64640
64641 duk__reset_func_for_pass2(comp_ctx);
64642 func->in_directive_prologue = 1;
64643 func->in_scanning = 0;
64644
64645 /* must be able to emit code, alloc consts, etc. */
64646
64648 (implicit_return_value ? &reg_stmt_value : NULL));
64649 func->reg_stmt_value = reg_stmt_value;
64650
64651 temp_first = DUK__GETTEMP(comp_ctx);
64652
64653 func->temp_first = temp_first;
64654 func->temp_next = temp_first;
64655 func->stmt_next = 0;
64656 func->label_next = 0;
64657
64658 /* XXX: init or assert catch depth etc -- all values */
64659 func->id_access_arguments = 0;
64660 func->id_access_slow = 0;
64661
64662 /*
64663 * Check function name validity now that we know strictness.
64664 * This only applies to function declarations and expressions,
64665 * not setter/getter name.
64666 *
64667 * See: test-dev-strict-mode-boundary.js
64668 */
64669
64670 if (func->is_function && !func->is_setget && func->h_name != NULL) {
64671 if (func->is_strict) {
64672 if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
64673 DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
64674 goto error_funcname;
64675 }
64677 DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
64678 goto error_funcname;
64679 }
64680 } else {
64683 DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
64684 goto error_funcname;
64685 }
64686 }
64687 }
64688
64689 /*
64690 * Second pass parsing.
64691 */
64692
64693 if (implicit_return_value) {
64694 /* Default implicit return value. */
64695 duk__emit_extraop_bc(comp_ctx,
64697 0);
64698 }
64699
64700 DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
64701 duk__parse_stmts(comp_ctx,
64702 1, /* allow source elements */
64703 expect_eof); /* expect EOF instead of } */
64704 DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
64705
64707
64708 if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
64709 /* Shuffle decision not changed. */
64710 break;
64711 }
64712 if (compile_round >= 3) {
64713 /* Should never happen but avoid infinite loop just in case. */
64714 DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
64716 }
64717 DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
64718 }
64719
64720 /*
64721 * Emit a final RETURN.
64722 *
64723 * It would be nice to avoid emitting an unnecessary "return" opcode
64724 * if the current PC is not reachable. However, this cannot be reliably
64725 * detected; even if the previous instruction is an unconditional jump,
64726 * there may be a previous jump which jumps to current PC (which is the
64727 * case for iteration and conditional statements, for instance).
64728 */
64729
64730 /* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
64731 * we could avoid the last RETURN if we could ensure there is no way to get here
64732 * (directly or via a jump)
64733 */
64734
64735 DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
64736 if (reg_stmt_value >= 0) {
64737 duk__emit_a_b(comp_ctx,
64740 (duk_regconst_t) reg_stmt_value /*reg*/);
64741 } else {
64742 duk__emit_a_b(comp_ctx,
64744 (duk_regconst_t) 0 /*flags*/,
64745 (duk_regconst_t) 0 /*reg(ignored)*/);
64746 }
64747
64748 /*
64749 * Peephole optimize JUMP chains.
64750 */
64751
64753
64754 /*
64755 * comp_ctx->curr_func is now ready to be converted into an actual
64756 * function template.
64757 */
64758
64759 DUK__RECURSION_DECREASE(comp_ctx, thr);
64760 return;
64761
64762 error_funcname:
64764}
64765
64766/*
64767 * Parse a function-like expression:
64768 *
64769 * - function expression
64770 * - function declaration
64771 * - function statement (non-standard)
64772 * - setter/getter
64773 *
64774 * Adds the function to comp_ctx->curr_func function table and returns the
64775 * function number.
64776 *
64777 * On entry, curr_token points to:
64778 *
64779 * - the token after 'function' for function expression/declaration/statement
64780 * - the token after 'set' or 'get' for setter/getter
64781 */
64782
64783/* Parse formals. */
64785 duk_hthread *thr = comp_ctx->thr;
64786 duk_context *ctx = (duk_context *) thr;
64787 duk_bool_t first = 1;
64788 duk_uarridx_t n;
64789
64790 for (;;) {
64791 if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
64792 break;
64793 }
64794
64795 if (first) {
64796 /* no comma */
64797 first = 0;
64798 } else {
64800 }
64801
64802 /* Note: when parsing a formal list in non-strict context, e.g.
64803 * "implements" is parsed as an identifier. When the function is
64804 * later detected to be strict, the argument list must be rechecked
64805 * against a larger set of reserved words (that of strict mode).
64806 * This is handled by duk__parse_func_body(). Here we recognize
64807 * whatever tokens are considered reserved in current strictness
64808 * (which is not always enough).
64809 */
64810
64811 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
64812 DUK_ERROR_SYNTAX(thr, "expected identifier");
64813 }
64816 DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
64817 (duk_heaphdr *) comp_ctx->curr_token.str1));
64818
64819 /* XXX: append primitive */
64820 duk_push_hstring(ctx, comp_ctx->curr_token.str1);
64821 n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
64822 duk_put_prop_index(ctx, comp_ctx->curr_func.argnames_idx, n);
64823
64824 duk__advance(comp_ctx); /* eat identifier */
64825 }
64826}
64827
64828/* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
64829 * correctly set up. Assumes that curr_token is just after 'function' (or
64830 * 'set'/'get' etc).
64831 */
64832DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
64833 duk_hthread *thr = comp_ctx->thr;
64834 duk_context *ctx = (duk_context *) thr;
64835
64836 DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
64837 DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
64838 DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
64839 DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
64840 DUK_ASSERT(comp_ctx->curr_func.is_setget == is_setget);
64841 DUK_ASSERT(comp_ctx->curr_func.is_decl == is_decl);
64842
64844
64845 /*
64846 * Function name (if any)
64847 *
64848 * We don't check for prohibited names here, because we don't
64849 * yet know whether the function will be strict. Function body
64850 * parsing handles this retroactively.
64851 *
64852 * For function expressions and declarations function name must
64853 * be an Identifer (excludes reserved words). For setter/getter
64854 * it is a PropertyName which allows reserved words and also
64855 * strings and numbers (e.g. "{ get 1() { ... } }").
64856 */
64857
64858 if (is_setget) {
64859 /* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
64860 if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER ||
64861 comp_ctx->curr_token.t == DUK_TOK_STRING) {
64862 duk_push_hstring(ctx, comp_ctx->curr_token.str1); /* keep in valstack */
64863 } else if (comp_ctx->curr_token.t == DUK_TOK_NUMBER) {
64864 duk_push_number(ctx, comp_ctx->curr_token.num);
64865 duk_to_string(ctx, -1);
64866 } else {
64868 }
64869 comp_ctx->curr_func.h_name = duk_get_hstring(ctx, -1); /* borrowed reference */
64870 DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
64871 duk__advance(comp_ctx);
64872 } else {
64873 /* Function name is an Identifier (not IdentifierName), but we get
64874 * the raw name (not recognizing keywords) here and perform the name
64875 * checks only after pass 1.
64876 */
64877 if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER) {
64878 duk_push_hstring(ctx, comp_ctx->curr_token.str1); /* keep in valstack */
64879 comp_ctx->curr_func.h_name = duk_get_hstring(ctx, -1); /* borrowed reference */
64880 DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
64881 duk__advance(comp_ctx);
64882 } else {
64883 /* valstack will be unbalanced, which is OK */
64884 DUK_ASSERT(!is_setget);
64885 if (is_decl) {
64887 }
64888 }
64889 }
64890
64891 DUK_DDD(DUK_DDDPRINT("function name: %!O",
64892 (duk_heaphdr *) comp_ctx->curr_func.h_name));
64893
64894 /*
64895 * Formal argument list
64896 *
64897 * We don't check for prohibited names or for duplicate argument
64898 * names here, becase we don't yet know whether the function will
64899 * be strict. Function body parsing handles this retroactively.
64900 */
64901
64903
64904 duk__parse_func_formals(comp_ctx);
64905
64906 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
64907 duk__advance(comp_ctx);
64908
64909 /*
64910 * Parse function body
64911 */
64912
64913 duk__parse_func_body(comp_ctx,
64914 0, /* expect_eof */
64915 0, /* implicit_return_value */
64916 DUK_TOK_LCURLY); /* expect_token */
64917
64918 /*
64919 * Convert duk_compiler_func to a function template and add it
64920 * to the parent function table.
64921 */
64922
64923 duk__convert_to_func_template(comp_ctx, is_setget /*force_no_namebind*/); /* -> [ ... func ] */
64924}
64925
64926/* Parse an inner function, adding the function template to the current function's
64927 * function table. Return a function number to be used by the outer function.
64928 *
64929 * Avoiding O(depth^2) inner function parsing is handled here. On the first pass,
64930 * compile and register the function normally into the 'funcs' array, also recording
64931 * a lexer point (offset/line) to the closing brace of the function. On the second
64932 * pass, skip the function and return the same 'fnum' as on the first pass by using
64933 * a running counter.
64934 *
64935 * An unfortunate side effect of this is that when parsing the inner function, almost
64936 * nothing is known of the outer function, i.e. the inner function's scope. We don't
64937 * need that information at the moment, but it would allow some optimizations if it
64938 * were used.
64939 */
64941 duk_hthread *thr = comp_ctx->thr;
64942 duk_context *ctx = (duk_context *) thr;
64943 duk_compiler_func old_func;
64944 duk_idx_t entry_top;
64945 duk_int_t fnum;
64946
64947 /*
64948 * On second pass, skip the function.
64949 */
64950
64951 if (!comp_ctx->curr_func.in_scanning) {
64952 duk_lexer_point lex_pt;
64953
64954 fnum = comp_ctx->curr_func.fnum_next++;
64955 duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
64956 lex_pt.offset = duk_to_int(ctx, -1);
64957 duk_pop(ctx);
64958 duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
64959 lex_pt.line = duk_to_int(ctx, -1);
64960 duk_pop(ctx);
64961
64962 DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
64963 (long) lex_pt.offset, (long) lex_pt.line));
64964
64965 DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
64966 comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
64967 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
64968 duk__advance(comp_ctx);
64970
64971 return fnum;
64972 }
64973
64974 /*
64975 * On first pass, perform actual parsing. Remember valstack top on entry
64976 * to restore it later, and switch to using a new function in comp_ctx.
64977 */
64978
64979 entry_top = duk_get_top(ctx);
64980 DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
64981 (long) entry_top, (long) comp_ctx->curr_token.start_offset));
64982
64983 DUK_MEMCPY(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
64984
64985 DUK_MEMZERO(&comp_ctx->curr_func, sizeof(duk_compiler_func));
64987 DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
64988
64989 /* inherit initial strictness from parent */
64990 comp_ctx->curr_func.is_strict = old_func.is_strict;
64991
64992 DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
64993 comp_ctx->curr_func.is_function = 1;
64994 DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
64995 DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
64996 comp_ctx->curr_func.is_setget = is_setget;
64997 comp_ctx->curr_func.is_decl = is_decl;
64998
64999 /*
65000 * Parse inner function
65001 */
65002
65003 duk__parse_func_like_raw(comp_ctx, is_decl, is_setget); /* pushes function template */
65004
65005 /* prev_token.start_offset points to the closing brace here; when skipping
65006 * we're going to reparse the closing brace to ensure semicolon insertion
65007 * etc work as expected.
65008 */
65009 DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
65010 (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
65011 DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
65012
65013 /* XXX: append primitive */
65014 DUK_ASSERT(duk_get_length(ctx, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
65015 fnum = old_func.fnum_next++;
65016
65017 if (fnum > DUK__MAX_FUNCS) {
65019 }
65020
65021 /* array writes autoincrement length */
65022 (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
65023 duk_push_size_t(ctx, comp_ctx->prev_token.start_offset);
65024 (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
65025 duk_push_int(ctx, comp_ctx->prev_token.start_line);
65026 (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
65027
65028 /*
65029 * Cleanup: restore original function, restore valstack state.
65030 */
65031
65032 DUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
65033 duk_set_top(ctx, entry_top);
65034
65035 DUK_ASSERT_TOP(ctx, entry_top);
65036
65037 return fnum;
65038}
65039
65040/*
65041 * Compile input string into an executable function template without
65042 * arguments.
65043 *
65044 * The string is parsed as the "Program" production of Ecmascript E5.
65045 * Compilation context can be either global code or eval code (see E5
65046 * Sections 14 and 15.1.2.1).
65047 *
65048 * Input stack: [ ... filename ]
65049 * Output stack: [ ... func_template ]
65050 */
65051
65052/* XXX: source code property */
65053
65055 duk_hthread *thr = (duk_hthread *) ctx;
65056 duk_hstring *h_filename;
65057 duk__compiler_stkstate *comp_stk;
65058 duk_compiler_ctx *comp_ctx;
65059 duk_lexer_point *lex_pt;
65060 duk_compiler_func *func;
65061 duk_idx_t entry_top;
65062 duk_bool_t is_strict;
65063 duk_bool_t is_eval;
65064 duk_bool_t is_funcexpr;
65065 duk_small_uint_t flags;
65066
65067 DUK_ASSERT(thr != NULL);
65068
65069 /*
65070 * Arguments check
65071 */
65072
65073 entry_top = duk_get_top(ctx);
65074 DUK_ASSERT(entry_top >= 2);
65075
65076 comp_stk = (duk__compiler_stkstate *) duk_require_pointer(ctx, -1);
65077 comp_ctx = &comp_stk->comp_ctx_alloc;
65078 lex_pt = &comp_stk->lex_pt_alloc;
65079 DUK_ASSERT(comp_ctx != NULL);
65080 DUK_ASSERT(lex_pt != NULL);
65081
65082 flags = comp_stk->flags;
65083 is_eval = (flags & DUK_JS_COMPILE_FLAG_EVAL ? 1 : 0);
65084 is_strict = (flags & DUK_JS_COMPILE_FLAG_STRICT ? 1 : 0);
65085 is_funcexpr = (flags & DUK_JS_COMPILE_FLAG_FUNCEXPR ? 1 : 0);
65086
65087 h_filename = duk_get_hstring(ctx, -2); /* may be undefined */
65088
65089 /*
65090 * Init compiler and lexer contexts
65091 */
65092
65093 func = &comp_ctx->curr_func;
65094#ifdef DUK_USE_EXPLICIT_NULL_INIT
65095 comp_ctx->thr = NULL;
65096 comp_ctx->h_filename = NULL;
65097 comp_ctx->prev_token.str1 = NULL;
65098 comp_ctx->prev_token.str2 = NULL;
65099 comp_ctx->curr_token.str1 = NULL;
65100 comp_ctx->curr_token.str2 = NULL;
65101#endif
65102
65104
65105 duk_push_dynamic_buffer(ctx, 0); /* entry_top + 0 */
65106 duk_push_undefined(ctx); /* entry_top + 1 */
65107 duk_push_undefined(ctx); /* entry_top + 2 */
65108 duk_push_undefined(ctx); /* entry_top + 3 */
65109 duk_push_undefined(ctx); /* entry_top + 4 */
65110
65111 comp_ctx->thr = thr;
65112 comp_ctx->h_filename = h_filename;
65113 comp_ctx->tok11_idx = entry_top + 1;
65114 comp_ctx->tok12_idx = entry_top + 2;
65115 comp_ctx->tok21_idx = entry_top + 3;
65116 comp_ctx->tok22_idx = entry_top + 4;
65118
65119 /* comp_ctx->lex has been pre-initialized by caller: it has been
65120 * zeroed and input/input_length has been set.
65121 */
65122 comp_ctx->lex.thr = thr;
65123 /* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
65124 comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
65125 comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
65126 comp_ctx->lex.buf_idx = entry_top + 0;
65127 comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 0);
65128 DUK_ASSERT(comp_ctx->lex.buf != NULL);
65131
65132 lex_pt->offset = 0;
65133 lex_pt->line = 1;
65134 DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt); /* fills window */
65135 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
65136
65137 /*
65138 * Initialize function state for a zero-argument function
65139 */
65140
65142 DUK_ASSERT(func->num_formals == 0);
65143
65144 if (is_funcexpr) {
65145 /* Name will be filled from function expression, not by caller.
65146 * This case is used by Function constructor and duk_compile()
65147 * API with the DUK_COMPILE_FUNCTION option.
65148 */
65149 DUK_ASSERT(func->h_name == NULL);
65150 } else {
65153 func->h_name = duk_get_hstring(ctx, -1);
65154 }
65155
65156 /*
65157 * Parse a function body or a function-like expression, depending
65158 * on flags.
65159 */
65160
65161 func->is_strict = is_strict;
65162 func->is_setget = 0;
65163 func->is_decl = 0;
65164
65165 if (is_funcexpr) {
65166 func->is_function = 1;
65167 func->is_eval = 0;
65168 func->is_global = 0;
65169
65170 duk__advance(comp_ctx); /* init 'curr_token' */
65172 (void) duk__parse_func_like_raw(comp_ctx,
65173 0, /* is_decl */
65174 0); /* is_setget */
65175 } else {
65176 func->is_function = 0;
65177 func->is_eval = is_eval;
65178 func->is_global = !is_eval;
65179
65180 duk__parse_func_body(comp_ctx,
65181 1, /* expect_eof */
65182 1, /* implicit_return_value */
65183 -1); /* expect_token */
65185
65186 /*
65187 * Convert duk_compiler_func to a function template
65188 */
65189
65190 duk__convert_to_func_template(comp_ctx, 0 /*force_no_namebind*/);
65191
65192 /*
65193 * Wrapping duk_safe_call() will mangle the stack, just return stack top
65194 */
65195
65196 /* [ ... filename (temps) func ] */
65197
65198 return 1;
65199}
65200
65201DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {
65202 duk_context *ctx = (duk_context *) thr;
65203 duk__compiler_stkstate comp_stk;
65204 duk_compiler_ctx *prev_ctx;
65205 duk_ret_t safe_rc;
65206
65207 /* XXX: this illustrates that a C catchpoint implemented using duk_safe_call()
65208 * is a bit heavy at the moment. The wrapper compiles to ~180 bytes on x64.
65209 * Alternatives would be nice.
65210 */
65211
65212 DUK_ASSERT(thr != NULL);
65213 DUK_ASSERT(src_buffer != NULL);
65214
65215 /* preinitialize lexer state partially */
65216 DUK_MEMZERO(&comp_stk, sizeof(comp_stk));
65217 comp_stk.flags = flags;
65219 comp_stk.comp_ctx_alloc.lex.input = src_buffer;
65220 comp_stk.comp_ctx_alloc.lex.input_length = src_length;
65221
65222 duk_push_pointer(ctx, (void *) &comp_stk);
65223
65224 /* [ ... filename &comp_stk ] */
65225
65226 prev_ctx = thr->compile_ctx;
65227 thr->compile_ctx = &comp_stk.comp_ctx_alloc; /* for duk_error_augment.c */
65228 safe_rc = duk_safe_call(ctx, duk__js_compile_raw, 2 /*nargs*/, 1 /*nret*/);
65229 thr->compile_ctx = prev_ctx; /* must restore reliably before returning */
65230
65231 if (safe_rc != DUK_EXEC_SUCCESS) {
65232 duk_throw(ctx);
65233 }
65234
65235 /* [ ... template ] */
65236}
65237/*
65238 * Ecmascript bytecode executor.
65239 */
65240
65241/* include removed: duk_internal.h */
65242
65243/*
65244 * Local declarations.
65245 */
65246
65248
65249/*
65250 * Arithmetic, binary, and logical helpers.
65251 *
65252 * Note: there is no opcode for logical AND or logical OR; this is on
65253 * purpose, because the evalution order semantics for them make such
65254 * opcodes pretty pointless: short circuiting means they are most
65255 * comfortably implemented as jumps. However, a logical NOT opcode
65256 * is useful.
65257 *
65258 * Note: careful with duk_tval pointers here: they are potentially
65259 * invalidated by any DECREF and almost any API call. It's still
65260 * preferable to work without making a copy but that's not always
65261 * possible.
65262 */
65263
65265 /*
65266 * Ecmascript modulus ('%') does not match IEEE 754 "remainder"
65267 * operation (implemented by remainder() in C99) but does seem
65268 * to match ANSI C fmod().
65269 *
65270 * Compare E5 Section 11.5.3 and "man fmod".
65271 */
65272
65273 return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
65274}
65275
65277 /*
65278 * Addition operator is different from other arithmetic
65279 * operations in that it also provides string concatenation.
65280 * Hence it is implemented separately.
65281 *
65282 * There is a fast path for number addition. Other cases go
65283 * through potentially multiple coercions as described in the
65284 * E5 specification. It may be possible to reduce the number
65285 * of coercions, but this must be done carefully to preserve
65286 * the exact semantics.
65287 *
65288 * E5 Section 11.6.1.
65289 *
65290 * Custom types also have special behavior implemented here.
65291 */
65292
65293 duk_context *ctx = (duk_context *) thr;
65295
65296 DUK_ASSERT(thr != NULL);
65297 DUK_ASSERT(ctx != NULL);
65298 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65299 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
65300 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
65301 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65302
65303 /*
65304 * Fast paths
65305 */
65306
65307#if defined(DUK_USE_FASTINT)
65308 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65309 duk_int64_t v1, v2, v3;
65310 duk_int32_t v3_hi;
65311 duk_tval *tv_z;
65312
65313 /* Input values are signed 48-bit so we can detect overflow
65314 * reliably from high bits or just a comparison.
65315 */
65316
65317 v1 = DUK_TVAL_GET_FASTINT(tv_x);
65318 v2 = DUK_TVAL_GET_FASTINT(tv_y);
65319 v3 = v1 + v2;
65320 v3_hi = (duk_int32_t) (v3 >> 32);
65321 if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
65322 tv_z = thr->valstack_bottom + idx_z;
65323 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
65324 return;
65325 } else {
65326 /* overflow, fall through */
65327 ;
65328 }
65329 }
65330#endif /* DUK_USE_FASTINT */
65331
65332 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
65333 duk_tval *tv_z;
65334
65335 du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
65338
65339 tv_z = thr->valstack_bottom + idx_z;
65340 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
65341 return;
65342 }
65343
65344 /*
65345 * Slow path: potentially requires function calls for coercion
65346 */
65347
65348 duk_push_tval(ctx, tv_x);
65349 duk_push_tval(ctx, tv_y);
65350 duk_to_primitive(ctx, -2, DUK_HINT_NONE); /* side effects -> don't use tv_x, tv_y after */
65352
65353 /* As a first approximation, buffer values are coerced to strings
65354 * for addition. This means that adding two buffers currently
65355 * results in a string.
65356 */
65359 duk_to_string(ctx, -2);
65360 duk_to_string(ctx, -1);
65361 duk_concat(ctx, 2); /* [... s1 s2] -> [... s1+s2] */
65362 duk_replace(ctx, (duk_idx_t) idx_z); /* side effects */
65363 } else {
65364 duk_double_t d1, d2;
65365
65366 d1 = duk_to_number(ctx, -2);
65367 d2 = duk_to_number(ctx, -1);
65368 DUK_ASSERT(duk_is_number(ctx, -2));
65369 DUK_ASSERT(duk_is_number(ctx, -1));
65372
65373 du.d = d1 + d2;
65376
65377 duk_pop_2(ctx);
65378 duk_push_number(ctx, du.d);
65379 duk_replace(ctx, (duk_idx_t) idx_z); /* side effects */
65380 }
65381}
65382
65384 /*
65385 * Arithmetic operations other than '+' have number-only semantics
65386 * and are implemented here. The separate switch-case here means a
65387 * "double dispatch" of the arithmetic opcode, but saves code space.
65388 *
65389 * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
65390 */
65391
65392 duk_context *ctx = (duk_context *) thr;
65393 duk_tval *tv_z;
65394 duk_double_t d1, d2;
65396
65397 DUK_ASSERT(thr != NULL);
65398 DUK_ASSERT(ctx != NULL);
65399 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65400 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
65401 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
65402 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65403
65404#if defined(DUK_USE_FASTINT)
65405 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65406 duk_int64_t v1, v2, v3;
65407 duk_int32_t v3_hi;
65408
65409 v1 = DUK_TVAL_GET_FASTINT(tv_x);
65410 v2 = DUK_TVAL_GET_FASTINT(tv_y);
65411
65412 switch (opcode) {
65413 case DUK_OP_SUB: {
65414 v3 = v1 - v2;
65415 break;
65416 }
65417 case DUK_OP_MUL: {
65418 /* Must ensure result is 64-bit (no overflow); a
65419 * simple and sufficient fast path is to allow only
65420 * 32-bit inputs. Avoid zero inputs to avoid
65421 * negative zero issues (-1 * 0 = -0, for instance).
65422 */
65423 if (v1 >= -0x80000000LL && v1 <= 0x7fffffffLL && v1 != 0 &&
65424 v2 >= -0x80000000LL && v2 <= 0x7fffffffLL && v2 != 0) {
65425 v3 = v1 * v2;
65426 } else {
65427 goto skip_fastint;
65428 }
65429 break;
65430 }
65431 case DUK_OP_DIV: {
65432 /* Don't allow a zero divisor. Fast path check by
65433 * "verifying" with multiplication. Also avoid zero
65434 * dividend to avoid negative zero issues (0 / -1 = -0
65435 * for instance).
65436 */
65437 if (v1 == 0 || v2 == 0) {
65438 goto skip_fastint;
65439 }
65440 v3 = v1 / v2;
65441 if (v3 * v2 != v1) {
65442 goto skip_fastint;
65443 }
65444 break;
65445 }
65446 case DUK_OP_MOD: {
65447 /* Don't allow a zero divisor. Restrict both v1 and
65448 * v2 to positive values to avoid compiler specific
65449 * behavior.
65450 */
65451 if (v1 < 1 || v2 < 1) {
65452 goto skip_fastint;
65453 }
65454 v3 = v1 % v2;
65455 DUK_ASSERT(v3 >= 0);
65456 DUK_ASSERT(v3 < v2);
65457 DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
65458 break;
65459 }
65460 default: {
65462 goto skip_fastint;
65463 }
65464 }
65465
65466 v3_hi = (duk_int32_t) (v3 >> 32);
65467 if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
65468 tv_z = thr->valstack_bottom + idx_z;
65469 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
65470 return;
65471 }
65472 /* fall through if overflow etc */
65473 }
65474 skip_fastint:
65475#endif /* DUK_USE_FASTINT */
65476
65477 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
65478 /* fast path */
65479 d1 = DUK_TVAL_GET_NUMBER(tv_x);
65480 d2 = DUK_TVAL_GET_NUMBER(tv_y);
65481 } else {
65482 duk_push_tval(ctx, tv_x);
65483 duk_push_tval(ctx, tv_y);
65484 d1 = duk_to_number(ctx, -2); /* side effects */
65485 d2 = duk_to_number(ctx, -1);
65486 DUK_ASSERT(duk_is_number(ctx, -2));
65487 DUK_ASSERT(duk_is_number(ctx, -1));
65490 duk_pop_2(ctx);
65491 }
65492
65493 switch (opcode) {
65494 case DUK_OP_SUB: {
65495 du.d = d1 - d2;
65496 break;
65497 }
65498 case DUK_OP_MUL: {
65499 du.d = d1 * d2;
65500 break;
65501 }
65502 case DUK_OP_DIV: {
65503 du.d = d1 / d2;
65504 break;
65505 }
65506 case DUK_OP_MOD: {
65507 du.d = duk__compute_mod(d1, d2);
65508 break;
65509 }
65510 default: {
65512 du.d = DUK_DOUBLE_NAN; /* should not happen */
65513 break;
65514 }
65515 }
65516
65517 /* important to use normalized NaN with 8-byte tagged types */
65520
65521 tv_z = thr->valstack_bottom + idx_z;
65522 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
65523}
65524
65526 /*
65527 * Binary bitwise operations use different coercions (ToInt32, ToUint32)
65528 * depending on the operation. We coerce the arguments first using
65529 * ToInt32(), and then cast to an 32-bit value if necessary. Note that
65530 * such casts must be correct even if there is no native 32-bit type
65531 * (e.g., duk_int32_t and duk_uint32_t are 64-bit).
65532 *
65533 * E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
65534 */
65535
65536 duk_context *ctx = (duk_context *) thr;
65537 duk_tval *tv_z;
65538 duk_int32_t i1, i2, i3;
65539 duk_uint32_t u1, u2, u3;
65540#if defined(DUK_USE_FASTINT)
65541 duk_int64_t fi3;
65542#else
65543 duk_double_t d3;
65544#endif
65545
65546 DUK_ASSERT(thr != NULL);
65547 DUK_ASSERT(ctx != NULL);
65548 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65549 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
65550 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
65551 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65552
65553#if defined(DUK_USE_FASTINT)
65554 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65555 i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
65556 i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
65557 }
65558 else
65559#endif /* DUK_USE_FASTINT */
65560 {
65561 duk_push_tval(ctx, tv_x);
65562 duk_push_tval(ctx, tv_y);
65563 i1 = duk_to_int32(ctx, -2);
65564 i2 = duk_to_int32(ctx, -1);
65565 duk_pop_2(ctx);
65566 }
65567
65568 switch (opcode) {
65569 case DUK_OP_BAND: {
65570 i3 = i1 & i2;
65571 break;
65572 }
65573 case DUK_OP_BOR: {
65574 i3 = i1 | i2;
65575 break;
65576 }
65577 case DUK_OP_BXOR: {
65578 i3 = i1 ^ i2;
65579 break;
65580 }
65581 case DUK_OP_BASL: {
65582 /* Signed shift, named "arithmetic" (asl) because the result
65583 * is signed, e.g. 4294967295 << 1 -> -2. Note that result
65584 * must be masked.
65585 */
65586
65587 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65588 i3 = i1 << (u2 & 0x1f); /* E5 Section 11.7.1, steps 7 and 8 */
65589 i3 = i3 & ((duk_int32_t) 0xffffffffUL); /* Note: left shift, should mask */
65590 break;
65591 }
65592 case DUK_OP_BASR: {
65593 /* signed shift */
65594
65595 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65596 i3 = i1 >> (u2 & 0x1f); /* E5 Section 11.7.2, steps 7 and 8 */
65597 break;
65598 }
65599 case DUK_OP_BLSR: {
65600 /* unsigned shift */
65601
65602 u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
65603 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65604
65605 /* special result value handling */
65606 u3 = u1 >> (u2 & 0x1f); /* E5 Section 11.7.2, steps 7 and 8 */
65607#if defined(DUK_USE_FASTINT)
65608 fi3 = (duk_int64_t) u3;
65609 goto fastint_result_set;
65610#else
65611 d3 = (duk_double_t) u3;
65612 goto result_set;
65613#endif
65614 }
65615 default: {
65617 i3 = 0; /* should not happen */
65618 break;
65619 }
65620 }
65621
65622#if defined(DUK_USE_FASTINT)
65623 /* Result is always fastint compatible. */
65624 /* XXX: Set 32-bit result (but must then handle signed and
65625 * unsigned results separately).
65626 */
65627 fi3 = (duk_int64_t) i3;
65629 fastint_result_set:
65630 tv_z = thr->valstack_bottom + idx_z;
65631 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3); /* side effects */
65632#else
65633 d3 = (duk_double_t) i3;
65634
65635 result_set:
65636 DUK_ASSERT(!DUK_ISNAN(d3)); /* 'd3' is never NaN, so no need to normalize */
65637 DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3); /* always normalized */
65638
65639 tv_z = thr->valstack_bottom + idx_z;
65640 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3); /* side effects */
65641#endif
65642}
65643
65644/* In-place unary operation. */
65646 /*
65647 * Arithmetic operations other than '+' have number-only semantics
65648 * and are implemented here. The separate switch-case here means a
65649 * "double dispatch" of the arithmetic opcode, but saves code space.
65650 *
65651 * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
65652 */
65653
65654 duk_context *ctx = (duk_context *) thr;
65655 duk_double_t d1;
65657
65658 DUK_ASSERT(thr != NULL);
65659 DUK_ASSERT(ctx != NULL);
65660 DUK_ASSERT(opcode == DUK_EXTRAOP_UNM || opcode == DUK_EXTRAOP_UNP);
65661 DUK_ASSERT(tv_x != NULL);
65662 DUK_ASSERT(idx_x >= 0);
65663
65664#if defined(DUK_USE_FASTINT)
65665 if (DUK_TVAL_IS_FASTINT(tv_x)) {
65666 duk_int64_t v1, v2;
65667
65668 v1 = DUK_TVAL_GET_FASTINT(tv_x);
65669 if (opcode == DUK_EXTRAOP_UNM) {
65670 /* The smallest fastint is no longer 48-bit when
65671 * negated. Positive zero becames negative zero
65672 * (cannot be represented) when negated.
65673 */
65674 if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
65675 v2 = -v1;
65676 DUK_TVAL_SET_FASTINT(tv_x, v2); /* no refcount changes */
65677 return;
65678 }
65679 } else {
65680 /* ToNumber() for a fastint is a no-op. */
65681 DUK_ASSERT(opcode == DUK_EXTRAOP_UNP);
65682 return;
65683 }
65684 /* fall through if overflow etc */
65685 }
65686#endif /* DUK_USE_FASTINT */
65687
65688 if (!DUK_TVAL_IS_NUMBER(tv_x)) {
65689 duk_to_number(ctx, idx_x); /* side effects, perform in-place */
65690 tv_x = DUK_GET_TVAL_POSIDX(ctx, idx_x);
65691 DUK_ASSERT(tv_x != NULL);
65693 }
65694
65695 d1 = DUK_TVAL_GET_NUMBER(tv_x);
65696 if (opcode == DUK_EXTRAOP_UNM) {
65697 du.d = -d1;
65698 } else {
65699 /* ToNumber() for a double is a no-op. */
65701 du.d = d1;
65702 }
65703 DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du); /* mandatory if du.d is a NaN */
65704
65706
65707#if defined(DUK_USE_FASTINT)
65708 /* Unary plus is used to force a fastint check, so must include
65709 * downgrade check.
65710 */
65711 DUK_TVAL_SET_NUMBER_CHKFAST(tv_x, du.d); /* no refcount changes */
65712#else
65713 DUK_TVAL_SET_NUMBER(tv_x, du.d); /* no refcount changes */
65714#endif
65715}
65716
65718 /*
65719 * E5 Section 11.4.8
65720 */
65721
65722 duk_context *ctx = (duk_context *) thr;
65723 duk_tval *tv_z;
65724 duk_int32_t i1, i2;
65725#if !defined(DUK_USE_FASTINT)
65726 duk_double_t d2;
65727#endif
65728
65729 DUK_ASSERT(thr != NULL);
65730 DUK_ASSERT(ctx != NULL);
65731 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65732 DUK_ASSERT_DISABLE(idx_z >= 0);
65733 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65734
65735#if defined(DUK_USE_FASTINT)
65736 if (DUK_TVAL_IS_FASTINT(tv_x)) {
65737 i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
65738 }
65739 else
65740#endif /* DUK_USE_FASTINT */
65741 {
65742 duk_push_tval(ctx, tv_x);
65743 i1 = duk_to_int32(ctx, -1);
65744 duk_pop(ctx);
65745 }
65746
65747 i2 = ~i1;
65748
65749#if defined(DUK_USE_FASTINT)
65750 /* Result is always fastint compatible. */
65751 tv_z = thr->valstack_bottom + idx_z;
65752 DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv_z, i2); /* side effects */
65753#else
65754 d2 = (duk_double_t) i2;
65755
65756 DUK_ASSERT(!DUK_ISNAN(d2)); /* 'val' is never NaN, so no need to normalize */
65757 DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2); /* always normalized */
65758
65759 tv_z = thr->valstack_bottom + idx_z;
65760 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d2); /* side effects */
65761#endif
65762}
65763
65765 /*
65766 * E5 Section 11.4.9
65767 */
65768
65769 duk_bool_t res;
65770
65771 DUK_ASSERT(thr != NULL);
65772 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65773 DUK_ASSERT(tv_z != NULL); /* reg */
65774
65775 DUK_UNREF(thr); /* w/o refcounts */
65776
65777 /* ToBoolean() does not require any operations with side effects so
65778 * we can do it efficiently. For footprint it would be better to use
65779 * duk_js_toboolean() and then push+replace to the result slot.
65780 */
65781 res = duk_js_toboolean(tv_x); /* does not modify tv_x */
65782 DUK_ASSERT(res == 0 || res == 1);
65783 res ^= 1;
65784 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv_z, res); /* side effects */
65786
65787/*
65788 * Longjmp and other control flow transfer for the bytecode executor.
65789 *
65790 * The longjmp handler can handle all longjmp types: error, yield, and
65791 * resume (pseudotypes are never actually thrown).
65793 * Error policy for longjmp: should not ordinarily throw errors; if errors
65794 * occur (e.g. due to out-of-memory) they bubble outwards rather than being
65795 * handled recursively.
65796 */
65797
65798#define DUK__LONGJMP_RESTART 0 /* state updated, restart bytecode execution */
65799#define DUK__LONGJMP_RETHROW 1 /* exit bytecode executor by rethrowing an error to caller */
65800
65801#define DUK__RETHAND_RESTART 0 /* state updated, restart bytecode execution */
65802#define DUK__RETHAND_FINISHED 1 /* exit bytecode execution with return value */
65803
65804/* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
65805 * top are combined into one pass.
65806 */
65807
65808/* Reconfigure value stack for return to an Ecmascript function at 'act_idx'. */
65810 duk_activation *act;
65811 duk_hcompiledfunction *h_func;
65812 duk_idx_t clamp_top;
65813
65814 DUK_ASSERT(thr != NULL);
65815 DUK_ASSERT_DISABLE(act_idx >= 0); /* unsigned */
65816 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
65818 DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0); /* unsigned */
65819
65820 /* Clamp so that values at 'clamp_top' and above are wiped and won't
65821 * retain reachable garbage. Then extend to 'nregs' because we're
65822 * returning to an Ecmascript function.
65823 */
65824
65825 act = thr->callstack + act_idx;
65826 h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
65827
65829 DUK_ASSERT(act->idx_retval >= act->idx_bottom);
65830 clamp_top = (duk_idx_t) (act->idx_retval - act->idx_bottom + 1); /* +1 = one retval */
65831 duk_set_top((duk_context *) thr, clamp_top);
65832 act = NULL;
65833
65834 (void) duk_valstack_resize_raw((duk_context *) thr,
65835 (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
65836 h_func->nregs + /* reg count */
65837 DUK_VALSTACK_INTERNAL_EXTRA, /* + spare */
65838 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
65839 0 /* no compact */ |
65841
65842 duk_set_top((duk_context *) thr, h_func->nregs);
65843}
65844
65846 duk_activation *act;
65847 duk_catcher *cat;
65848 duk_hcompiledfunction *h_func;
65849 duk_idx_t clamp_top;
65850
65851 DUK_ASSERT(thr != NULL);
65852 DUK_ASSERT_DISABLE(act_idx >= 0); /* unsigned */
65853 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
65855 DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0); /* unsigned */
65856
65857 act = thr->callstack + act_idx;
65858 cat = thr->catchstack + cat_idx;
65859 h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
65860
65861 thr->valstack_bottom = thr->valstack + act->idx_bottom;
65862 DUK_ASSERT(cat->idx_base >= act->idx_bottom);
65863 clamp_top = (duk_idx_t) (cat->idx_base - act->idx_bottom + 2); /* +2 = catcher value, catcher lj_type */
65864 duk_set_top((duk_context *) thr, clamp_top);
65865 act = NULL;
65866 cat = NULL;
65867
65868 (void) duk_valstack_resize_raw((duk_context *) thr,
65869 (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
65870 h_func->nregs + /* reg count */
65871 DUK_VALSTACK_INTERNAL_EXTRA, /* + spare */
65872 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
65873 0 /* no compact */ |
65875
65876 duk_set_top((duk_context *) thr, h_func->nregs);
65877}
65878
65879/* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type. */
65880DUK_LOCAL void duk__set_catcher_regs(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
65881 duk_tval *tv1;
65882
65883 DUK_ASSERT(thr != NULL);
65884 DUK_ASSERT(tv_val_unstable != NULL);
65885
65886 tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base;
65887 DUK_ASSERT(tv1 < thr->valstack_top);
65888 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */
65889
65890 tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base + 1;
65891 DUK_ASSERT(tv1 < thr->valstack_top);
65892
65893 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) lj_type); /* side effects */
65894}
65895
65896DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
65897 duk_context *ctx;
65898 duk_activation *act;
65899
65900 DUK_ASSERT(thr != NULL);
65901 DUK_ASSERT(tv_val_unstable != NULL);
65902 ctx = (duk_context *) thr;
65903
65904 duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
65905
65906 duk_hthread_catchstack_unwind(thr, cat_idx + 1);
65908
65909 DUK_ASSERT(thr->callstack_top >= 1);
65912
65913 duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
65914
65915 DUK_ASSERT(thr->callstack_top >= 1);
65916 act = thr->callstack + thr->callstack_top - 1;
65917 act->curr_pc = thr->catchstack[cat_idx].pc_base + 0; /* +0 = catch */
65918 act = NULL;
65919
65920 /*
65921 * If entering a 'catch' block which requires an automatic
65922 * catch variable binding, create the lexical environment.
65923 *
65924 * The binding is mutable (= writable) but not deletable.
65925 * Step 4 for the catch production in E5 Section 12.14;
65926 * no value is given for CreateMutableBinding 'D' argument,
65927 * which implies the binding is not deletable.
65928 */
65929
65930 if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(&thr->catchstack[cat_idx])) {
65931 duk_hobject *new_env;
65932 duk_hobject *act_lex_env;
65933
65934 DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding"));
65935
65936 /* Note: 'act' is dangerous here because it may get invalidate at many
65937 * points, so we re-lookup it multiple times.
65938 */
65939 DUK_ASSERT(thr->callstack_top >= 1);
65940 act = thr->callstack + thr->callstack_top - 1;
65941
65942 if (act->lex_env == NULL) {
65943 DUK_ASSERT(act->var_env == NULL);
65944 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
65945
65946 /* this may have side effects, so re-lookup act */
65948 act = thr->callstack + thr->callstack_top - 1;
65949 }
65950 DUK_ASSERT(act->lex_env != NULL);
65951 DUK_ASSERT(act->var_env != NULL);
65953 DUK_UNREF(act); /* unreferenced without assertions */
65954
65955 act = thr->callstack + thr->callstack_top - 1;
65956 act_lex_env = act->lex_env;
65957 act = NULL; /* invalidated */
65958
65962 act_lex_env);
65963 new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
65964 DUK_ASSERT(new_env != NULL);
65965 DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
65966
65967 /* Note: currently the catch binding is handled without a register
65968 * binding because we don't support dynamic register bindings (they
65969 * must be fixed for an entire function). So, there is no need to
65970 * record regbases etc.
65971 */
65972
65973 DUK_ASSERT(thr->catchstack[cat_idx].h_varname != NULL);
65974 duk_push_hstring(ctx, thr->catchstack[cat_idx].h_varname);
65975 duk_push_tval(ctx, thr->valstack + thr->catchstack[cat_idx].idx_base);
65976 duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_W); /* writable, not configurable */
65977
65978 act = thr->callstack + thr->callstack_top - 1;
65979 act->lex_env = new_env;
65980 DUK_HOBJECT_INCREF(thr, new_env); /* reachable through activation */
65981
65982 DUK_CAT_SET_LEXENV_ACTIVE(&thr->catchstack[cat_idx]);
65983
65984 duk_pop(ctx);
65985
65986 DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
65987 }
65988
65990}
65991
65992DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
65993 duk_activation *act;
65994
65995 DUK_ASSERT(thr != NULL);
65996 DUK_ASSERT(tv_val_unstable != NULL);
65997
65998 duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
65999
66000 duk_hthread_catchstack_unwind(thr, cat_idx + 1); /* cat_idx catcher is kept, even for finally */
66002
66003 DUK_ASSERT(thr->callstack_top >= 1);
66006
66007 duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
66008
66009 DUK_ASSERT(thr->callstack_top >= 1);
66010 act = thr->callstack + thr->callstack_top - 1;
66011 act->curr_pc = thr->catchstack[cat_idx].pc_base + 1; /* +1 = finally */
66012 act = NULL;
66013
66015}
66016
66018 duk_activation *act;
66019
66020 DUK_ASSERT(thr != NULL);
66021
66022 DUK_ASSERT(thr->callstack_top >= 1);
66023 act = thr->callstack + thr->callstack_top - 1;
66024
66027
66028 /* +0 = break, +1 = continue */
66029 act->curr_pc = thr->catchstack[cat_idx].pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
66030 act = NULL; /* invalidated */
66031
66032 duk_hthread_catchstack_unwind(thr, cat_idx + 1); /* keep label catcher */
66033 /* no need to unwind callstack */
66034
66035 /* valstack should not need changes */
66036#if defined(DUK_USE_ASSERTIONS)
66037 DUK_ASSERT(thr->callstack_top >= 1);
66038 act = thr->callstack + thr->callstack_top - 1;
66041#endif
66042}
66043
66044/* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
66045 * when a RETURN opcode terminates a thread and yields to the resumer.
66046 */
66047DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_size_t act_idx, duk_tval *tv_val_unstable) {
66048 duk_tval *tv1;
66049
66050 DUK_ASSERT(thr != NULL);
66051 DUK_ASSERT(resumer != NULL);
66052 DUK_ASSERT(tv_val_unstable != NULL);
66053 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + act_idx) != NULL);
66054 DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + act_idx))); /* resume caller must be an ecmascript func */
66055
66056 tv1 = resumer->valstack + resumer->callstack[act_idx].idx_retval; /* return value from Duktape.Thread.resume() */
66057 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */
66058
66059 duk_hthread_callstack_unwind(resumer, act_idx + 1); /* unwind to 'resume' caller */
66060
66061 /* no need to unwind catchstack */
66062 duk__reconfig_valstack_ecma_return(resumer, act_idx);
66063
66064 /* caller must change active thread, and set thr->resumer to NULL */
66065}
66066
66069 duk_hthread *entry_thread,
66070 duk_size_t entry_callstack_top) {
66071 duk_size_t entry_callstack_index;
66073
66074 DUK_ASSERT(thr != NULL);
66075 DUK_ASSERT(entry_thread != NULL);
66076 DUK_ASSERT(entry_callstack_top > 0); /* guarantees entry_callstack_top - 1 >= 0 */
66077
66078 entry_callstack_index = entry_callstack_top - 1;
66079
66080 /* 'thr' is the current thread, as no-one resumes except us and we
66081 * switch 'thr' in that case.
66082 */
66083 DUK_ASSERT(thr == thr->heap->curr_thread);
66084
66085 /*
66086 * (Re)try handling the longjmp.
66087 *
66088 * A longjmp handler may convert the longjmp to a different type and
66089 * "virtually" rethrow by goto'ing to 'check_longjmp'. Before the goto,
66090 * the following must be updated:
66091 * - the heap 'lj' state
66092 * - 'thr' must reflect the "throwing" thread
66093 */
66094
66095 check_longjmp:
66096
66097 DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld",
66098 (long) thr->heap->lj.type,
66099 (duk_tval *) &thr->heap->lj.value1,
66100 (duk_tval *) &thr->heap->lj.value2,
66101 (long) thr->heap->lj.iserror));
66102
66103 switch (thr->heap->lj.type) {
66104
66105 case DUK_LJ_TYPE_RESUME: {
66106 /*
66107 * Note: lj.value1 is 'value', lj.value2 is 'resumee'.
66108 * This differs from YIELD.
66109 */
66110
66111 duk_tval *tv;
66112 duk_tval *tv2;
66113 duk_size_t act_idx;
66114 duk_hthread *resumee;
66115
66116 /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
66117
66118 DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged by Duktape.Thread.resume() */
66119 DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66124 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* an Ecmascript function */
66125 DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66126
66127 tv = &thr->heap->lj.value2; /* resumee */
66131 resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
66132
66133 DUK_ASSERT(resumee != NULL);
66134 DUK_ASSERT(resumee->resumer == NULL);
66136 resumee->state == DUK_HTHREAD_STATE_YIELDED); /* checked by Duktape.Thread.resume() */
66138 resumee->callstack_top >= 2); /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */
66140 (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1) != NULL &&
66142 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1))->func == duk_bi_thread_yield));
66144 (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2) != NULL &&
66145 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2)))); /* an Ecmascript function */
66147 (resumee->callstack + resumee->callstack_top - 2)->idx_retval >= 0); /* idx_retval unsigned */
66149 resumee->callstack_top == 0); /* INACTIVE: no activation, single function value on valstack */
66151 (resumee->valstack_top == resumee->valstack + 1 &&
66152 DUK_TVAL_IS_OBJECT(resumee->valstack_top - 1) &&
66154
66155 if (thr->heap->lj.iserror) {
66156 /*
66157 * Throw the error in the resumed thread's context; the
66158 * error value is pushed onto the resumee valstack.
66159 *
66160 * Note: the callstack of the target may empty in this case
66161 * too (i.e. the target thread has never been resumed). The
66162 * value stack will contain the initial function in that case,
66163 * which we simply ignore.
66164 */
66165
66166 resumee->resumer = thr;
66169 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66170 thr = resumee;
66171
66172 thr->heap->lj.type = DUK_LJ_TYPE_THROW;
66173
66174 /* thr->heap->lj.value1 is already the value to throw */
66175 /* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
66176
66177 DUK_ASSERT(thr->heap->lj.iserror); /* already set */
66178
66179 DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
66180 goto check_longjmp;
66181 } else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
66182 act_idx = resumee->callstack_top - 2; /* Ecmascript function */
66183 DUK_ASSERT_DISABLE(resumee->callstack[act_idx].idx_retval >= 0); /* unsigned */
66184
66185 tv = resumee->valstack + resumee->callstack[act_idx].idx_retval; /* return value from Duktape.Thread.yield() */
66186 DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
66187 tv2 = &thr->heap->lj.value1;
66188 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2); /* side effects */
66189
66190 duk_hthread_callstack_unwind(resumee, act_idx + 1); /* unwind to 'yield' caller */
66191
66192 /* no need to unwind catchstack */
66193
66194 duk__reconfig_valstack_ecma_return(resumee, act_idx);
66195
66196 resumee->resumer = thr;
66199 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66200#if 0
66201 thr = resumee; /* not needed, as we exit right away */
66202#endif
66203 DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
66204 retval = DUK__LONGJMP_RESTART;
66205 goto wipe_and_return;
66206 } else {
66207 duk_small_uint_t call_flags;
66208 duk_bool_t setup_rc;
66209
66210 /* resumee: [... initial_func] (currently actually: [initial_func]) */
66211
66212 duk_push_undefined((duk_context *) resumee);
66213 tv = &thr->heap->lj.value1;
66214 duk_push_tval((duk_context *) resumee, tv);
66215
66216 /* resumee: [... initial_func undefined(= this) resume_value ] */
66217
66218 call_flags = DUK_CALL_FLAG_IS_RESUME; /* is resume, not a tail call */
66219
66220 setup_rc = duk_handle_ecma_call_setup(resumee,
66221 1, /* num_stack_args */
66222 call_flags); /* call_flags */
66223 if (setup_rc == 0) {
66224 /* Shouldn't happen but check anyway. */
66226 }
66227
66228 resumee->resumer = thr;
66231 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66232#if 0
66233 thr = resumee; /* not needed, as we exit right away */
66234#endif
66235 DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
66236 retval = DUK__LONGJMP_RESTART;
66237 goto wipe_and_return;
66238 }
66240 break; /* never here */
66241 }
66242
66243 case DUK_LJ_TYPE_YIELD: {
66244 /*
66245 * Currently only allowed only if yielding thread has only
66246 * Ecmascript activations (except for the Duktape.Thread.yield()
66247 * call at the callstack top) and none of them constructor
66248 * calls.
66249 *
66250 * This excludes the 'entry' thread which will always have
66251 * a preventcount > 0.
66252 */
66253
66254 duk_hthread *resumer;
66255
66256 /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
66257
66258 DUK_ASSERT(thr != entry_thread); /* Duktape.Thread.yield() should prevent */
66259 DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged from Duktape.Thread.yield() */
66260 DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.yield() activation */
66265 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* an Ecmascript function */
66266 DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66267
66268 resumer = thr->resumer;
66269
66270 DUK_ASSERT(resumer != NULL);
66271 DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED); /* written by a previous RESUME handling */
66272 DUK_ASSERT(resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66273 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1) != NULL &&
66275 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1))->func == duk_bi_thread_resume);
66276 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2) != NULL &&
66277 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2))); /* an Ecmascript function */
66278 DUK_ASSERT_DISABLE((resumer->callstack + resumer->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66279
66280 if (thr->heap->lj.iserror) {
66282 thr->resumer = NULL;
66284 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66285 thr = resumer;
66286
66287 thr->heap->lj.type = DUK_LJ_TYPE_THROW;
66288 /* lj.value1 is already set */
66289 DUK_ASSERT(thr->heap->lj.iserror); /* already set */
66290
66291 DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
66292 goto check_longjmp;
66293 } else {
66294 duk__handle_yield(thr, resumer, resumer->callstack_top - 2, &thr->heap->lj.value1);
66295
66297 thr->resumer = NULL;
66299 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66300#if 0
66301 thr = resumer; /* not needed, as we exit right away */
66302#endif
66303
66304 DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
66305 retval = DUK__LONGJMP_RESTART;
66306 goto wipe_and_return;
66307 }
66309 break; /* never here */
66310 }
66311
66312 case DUK_LJ_TYPE_THROW: {
66313 /*
66314 * Three possible outcomes:
66315 * * A try or finally catcher is found => resume there.
66316 * (or)
66317 * * The error propagates to the bytecode executor entry
66318 * level (and we're in the entry thread) => rethrow
66319 * with a new longjmp(), after restoring the previous
66320 * catchpoint.
66321 * * The error is not caught in the current thread, so
66322 * the thread finishes with an error. This works like
66323 * a yielded error, except that the thread is finished
66324 * and can no longer be resumed. (There is always a
66325 * resumer in this case.)
66326 *
66327 * Note: until we hit the entry level, there can only be
66328 * Ecmascript activations.
66329 */
66330
66331 duk_catcher *cat;
66332 duk_hthread *resumer;
66333
66334 cat = thr->catchstack + thr->catchstack_top - 1;
66335 while (cat >= thr->catchstack) {
66336 if (thr == entry_thread &&
66337 cat->callstack_index < entry_callstack_index) {
66338 /* entry level reached */
66339 break;
66340 }
66341
66342 if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
66344
66346 cat - thr->catchstack,
66347 &thr->heap->lj.value1,
66349
66350 DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
66351 retval = DUK__LONGJMP_RESTART;
66352 goto wipe_and_return;
66353 }
66354
66355 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
66358
66360 cat - thr->catchstack,
66361 &thr->heap->lj.value1,
66363
66364 DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
66365 retval = DUK__LONGJMP_RESTART;
66366 goto wipe_and_return;
66367 }
66368
66369 cat--;
66370 }
66371
66372 if (thr == entry_thread) {
66373 /* not caught by anything before entry level; rethrow and let the
66374 * final catcher unwind everything
66375 */
66376#if 0
66377 duk_hthread_catchstack_unwind(thr, (cat - thr->catchstack) + 1); /* leave 'cat' as top catcher (also works if catchstack exhausted) */
66378 duk_hthread_callstack_unwind(thr, entry_callstack_index + 1);
66379
66380#endif
66381 DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
66382 retval = DUK__LONGJMP_RETHROW;
66383 goto just_return;
66384 /* Note: MUST NOT wipe_and_return here, as heap->lj must remain intact */
66385 }
66386
66387 DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
66388
66389 /* not caught by current thread, thread terminates (yield error to resumer);
66390 * note that this may cause a cascade if the resumer terminates with an uncaught
66391 * exception etc (this is OK, but needs careful testing)
66392 */
66393
66394 DUK_ASSERT(thr->resumer != NULL);
66395 DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66398 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */
66400 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2))); /* an Ecmascript function */
66401
66402 resumer = thr->resumer;
66403
66404 /* reset longjmp */
66405
66406 DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW); /* already set */
66407 /* lj.value1 already set */
66408
66409 duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
66411
66412 thr->resumer = NULL;
66414 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66415 thr = resumer;
66416 goto check_longjmp;
66417 }
66418
66419 case DUK_LJ_TYPE_BREAK: /* pseudotypes, not used in actual longjmps */
66421 case DUK_LJ_TYPE_RETURN:
66422 case DUK_LJ_TYPE_NORMAL:
66423 default: {
66424 /* should never happen, but be robust */
66425 DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
66426 goto convert_to_internal_error;
66427 }
66428
66429 } /* end switch */
66430
66432
66433 wipe_and_return:
66434 /* this is not strictly necessary, but helps debugging */
66436 thr->heap->lj.iserror = 0;
66437
66438 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
66439 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
66440
66441 just_return:
66442 return retval;
66443
66444 convert_to_internal_error:
66445 /* This could also be thrown internally (set the error, goto check_longjmp),
66446 * but it's better for internal errors to bubble outwards so that we won't
66447 * infinite loop in this catchpoint.
66448 */
66451 return retval;
66452}
66453
66454/* Handle a BREAK/CONTINUE opcode. Avoid using longjmp() for BREAK/CONTINUE
66455 * handling because it has a measurable performance impact in ordinary
66456 * environments and an extreme impact in Emscripten (GH-342).
66457 */
66459 duk_uint_t label_id,
66460 duk_small_uint_t lj_type) {
66461 duk_catcher *cat;
66462 duk_size_t orig_callstack_index;
66463
66464 DUK_ASSERT(thr != NULL);
66465
66466 /*
66467 * Find a matching label catcher or 'finally' catcher in
66468 * the same function.
66469 *
66470 * A label catcher must always exist and will match unless
66471 * a 'finally' captures the break/continue first. It is the
66472 * compiler's responsibility to ensure that labels are used
66473 * correctly.
66474 */
66475
66476 /* Note: thr->catchstack_top may be 0, so that cat < thr->catchstack
66477 * initially. This is OK and intended.
66478 */
66479 cat = thr->catchstack + thr->catchstack_top - 1;
66480 DUK_ASSERT(thr->callstack_top > 0);
66481 orig_callstack_index = thr->callstack_top - 1;
66482
66483 DUK_DDD(DUK_DDDPRINT("handling break/continue with label=%ld, callstack index=%ld",
66484 (long) label_id, (long) cat->callstack_index));
66485
66486 while (cat >= thr->catchstack) {
66487 if (cat->callstack_index != orig_callstack_index) {
66488 break;
66489 }
66490 DUK_DDD(DUK_DDDPRINT("considering catcher %ld: type=%ld label=%ld",
66491 (long) (cat - thr->catchstack),
66492 (long) DUK_CAT_GET_TYPE(cat),
66493 (long) DUK_CAT_GET_LABEL(cat)));
66494
66495 if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
66497 duk_size_t cat_idx;
66498 duk_tval tv_tmp;
66499
66500 cat_idx = (duk_size_t) (cat - thr->catchstack); /* get before side effects */
66501
66502 DUK_TVAL_SET_FASTINT_U32(&tv_tmp, (duk_uint32_t) label_id);
66503 duk__handle_finally(thr, cat_idx, &tv_tmp, lj_type);
66504
66505 DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
66506 return;
66507 }
66509 (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
66510 duk_size_t cat_idx;
66511
66512 cat_idx = (duk_size_t) (cat - thr->catchstack);
66513 duk__handle_label(thr, cat_idx, lj_type);
66515 DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
66516 return;
66517 }
66518 cat--;
66519 }
66520
66521 /* should never happen, but be robust */
66522 DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
66524 return;
66525}
66526
66527/* Handle a RETURN opcode. Avoid using longjmp() for return handling because
66528 * it has a measurable performance impact in ordinary environments and an extreme
66529 * impact in Emscripten (GH-342). Return value is on value stack top.
66530 */
66532 duk_hthread *entry_thread,
66533 duk_size_t entry_callstack_top) {
66534 duk_tval *tv1;
66535 duk_tval *tv2;
66536 duk_hthread *resumer;
66537 duk_catcher *cat;
66538 duk_size_t new_cat_top;
66539 duk_size_t orig_callstack_index;
66540
66541 /* We can directly access value stack here. */
66542
66543 DUK_ASSERT(thr != NULL);
66544 DUK_ASSERT(entry_thread != NULL);
66545 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66546 tv1 = thr->valstack_top - 1;
66547 DUK_TVAL_CHKFAST_INPLACE(tv1); /* fastint downgrade check for return values */
66548
66549 /*
66550 * Four possible outcomes:
66551 *
66552 * 1. A 'finally' in the same function catches the 'return'.
66553 * It may continue to propagate when 'finally' is finished,
66554 * or it may be neutralized by 'finally' (both handled by
66555 * ENDFIN).
66556 *
66557 * 2. The return happens at the entry level of the bytecode
66558 * executor, so return from the executor (in C stack).
66559 *
66560 * 3. There is a calling (Ecmascript) activation in the call
66561 * stack => return to it, in the same executor instance.
66562 *
66563 * 4. There is no calling activation, and the thread is
66564 * terminated. There is always a resumer in this case,
66565 * which gets the return value similarly to a 'yield'
66566 * (except that the current thread can no longer be
66567 * resumed).
66568 */
66569
66570 DUK_ASSERT(thr != NULL);
66571 DUK_ASSERT(thr->callstack_top >= 1);
66572 DUK_ASSERT(thr->catchstack != NULL);
66573
66574 /* XXX: does not work if thr->catchstack is NULL */
66575 /* XXX: does not work if thr->catchstack is allocated but lowest pointer */
66576
66577 cat = thr->catchstack + thr->catchstack_top - 1; /* may be < thr->catchstack initially */
66578 DUK_ASSERT(thr->callstack_top > 0); /* ensures callstack_top - 1 >= 0 */
66579 orig_callstack_index = thr->callstack_top - 1;
66580
66581 while (cat >= thr->catchstack) {
66582 if (cat->callstack_index != orig_callstack_index) {
66583 break;
66584 }
66585 if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
66587 duk_size_t cat_idx;
66588
66589 cat_idx = (duk_size_t) (cat - thr->catchstack); /* get before side effects */
66590
66591 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66592 duk__handle_finally(thr, cat_idx, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
66593
66594 DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
66595 return DUK__RETHAND_RESTART;
66596 }
66597 cat--;
66598 }
66599 /* If out of catchstack, cat = thr->catchstack - 1;
66600 * new_cat_top will be 0 in that case.
66601 */
66602 new_cat_top = (duk_size_t) ((cat + 1) - thr->catchstack);
66603 cat = NULL; /* avoid referencing, invalidated */
66604
66605 DUK_DDD(DUK_DDDPRINT("no catcher in catch stack, return to calling activation / yield"));
66606
66607 if (thr == entry_thread &&
66608 thr->callstack_top == entry_callstack_top) {
66609 /* Return to the bytecode executor caller which will unwind stacks.
66610 * Return value is already on the stack top: [ ... retval ].
66611 */
66612
66613 /* XXX: could unwind catchstack here, so that call handling
66614 * didn't need to do that?
66615 */
66616 DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
66617 return DUK__RETHAND_FINISHED;
66618 }
66619
66620 if (thr->callstack_top >= 2) {
66621 /* There is a caller; it MUST be an Ecmascript caller (otherwise it would
66622 * match entry level check)
66623 */
66624
66625 DUK_DDD(DUK_DDDPRINT("return to Ecmascript caller, idx_retval=%ld, lj_value1=%!T",
66626 (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
66627 (duk_tval *) &thr->heap->lj.value1));
66628
66629 DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* must be ecmascript */
66630
66631 tv1 = thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval;
66632 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66633 tv2 = thr->valstack_top - 1;
66634 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
66635
66636 DUK_DDD(DUK_DDDPRINT("return value at idx_retval=%ld is %!T",
66637 (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
66638 (duk_tval *) (thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval)));
66639
66640 duk_hthread_catchstack_unwind(thr, new_cat_top); /* leave 'cat' as top catcher (also works if catchstack exhausted) */
66643
66644 DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
66645 return DUK__RETHAND_RESTART;
66646 }
66647
66648 DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
66649
66650 DUK_ASSERT(thr->resumer != NULL);
66651 DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66654 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */
66656 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2))); /* an Ecmascript function */
66657 DUK_ASSERT_DISABLE((thr->resumer->callstack + thr->resumer->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66660
66661 resumer = thr->resumer;
66662
66663 /* Share yield longjmp handler. */
66664 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66665 duk__handle_yield(thr, resumer, resumer->callstack_top - 2, thr->valstack_top - 1);
66666
66667 duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
66669
66670 thr->resumer = NULL;
66672 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66673#if 0
66674 thr = resumer; /* not needed */
66675#endif
66676
66677 DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
66678 return DUK__RETHAND_RESTART;
66679}
66680
66681/*
66682 * Executor interrupt handling
66683 *
66684 * The handler is called whenever the interrupt countdown reaches zero
66685 * (or below). The handler must perform whatever checks are activated,
66686 * e.g. check for cumulative step count to impose an execution step
66687 * limit or check for breakpoints or other debugger interaction.
66688 *
66689 * When the actions are done, the handler must reinit the interrupt
66690 * init and counter values. The 'init' value must indicate how many
66691 * bytecode instructions are executed before the next interrupt. The
66692 * counter must interface with the bytecode executor loop. Concretely,
66693 * the new init value is normally one higher than the new counter value.
66694 * For instance, to execute exactly one bytecode instruction the init
66695 * value is set to 1 and the counter to 0. If an error is thrown by the
66696 * interrupt handler, the counters are set to the same value (e.g. both
66697 * to 0 to cause an interrupt when the next bytecode instruction is about
66698 * to be executed after error handling).
66699 *
66700 * Maintaining the init/counter value properly is important for accurate
66701 * behavior. For instance, executor step limit needs a cumulative step
66702 * count which is simply computed as a sum of 'init' values. This must
66703 * work accurately even when single stepping.
66704 */
66705
66706#if defined(DUK_USE_INTERRUPT_COUNTER)
66707
66708#define DUK__INT_NOACTION 0 /* no specific action, resume normal execution */
66709#define DUK__INT_RESTART 1 /* must "goto restart_execution", e.g. breakpoints changed */
66710
66711#if defined(DUK_USE_DEBUGGER_SUPPORT)
66712DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
66713 duk_context *ctx;
66714 duk_activation *act;
66715 duk_breakpoint *bp;
66716 duk_breakpoint **bp_active;
66717 duk_uint_fast32_t line = 0;
66718 duk_bool_t process_messages;
66719 duk_bool_t processed_messages = 0;
66720
66721 DUK_ASSERT(thr->heap->dbg_processing == 0); /* don't re-enter e.g. during Eval */
66722
66723 ctx = (duk_context *) thr;
66724 act = thr->callstack + thr->callstack_top - 1;
66725
66726 /* It might seem that replacing 'thr->heap' with just 'heap' below
66727 * might be a good idea, but it increases code size slightly
66728 * (probably due to unnecessary spilling) at least on x64.
66729 */
66730
66731 /*
66732 * Breakpoint and step state checks
66733 */
66734
66736 (thr->heap->dbg_step_thread == thr &&
66737 thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
66738 line = duk_debug_curr_line(thr);
66739
66740 if (act->prev_line != line) {
66741 /* Stepped? Step out is handled by callstack unwind. */
66742 if ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
66743 thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
66744 (thr->heap->dbg_step_thread == thr) &&
66745 (thr->heap->dbg_step_csindex == thr->callstack_top - 1) &&
66746 (line != thr->heap->dbg_step_startline)) {
66747 DUK_D(DUK_DPRINT("STEP STATE TRIGGERED PAUSE at line %ld",
66748 (long) line));
66749
66750 DUK_HEAP_SET_PAUSED(thr->heap);
66751 }
66752
66753 /* Check for breakpoints only on line transition.
66754 * Breakpoint is triggered when we enter the target
66755 * line from a different line, and the previous line
66756 * was within the same function.
66757 *
66758 * This condition is tricky: the condition used to be
66759 * that transition to -or across- the breakpoint line
66760 * triggered the breakpoint. This seems intuitively
66761 * better because it handles breakpoints on lines with
66762 * no emitted opcodes; but this leads to the issue
66763 * described in: https://github.com/svaarala/duktape/issues/263.
66764 */
66765 bp_active = thr->heap->dbg_breakpoints_active;
66766 for (;;) {
66767 bp = *bp_active++;
66768 if (bp == NULL) {
66769 break;
66770 }
66771
66772 DUK_ASSERT(bp->filename != NULL);
66773 if (act->prev_line != bp->line && line == bp->line) {
66774 DUK_D(DUK_DPRINT("BREAKPOINT TRIGGERED at %!O:%ld",
66775 (duk_heaphdr *) bp->filename, (long) bp->line));
66776
66777 DUK_HEAP_SET_PAUSED(thr->heap);
66778 }
66779 }
66780 } else {
66781 ;
66782 }
66783
66784 act->prev_line = line;
66785 }
66786
66787 /*
66788 * Rate limit check for sending status update or peeking into
66789 * the debug transport. Both can be expensive operations that
66790 * we don't want to do on every opcode.
66791 *
66792 * Making sure the interval remains reasonable on a wide variety
66793 * of targets and bytecode is difficult without a timestamp, so
66794 * we use a Date-provided timestamp for the rate limit check.
66795 * But since it's also expensive to get a timestamp, a bytecode
66796 * counter is used to rate limit getting timestamps.
66797 */
66798
66799 process_messages = 0;
66800 if (thr->heap->dbg_state_dirty || thr->heap->dbg_paused || thr->heap->dbg_detaching) {
66801 /* Enter message processing loop for sending Status notifys and
66802 * to finish a pending detach.
66803 */
66804 process_messages = 1;
66805 }
66806
66807 /* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
66808 thr->heap->dbg_exec_counter += thr->interrupt_init;
66809 if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
66810 /* Overflow of the execution counter is fine and doesn't break
66811 * anything here.
66812 */
66813
66814 duk_double_t now, diff_last;
66815
66816 thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
66817 now = DUK_USE_DATE_GET_NOW(ctx);
66818
66819 diff_last = now - thr->heap->dbg_last_time;
66820 if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
66821 /* Negative value checked so that a "time jump" works
66822 * reasonably.
66823 *
66824 * Same interval is now used for status sending and
66825 * peeking.
66826 */
66827
66828 thr->heap->dbg_last_time = now;
66829 thr->heap->dbg_state_dirty = 1;
66830 process_messages = 1;
66831 }
66832 }
66833
66834 /*
66835 * Process messages and send status if necessary.
66836 *
66837 * If we're paused, we'll block for new messages. If we're not
66838 * paused, we'll process anything we can peek but won't block
66839 * for more. Detach (and re-attach) handling is all localized
66840 * to duk_debug_process_messages() too.
66841 *
66842 * Debugger writes outside the message loop may cause debugger
66843 * detach1 phase to run, after which dbg_read_cb == NULL and
66844 * dbg_detaching != 0. The message loop will finish the detach
66845 * by running detach2 phase, so enter the message loop also when
66846 * detaching.
66847 */
66848
66849 act = NULL; /* may be changed */
66850 if (process_messages) {
66851 DUK_ASSERT(thr->heap->dbg_processing == 0);
66852 processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
66853 DUK_ASSERT(thr->heap->dbg_processing == 0);
66854 }
66855
66856 /* Continue checked execution if there are breakpoints or we're stepping.
66857 * Also use checked execution if paused flag is active - it shouldn't be
66858 * because the debug message loop shouldn't terminate if it was. Step out
66859 * is handled by callstack unwind and doesn't need checked execution.
66860 * Note that debugger may have detached due to error or explicit request
66861 * above, so we must recheck attach status.
66862 */
66863
66864 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
66865 act = thr->callstack + thr->callstack_top - 1; /* relookup, may have changed */
66867 ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
66868 thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
66869 thr->heap->dbg_step_thread == thr &&
66870 thr->heap->dbg_step_csindex == thr->callstack_top - 1) ||
66871 thr->heap->dbg_paused) {
66872 *out_immediate = 1;
66873 }
66874
66875 /* If we processed any debug messages breakpoints may have
66876 * changed; restart execution to re-check active breakpoints.
66877 */
66878 if (processed_messages) {
66879 DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
66880 *out_interrupt_retval = DUK__INT_RESTART;
66881 }
66882 } else {
66883 DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
66884 }
66885}
66886#endif /* DUK_USE_DEBUGGER_SUPPORT */
66887
66888DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
66889 duk_int_t ctr;
66890 duk_activation *act;
66892 duk_bool_t immediate = 0;
66893 duk_small_uint_t retval;
66894
66895 DUK_ASSERT(thr != NULL);
66896 DUK_ASSERT(thr->heap != NULL);
66897 DUK_ASSERT(thr->callstack != NULL);
66898 DUK_ASSERT(thr->callstack_top > 0);
66899
66900#if defined(DUK_USE_DEBUG)
66901 thr->heap->inst_count_interrupt += thr->interrupt_init;
66902 DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
66903 "instruction counts: executor=%ld, interrupt=%ld",
66904 (long) thr->interrupt_counter, (long) thr->interrupt_init,
66905 (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
66906#endif
66907
66908 retval = DUK__INT_NOACTION;
66909 ctr = DUK_HTHREAD_INTCTR_DEFAULT;
66910
66911 /*
66912 * Avoid nested calls. Concretely this happens during debugging, e.g.
66913 * when we eval() an expression.
66914 *
66915 * Also don't interrupt if we're currently doing debug processing
66916 * (which can be initiated outside the bytecode executor) as this
66917 * may cause the debugger to be called recursively. Check required
66918 * for correct operation of throw intercept and other "exotic" halting
66919 * scenarios.
66920 */
66921
66922#if defined(DUK_USE_DEBUGGER_SUPPORT)
66923 if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
66924#else
66926#endif
66927 DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
66928
66929 /* Set a high interrupt counter; the original executor
66930 * interrupt invocation will rewrite before exiting.
66931 */
66932 thr->interrupt_init = ctr;
66933 thr->interrupt_counter = ctr - 1;
66934 return DUK__INT_NOACTION;
66935 }
66937
66938 act = thr->callstack + thr->callstack_top - 1;
66939
66942
66943 DUK_UNREF(fun);
66944
66945#if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
66946 /*
66947 * Execution timeout check
66948 */
66949
66950 if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
66951 /* Keep throwing an error whenever we get here. The unusual values
66952 * are set this way because no instruction is ever executed, we just
66953 * throw an error until all try/catch/finally and other catchpoints
66954 * have been exhausted. Duktape/C code gets control at each protected
66955 * call but whenever it enters back into Duktape the RangeError gets
66956 * raised. User exec timeout check must consistently indicate a timeout
66957 * until we've fully bubbled out of Duktape.
66958 */
66959 DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
66960 thr->interrupt_init = 0;
66961 thr->interrupt_counter = 0;
66963 DUK_ERROR_RANGE(thr, "execution timeout");
66964 }
66965#endif /* DUK_USE_EXEC_TIMEOUT_CHECK */
66966
66967#if defined(DUK_USE_DEBUGGER_SUPPORT)
66968 if (!thr->heap->dbg_processing &&
66969 (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
66970 /* Avoid recursive re-entry; enter when we're attached or
66971 * detaching (to finish off the pending detach).
66972 */
66973 duk__interrupt_handle_debugger(thr, &immediate, &retval);
66974 act = thr->callstack + thr->callstack_top - 1; /* relookup if changed */
66975 DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
66976 }
66977#endif /* DUK_USE_DEBUGGER_SUPPORT */
66978
66979 /*
66980 * Update the interrupt counter
66981 */
66982
66983 if (immediate) {
66984 /* Cause an interrupt after executing one instruction. */
66985 ctr = 1;
66986 }
66987
66988 /* The counter value is one less than the init value: init value should
66989 * indicate how many instructions are executed before interrupt. To
66990 * execute 1 instruction (after interrupt handler return), counter must
66991 * be 0.
66992 */
66993 DUK_ASSERT(ctr >= 1);
66994 thr->interrupt_init = ctr;
66995 thr->interrupt_counter = ctr - 1;
66997
66998 return retval;
66999}
67000#endif /* DUK_USE_INTERRUPT_COUNTER */
67001
67002/*
67003 * Debugger handling for executor restart
67004 *
67005 * Check for breakpoints, stepping, etc, and figure out if we should execute
67006 * in checked or normal mode. Note that we can't do this when an activation
67007 * is created, because breakpoint status (and stepping status) may change
67008 * later, so we must recheck every time we're executing an activation.
67009 * This primitive should be side effect free to avoid changes during check.
67010 */
67011
67012#if defined(DUK_USE_DEBUGGER_SUPPORT)
67013DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompiledfunction *fun) {
67014 duk_heap *heap;
67015 duk_tval *tv_tmp;
67016 duk_hstring *filename;
67017 duk_small_uint_t bp_idx;
67018 duk_breakpoint **bp_active;
67019
67020 DUK_ASSERT(thr != NULL);
67021 DUK_ASSERT(act != NULL);
67022 DUK_ASSERT(fun != NULL);
67023
67024 heap = thr->heap;
67025 bp_active = heap->dbg_breakpoints_active;
67026 act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
67027
67029 if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
67030 filename = DUK_TVAL_GET_STRING(tv_tmp);
67031
67032 /* Figure out all active breakpoints. A breakpoint is
67033 * considered active if the current function's fileName
67034 * matches the breakpoint's fileName, AND there is no
67035 * inner function that has matching line numbers
67036 * (otherwise a breakpoint would be triggered both
67037 * inside and outside of the inner function which would
67038 * be confusing). Example:
67039 *
67040 * function foo() {
67041 * print('foo');
67042 * function bar() { <-. breakpoints in these
67043 * print('bar'); | lines should not affect
67044 * } <-' foo() execution
67045 * bar();
67046 * }
67047 *
67048 * We need a few things that are only available when
67049 * debugger support is enabled: (1) a line range for
67050 * each function, and (2) access to the function
67051 * template to access the inner functions (and their
67052 * line ranges).
67053 *
67054 * It's important to have a narrow match for active
67055 * breakpoints so that we don't enter checked execution
67056 * when that's not necessary. For instance, if we're
67057 * running inside a certain function and there's
67058 * breakpoint outside in (after the call site), we
67059 * don't want to slow down execution of the function.
67060 */
67061
67062 for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
67063 duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
67064 duk_hobject **funcs, **funcs_end;
67065 duk_hcompiledfunction *inner_fun;
67066 duk_bool_t bp_match;
67067
67068 if (bp->filename == filename &&
67069 bp->line >= fun->start_line && bp->line <= fun->end_line) {
67070 bp_match = 1;
67071 DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
67072 "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
67074 (long) bp->line,
67075 DUK_HSTRING_GET_DATA(filename),
67076 (long) bp->line,
67077 (long) fun->start_line,
67078 (long) fun->end_line));
67079
67081 funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, fun);
67082 while (funcs != funcs_end) {
67083 inner_fun = (duk_hcompiledfunction *) *funcs;
67085 if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
67086 DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
67087 bp_match = 0;
67088 break;
67089 }
67090 funcs++;
67091 }
67092
67093 if (bp_match) {
67094 /* No need to check for size of bp_active list,
67095 * it's always larger than maximum number of
67096 * breakpoints.
67097 */
67099 *bp_active = heap->dbg_breakpoints + bp_idx;
67100 bp_active++;
67101 }
67102 }
67103 }
67104 }
67105
67106 *bp_active = NULL; /* terminate */
67107
67108 DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
67109
67110 /* Force pause if we were doing "step into" in another activation. */
67111 if (thr->heap->dbg_step_thread != NULL &&
67112 thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO &&
67113 (thr->heap->dbg_step_thread != thr ||
67114 thr->heap->dbg_step_csindex != thr->callstack_top - 1)) {
67115 DUK_D(DUK_DPRINT("STEP INTO ACTIVE, FORCE PAUSED"));
67116 DUK_HEAP_SET_PAUSED(thr->heap);
67117 }
67118
67119 /* Force interrupt right away if we're paused or in "checked mode".
67120 * Step out is handled by callstack unwind.
67121 */
67123 thr->heap->dbg_paused ||
67124 (thr->heap->dbg_step_type != DUK_STEP_TYPE_OUT &&
67125 thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
67126 /* We'll need to interrupt early so recompute the init
67127 * counter to reflect the number of bytecode instructions
67128 * executed so that step counts for e.g. debugger rate
67129 * limiting are accurate.
67130 */
67131 DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
67132 thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
67133 thr->interrupt_counter = 0;
67134 }
67135}
67136#endif /* DUK_USE_DEBUGGER_SUPPORT */
67137
67138/*
67139 * Ecmascript bytecode executor.
67140 *
67141 * Resume execution for the current thread from its current activation.
67142 * Returns when execution would return from the entry level activation,
67143 * leaving a single return value on top of the stack. Function calls
67144 * and thread resumptions are handled internally. If an error occurs,
67145 * a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
67146 * setjmp() jmpbuf.
67147 *
67148 * Ecmascript function calls and coroutine resumptions are handled
67149 * internally (by the outer executor function) without recursive C calls.
67150 * Other function calls are handled using duk_handle_call(), increasing
67151 * C recursion depth.
67152 *
67153 * Abrupt completions (= long control tranfers) are handled either
67154 * directly by reconfiguring relevant stacks and restarting execution,
67155 * or via a longjmp. Longjmp-free handling is preferable for performance
67156 * (especially Emscripten performance), and is used for: break, continue,
67157 * and return.
67158 *
67159 * For more detailed notes, see doc/execution.rst.
67160 *
67161 * Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
67162 * and volatile.
67165/* Presence of 'fun' is config based, there's a marginal performance
67166 * difference and the best option is architecture dependent.
67167 */
67168#if defined(DUK_USE_EXEC_FUN_LOCAL)
67169#define DUK__FUN() fun
67170#else
67171#define DUK__FUN() ((duk_hcompiledfunction *) DUK_ACT_GET_FUNC((thr)->callstack + (thr)->callstack_top - 1))
67172#endif
67173#define DUK__STRICT() (DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
67174
67175/* Reg/const access macros: these are very footprint and performance sensitive
67176 * so modify with care.
67178#define DUK__REG(x) (*(thr->valstack_bottom + (x)))
67179#define DUK__REGP(x) (thr->valstack_bottom + (x))
67180#define DUK__CONST(x) (*(consts + (x)))
67181#define DUK__CONSTP(x) (consts + (x))
67182#if 0
67183#define DUK__REGCONST(x) ((x) < DUK_BC_REGLIMIT ? DUK__REG((x)) : DUK__CONST((x) - DUK_BC_REGLIMIT))
67184#define DUK__REGCONSTP(x) ((x) < DUK_BC_REGLIMIT ? DUK__REGP((x)) : DUK__CONSTP((x) - DUK_BC_REGLIMIT))
67185#define DUK__REGCONST(x) *((((x) < DUK_BC_REGLIMIT ? thr->valstack_bottom : consts2) + (x)))
67186#define DUK__REGCONSTP(x) (((x) < DUK_BC_REGLIMIT ? thr->valstack_bottom : consts2) + (x))
67187#endif
67188/* This macro works when a regconst field is 9 bits, [0,0x1ff]. Adding
67189 * DUK_LIKELY/DUK_UNLIKELY increases code footprint and doesn't seem to
67190 * improve performance on x64 (and actually harms performance in some tests).
67191 */
67192#define DUK__RCISREG(x) (((x) & 0x100) == 0)
67193#define DUK__REGCONST(x) (*((DUK__RCISREG((x)) ? thr->valstack_bottom : consts2) + (x)))
67194#define DUK__REGCONSTP(x) ((DUK__RCISREG((x)) ? thr->valstack_bottom : consts2) + (x))
67195
67196#ifdef DUK_USE_VERBOSE_EXECUTOR_ERRORS
67197#define DUK__INTERNAL_ERROR(msg) do { \
67198 DUK_ERROR_INTERNAL(thr, (msg)); \
67199 } while (0)
67200#else
67201#define DUK__INTERNAL_ERROR(msg) do { \
67202 goto internal_error; \
67203 } while (0)
67204#endif
67205
67206#define DUK__SYNC_CURR_PC() do { \
67207 duk_activation *act; \
67208 act = thr->callstack + thr->callstack_top - 1; \
67209 act->curr_pc = curr_pc; \
67210 } while (0)
67211#define DUK__SYNC_AND_NULL_CURR_PC() do { \
67212 duk_activation *act; \
67213 act = thr->callstack + thr->callstack_top - 1; \
67214 act->curr_pc = curr_pc; \
67215 thr->ptr_curr_pc = NULL; \
67216 } while (0)
67217
67219 duk_hthread *entry_thread,
67220 duk_size_t entry_callstack_top,
67221 duk_int_t entry_call_recursion_depth,
67222 duk_jmpbuf *entry_jmpbuf_ptr) {
67223 duk_small_uint_t lj_ret;
67224
67225 /* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
67226 * before longjmp.
67227 */
67228 DUK_ASSERT(heap->curr_thread != NULL);
67230
67231 /* XXX: signalling the need to shrink check (only if unwound) */
67232
67233 /* Must be restored here to handle e.g. yields properly. */
67234 heap->call_recursion_depth = entry_call_recursion_depth;
67235
67236 /* Switch to caller's setjmp() catcher so that if an error occurs
67237 * during error handling, it is always propagated outwards instead
67238 * of causing an infinite loop in our own handler.
67239 */
67240 heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
67241
67242 lj_ret = duk__handle_longjmp(heap->curr_thread, entry_thread, entry_callstack_top);
67243
67244 if (lj_ret == DUK__LONGJMP_RESTART) {
67245 /* Restart bytecode execution, possibly with a changed thread. */
67246 ;
67247 } else {
67248 /* Rethrow error to calling state. */
67250
67251 /* Longjmp handling has restored jmpbuf_ptr. */
67252 DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);
67253
67254 /* Thread may have changed, e.g. YIELD converted to THROW. */
67257 }
67258}
67259
67260/* Outer executor with setjmp/longjmp handling. */
67262 /* Entry level info. */
67263 duk_hthread *entry_thread;
67264 duk_size_t entry_callstack_top;
67265 duk_int_t entry_call_recursion_depth;
67266 duk_jmpbuf *entry_jmpbuf_ptr;
67267 duk_jmpbuf our_jmpbuf;
67268 duk_heap *heap;
67269
67270 DUK_ASSERT(exec_thr != NULL);
67271 DUK_ASSERT(exec_thr->heap != NULL);
67272 DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
67274 DUK_ASSERT(exec_thr->callstack_top >= 1); /* at least one activation, ours */
67275 DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1) != NULL);
67277
67278 entry_thread = exec_thr;
67279 heap = entry_thread->heap;
67280 entry_callstack_top = entry_thread->callstack_top;
67281 entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
67282 entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
67283
67284 /*
67285 * Note: we currently assume that the setjmp() catchpoint is
67286 * not re-entrant (longjmp() cannot be called more than once
67287 * for a single setjmp()).
67288 *
67289 * See doc/code-issues.rst for notes on variable assignment
67290 * before and after setjmp().
67291 */
67292
67293 for (;;) {
67294 heap->lj.jmpbuf_ptr = &our_jmpbuf;
67295 DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
67296
67297#if defined(DUK_USE_CPP_EXCEPTIONS)
67298 try {
67299#else
67300 DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
67301 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
67302#endif
67303 /* Execute bytecode until returned or longjmp(). */
67304 duk__js_execute_bytecode_inner(entry_thread, entry_callstack_top);
67305
67306 /* Successful return: restore jmpbuf and return to caller. */
67307 heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
67308
67309 return;
67310#if defined(DUK_USE_CPP_EXCEPTIONS)
67311 } catch (duk_internal_exception &exc) {
67312#else
67313 } else {
67314#endif
67315#if defined(DUK_USE_CPP_EXCEPTIONS)
67316 DUK_UNREF(exc);
67317#endif
67318 DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
67319
67321 entry_thread,
67322 entry_callstack_top,
67323 entry_call_recursion_depth,
67324 entry_jmpbuf_ptr);
67325 }
67326#if defined(DUK_USE_CPP_EXCEPTIONS)
67327 catch (std::exception &exc) {
67328 const char *what = exc.what();
67329 if (!what) {
67330 what = "unknown";
67331 }
67332 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
67333 try {
67334 DUK_ASSERT(heap->curr_thread != NULL);
67335 DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
67336 } catch (duk_internal_exception exc) {
67337 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
67338 DUK_UNREF(exc);
67340 entry_thread,
67341 entry_callstack_top,
67342 entry_call_recursion_depth,
67343 entry_jmpbuf_ptr);
67344 }
67345 } catch (...) {
67346 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
67347 try {
67348 DUK_ASSERT(heap->curr_thread != NULL);
67349 DUK_ERROR_API(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
67350 } catch (duk_internal_exception exc) {
67351 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
67352 DUK_UNREF(exc);
67354 entry_thread,
67355 entry_callstack_top,
67356 entry_call_recursion_depth,
67357 entry_jmpbuf_ptr);
67358 }
67359 }
67360#endif
67361 }
67362
67364}
67365
67366/* Inner executor, performance critical. */
67367DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top) {
67368 /* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
67369 * Critical for performance. It would be safest to make this volatile,
67370 * but that eliminates performance benefits; aliasing guarantees
67371 * should be enough though.
67372 */
67373 duk_instr_t *curr_pc; /* bytecode has a stable pointer */
67374
67375 /* Hot variables for interpretation. Critical for performance,
67376 * but must add sparingly to minimize register shuffling.
67377 */
67378 duk_hthread *thr; /* stable */
67379 duk_tval *consts; /* stable */
67380 duk_tval *consts2; /* stable; precalculated for faster lookups */
67382 /* 'funcs' is quite rarely used, so no local for it */
67383#if defined(DUK_USE_EXEC_FUN_LOCAL)
67385#else
67386 /* 'fun' is quite rarely used, so no local for it */
67387#endif
67388
67389#ifdef DUK_USE_INTERRUPT_COUNTER
67390 duk_int_t int_ctr;
67391#endif
67392
67393#ifdef DUK_USE_ASSERTIONS
67394 duk_size_t valstack_top_base; /* valstack top, should match before interpreting each op (no leftovers) */
67395#endif
67396
67397 /*
67398 * Restart execution by reloading thread state.
67399 *
67400 * Note that 'thr' and any thread configuration may have changed,
67401 * so all local variables are suspect and we need to reinitialize.
67402 *
67403 * The number of local variables should be kept to a minimum: if
67404 * the variables are spilled, they will need to be loaded from
67405 * memory anyway.
67406 *
67407 * Any 'goto restart_execution;' code path in opcode dispatch must
67408 * ensure 'curr_pc' is synced back to act->curr_pc before the goto
67409 * takes place.
67410 *
67411 * The interpreter must be very careful with memory pointers, as
67412 * many pointers are not guaranteed to be 'stable' and may be
67413 * reallocated and relocated on-the-fly quite easily (e.g. by a
67414 * memory allocation or a property access).
67415 *
67416 * The following are assumed to have stable pointers:
67417 * - the current thread
67418 * - the current function
67419 * - the bytecode, constant table, inner function table of the
67420 * current function (as they are a part of the function allocation)
67421 *
67422 * The following are assumed to have semi-stable pointers:
67423 * - the current activation entry: stable as long as callstack
67424 * is not changed (reallocated by growing or shrinking), or
67425 * by any garbage collection invocation (through finalizers)
67426 * - Note in particular that ANY DECREF can invalidate the
67427 * activation pointer, so for the most part a fresh lookup
67428 * is required
67429 *
67430 * The following are not assumed to have stable pointers at all:
67431 * - the value stack (registers) of the current thread
67432 * - the catch stack of the current thread
67433 *
67434 * See execution.rst for discussion.
67435 */
67436
67437 restart_execution:
67438
67439 /* Lookup current thread; use the stable 'entry_thread' for this to
67440 * avoid clobber warnings. Any valid, reachable 'thr' value would be
67441 * fine for this, so using 'entry_thread' is just to silence warnings.
67442 */
67443 thr = entry_thread->heap->curr_thread;
67444 DUK_ASSERT(thr != NULL);
67445 DUK_ASSERT(thr->callstack_top >= 1);
67448
67449 thr->ptr_curr_pc = &curr_pc;
67450
67451 /* Relookup and initialize dispatch loop variables. Debugger check. */
67452 {
67453 duk_activation *act;
67454#if !defined(DUK_USE_EXEC_FUN_LOCAL)
67456#endif
67457
67458 /* Assume interrupt init/counter are properly initialized here. */
67459 /* Assume that thr->valstack_bottom has been set-up before getting here. */
67460
67461 act = thr->callstack + thr->callstack_top - 1;
67463 DUK_ASSERT(fun != NULL);
67464 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
67465 consts = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, fun);
67466 DUK_ASSERT(consts != NULL);
67467 consts2 = consts - DUK_BC_REGLIMIT;
67468
67469#if defined(DUK_USE_DEBUGGER_SUPPORT)
67470 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) && !thr->heap->dbg_processing) {
67471 duk__executor_recheck_debugger(thr, act, fun);
67472 act = thr->callstack + thr->callstack_top - 1; /* relookup after side effects (no side effects currently however) */
67473 }
67474#endif /* DUK_USE_DEBUGGER_SUPPORT */
67475
67476#ifdef DUK_USE_ASSERTIONS
67477 valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
67478#endif
67479
67480 /* Set up curr_pc for opcode dispatch. */
67481 curr_pc = act->curr_pc;
67482 }
67483
67484 DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
67485 "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, catchstack_top=%ld, "
67486 "preventcount=%ld",
67487 (void *) thr,
67488 (long) (thr->callstack_top - 1),
67489 (void *) DUK__FUN(),
67490 (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
67491 (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
67492 (long) (thr->callstack_top - 1),
67493 (long) (thr->valstack_bottom - thr->valstack),
67494 (long) (thr->valstack_top - thr->valstack),
67495 (long) thr->catchstack_top,
67496 (long) thr->callstack_preventcount));
67497
67498 /* Dispatch loop. */
67499
67500 for (;;) {
67501 DUK_ASSERT(thr->callstack_top >= 1);
67502 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
67503 DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
67504
67505 /* Executor interrupt counter check, used to implement breakpoints,
67506 * debugging interface, execution timeouts, etc. The counter is heap
67507 * specific but is maintained in the current thread to make the check
67508 * as fast as possible. The counter is copied back to the heap struct
67509 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
67510 */
67511#if defined(DUK_USE_INTERRUPT_COUNTER)
67512 int_ctr = thr->interrupt_counter;
67513 if (DUK_LIKELY(int_ctr > 0)) {
67514 thr->interrupt_counter = int_ctr - 1;
67515 } else {
67516 /* Trigger at zero or below */
67517 duk_small_uint_t exec_int_ret;
67518
67519 /* Write curr_pc back for the debugger. */
67520 DUK_ASSERT(thr->callstack_top > 0);
67521 {
67522 duk_activation *act;
67523 act = thr->callstack + thr->callstack_top - 1;
67524 act->curr_pc = (duk_instr_t *) curr_pc;
67525 }
67526
67527 /* Force restart caused by a function return; must recheck
67528 * debugger breakpoints before checking line transitions,
67529 * see GH-303. Restart and then handle interrupt_counter
67530 * zero again.
67531 */
67532#if defined(DUK_USE_DEBUGGER_SUPPORT)
67533 if (thr->heap->dbg_force_restart) {
67534 DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution")); /* GH-303 */
67535 thr->heap->dbg_force_restart = 0;
67536 goto restart_execution;
67537 }
67538#endif
67539
67540 exec_int_ret = duk__executor_interrupt(thr);
67541 if (exec_int_ret == DUK__INT_RESTART) {
67542 /* curr_pc synced back above */
67543 goto restart_execution;
67544 }
67545 }
67546#endif /* DUK_USE_INTERRUPT_COUNTER */
67547#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
67548 /* For cross-checking during development: ensure dispatch count
67549 * matches cumulative interrupt counter init value sums.
67550 */
67551 thr->heap->inst_count_exec++;
67552#endif
67553
67554#if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
67555 {
67556 duk_activation *act;
67557 act = thr->callstack + thr->callstack_top - 1;
67560 DUK_UNREF(act); /* if debugging disabled */
67561
67562 DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld --> %!I",
67563 (long) (curr_pc - DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, DUK__FUN())),
67564 (unsigned long) *curr_pc,
67565 (long) DUK_DEC_OP(*curr_pc),
67566 (long) (thr->valstack_top - thr->valstack),
67567 (long) (thr->valstack_end - thr->valstack),
67568 (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
67569 (duk_instr_t) *curr_pc));
67570 }
67571#endif
67572
67573#if defined(DUK_USE_ASSERTIONS)
67574 /* Quite heavy assert: check valstack policy. Improper
67575 * shuffle instructions can write beyond valstack_top/end
67576 * so this check catches them in the act.
67577 */
67578 {
67579 duk_tval *tv;
67580 tv = thr->valstack_top;
67581 while (tv != thr->valstack_end) {
67583 tv++;
67584 }
67585 }
67586#endif
67587
67588 ins = *curr_pc++;
67589
67590 /* Typing: use duk_small_(u)int_fast_t when decoding small
67591 * opcode fields (op, A, B, C) and duk_(u)int_fast_t when
67592 * decoding larger fields (e.g. BC which is 18 bits). Use
67593 * unsigned variant by default, signed when the value is used
67594 * in signed arithmetic. Using variable names such as 'a', 'b',
67595 * 'c', 'bc', etc makes it easier to spot typing mismatches.
67596 */
67597
67598 /* XXX: the best typing needs to be validated by perf measurement:
67599 * e.g. using a small type which is the cast to a larger duk_idx_t
67600 * may be slower than declaring the variable as a duk_idx_t in the
67601 * first place.
67602 */
67603
67604 /* XXX: use macros for the repetitive tval/refcount handling. */
67605
67606 switch ((int) DUK_DEC_OP(ins)) {
67607 /* XXX: switch cast? */
67608
67609 case DUK_OP_LDREG: {
67611 duk_uint_fast_t bc;
67612 duk_tval *tv1, *tv2;
67613
67614 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67615 bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
67616 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
67617 break;
67618 }
67619
67620 case DUK_OP_STREG: {
67622 duk_uint_fast_t bc;
67623 duk_tval *tv1, *tv2;
67624
67625 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67626 bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
67627 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1); /* side effects */
67628 break;
67629 }
67630
67631 case DUK_OP_LDCONST: {
67633 duk_uint_fast_t bc;
67634 duk_tval *tv1, *tv2;
67635
67636 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67637 bc = DUK_DEC_BC(ins); tv2 = DUK__CONSTP(bc);
67638 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
67639 break;
67640 }
67641
67642 case DUK_OP_LDINT: {
67644 duk_int_fast_t bc;
67645 duk_tval *tv1;
67646#if defined(DUK_USE_FASTINT)
67647 duk_int32_t val;
67648#else
67649 duk_double_t val;
67650#endif
67651
67652#if defined(DUK_USE_FASTINT)
67653 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67654 bc = DUK_DEC_BC(ins); val = (duk_int32_t) (bc - DUK_BC_LDINT_BIAS);
67655 DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv1, val); /* side effects */
67656#else
67657 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67658 bc = DUK_DEC_BC(ins); val = (duk_double_t) (bc - DUK_BC_LDINT_BIAS);
67659 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv1, val); /* side effects */
67660#endif
67661 break;
67662 }
67663
67664 case DUK_OP_LDINTX: {
67666 duk_tval *tv1;
67667 duk_double_t val;
67668
67669 /* LDINTX is not necessarily in FASTINT range, so
67670 * no fast path for now.
67671 *
67672 * XXX: perhaps restrict LDINTX to fastint range, wider
67673 * range very rarely needed.
67674 */
67675
67676 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67678 val = DUK_TVAL_GET_NUMBER(tv1) * ((duk_double_t) (1L << DUK_BC_LDINTX_SHIFT)) +
67679 (duk_double_t) DUK_DEC_BC(ins);
67680#if defined(DUK_USE_FASTINT)
67682#else
67683 DUK_TVAL_SET_NUMBER(tv1, val);
67684#endif
67685 break;
67686 }
67687
67688 case DUK_OP_MPUTOBJ:
67689 case DUK_OP_MPUTOBJI: {
67690 duk_context *ctx = (duk_context *) thr;
67692 duk_tval *tv1;
67693 duk_hobject *obj;
67694 duk_uint_fast_t idx;
67696
67697 /* A -> register of target object
67698 * B -> first register of key/value pair list
67699 * C -> number of key/value pairs
67700 */
67701
67702 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67704 obj = DUK_TVAL_GET_OBJECT(tv1);
67705
67706 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
67707 if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
67708 duk_tval *tv_ind = DUK__REGP(idx);
67710 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67711 }
67712
67713 count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
67714
67715#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67716 if (DUK_UNLIKELY(idx + count * 2 > (duk_uint_fast_t) duk_get_top(ctx))) {
67717 /* XXX: use duk_is_valid_index() instead? */
67718 /* XXX: improve check; check against nregs, not against top */
67719 DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
67720 }
67721#endif
67722
67723 duk_push_hobject(ctx, obj);
67724
67725 while (count > 0) {
67726 /* XXX: faster initialization (direct access or better primitives) */
67727
67728 duk_push_tval(ctx, DUK__REGP(idx));
67729 DUK_ASSERT(duk_is_string(ctx, -1));
67730 duk_push_tval(ctx, DUK__REGP(idx + 1)); /* -> [... obj key value] */
67731 duk_xdef_prop_wec(ctx, -3); /* -> [... obj] */
67732
67733 count--;
67734 idx += 2;
67735 }
67736
67737 duk_pop(ctx); /* [... obj] -> [...] */
67738 break;
67739 }
67740
67741 case DUK_OP_MPUTARR:
67742 case DUK_OP_MPUTARRI: {
67743 duk_context *ctx = (duk_context *) thr;
67745 duk_tval *tv1;
67746 duk_hobject *obj;
67747 duk_uint_fast_t idx;
67749 duk_uint32_t arr_idx;
67750
67751 /* A -> register of target object
67752 * B -> first register of value data (start_index, value1, value2, ..., valueN)
67753 * C -> number of key/value pairs (N)
67754 */
67755
67756 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67758 obj = DUK_TVAL_GET_OBJECT(tv1);
67759 DUK_ASSERT(obj != NULL);
67760
67761 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
67762 if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
67763 duk_tval *tv_ind = DUK__REGP(idx);
67765 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67766 }
67767
67768 count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
67769
67770#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67771 if (idx + count + 1 > (duk_uint_fast_t) duk_get_top(ctx)) {
67772 /* XXX: use duk_is_valid_index() instead? */
67773 /* XXX: improve check; check against nregs, not against top */
67774 DUK__INTERNAL_ERROR("MPUTARR out of bounds");
67775 }
67776#endif
67777
67778 tv1 = DUK__REGP(idx);
67780 arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
67781 idx++;
67782
67783 duk_push_hobject(ctx, obj);
67784
67785 while (count > 0) {
67786 /* duk_xdef_prop() will define an own property without any array
67787 * special behaviors. We'll need to set the array length explicitly
67788 * in the end. For arrays with elisions, the compiler will emit an
67789 * explicit SETALEN which will update the length.
67790 */
67791
67792 /* XXX: because we're dealing with 'own' properties of a fresh array,
67793 * the array initializer should just ensure that the array has a large
67794 * enough array part and write the values directly into array part,
67795 * and finally set 'length' manually in the end (as already happens now).
67796 */
67797
67798 duk_push_tval(ctx, DUK__REGP(idx)); /* -> [... obj value] */
67799 duk_xdef_prop_index_wec(ctx, -2, arr_idx); /* -> [... obj] */
67800
67801 /* XXX: could use at least one fewer loop counters */
67802 count--;
67803 idx++;
67804 arr_idx++;
67805 }
67806
67807 /* XXX: E5.1 Section 11.1.4 coerces the final length through
67808 * ToUint32() which is odd but happens now as a side effect of
67809 * 'arr_idx' type.
67810 */
67811 duk_hobject_set_length(thr, obj, (duk_uint32_t) arr_idx);
67812
67813 duk_pop(ctx); /* [... obj] -> [...] */
67814 break;
67815 }
67816
67817 case DUK_OP_NEW:
67818 case DUK_OP_NEWI: {
67819 duk_context *ctx = (duk_context *) thr;
67821 duk_uint_fast_t idx;
67823
67824 /* A -> unused (reserved for flags, for consistency with DUK_OP_CALL)
67825 * B -> target register and start reg: constructor, arg1, ..., argN
67826 * (for DUK_OP_NEWI, 'b' is indirect)
67827 * C -> num args (N)
67828 */
67829
67830 /* duk_new() will call the constuctor using duk_handle_call().
67831 * A constructor call prevents a yield from inside the constructor,
67832 * even if the constructor is an Ecmascript function.
67833 */
67834
67835 /* Don't need to sync curr_pc here; duk_new() will do that
67836 * when it augments the created error.
67837 */
67838
67839 /* XXX: unnecessary copying of values? Just set 'top' to
67840 * b + c, and let the return handling fix up the stack frame?
67841 */
67842
67843 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
67844 if (DUK_DEC_OP(ins) == DUK_OP_NEWI) {
67845 duk_tval *tv_ind = DUK__REGP(idx);
67847 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67848 }
67849
67850#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67851 if (idx + c + 1 > (duk_uint_fast_t) duk_get_top(ctx)) {
67852 /* XXX: use duk_is_valid_index() instead? */
67853 /* XXX: improve check; check against nregs, not against top */
67854 DUK__INTERNAL_ERROR("NEW out of bounds");
67855 }
67856#endif
67857
67858 duk_require_stack(ctx, (duk_idx_t) c);
67859 duk_push_tval(ctx, DUK__REGP(idx));
67860 for (i = 0; i < c; i++) {
67861 duk_push_tval(ctx, DUK__REGP(idx + i + 1));
67862 }
67863 duk_new(ctx, (duk_idx_t) c); /* [... constructor arg1 ... argN] -> [retval] */
67864 DUK_DDD(DUK_DDDPRINT("NEW -> %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
67865 duk_replace(ctx, (duk_idx_t) idx);
67866
67867 /* When debugger is enabled, we need to recheck the activation
67868 * status after returning. This is now handled by call handling
67869 * and heap->dbg_force_restart.
67870 */
67871 break;
67872 }
67873
67874 case DUK_OP_REGEXP: {
67875#ifdef DUK_USE_REGEXP_SUPPORT
67876 duk_context *ctx = (duk_context *) thr;
67880
67881 /* A -> target register
67882 * B -> bytecode (also contains flags)
67883 * C -> escaped source
67884 */
67885
67887 duk_push_tval(ctx, DUK__REGCONSTP(b)); /* -> [ ... escaped_source bytecode ] */
67888 duk_regexp_create_instance(thr); /* -> [ ... regexp_instance ] */
67889 DUK_DDD(DUK_DDDPRINT("regexp instance: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
67890 duk_replace(ctx, (duk_idx_t) a);
67891#else
67892 /* The compiler should never emit DUK_OP_REGEXP if there is no
67893 * regexp support.
67894 */
67895 DUK__INTERNAL_ERROR("no regexp support");
67896#endif
67897
67898 break;
67899 }
67900
67901 case DUK_OP_CSREG:
67902 case DUK_OP_CSREGI: {
67903 /*
67904 * Assuming a register binds to a variable declared within this
67905 * function (a declarative binding), the 'this' for the call
67906 * setup is always 'undefined'. E5 Section 10.2.1.1.6.
67907 */
67908
67909 duk_context *ctx = (duk_context *) thr;
67910 duk_small_uint_fast_t b = DUK_DEC_B(ins); /* restricted to regs */
67911 duk_uint_fast_t idx;
67912
67913 /* A -> target register (A, A+1) for call setup
67914 * (for DUK_OP_CSREGI, 'a' is indirect)
67915 * B -> register containing target function (not type checked here)
67916 */
67917
67918 /* XXX: direct manipulation, or duk_replace_tval() */
67919
67920 /* Note: target registers a and a+1 may overlap with DUK__REGP(b).
67921 * Careful here.
67922 */
67923
67924 idx = (duk_uint_fast_t) DUK_DEC_A(ins);
67925 if (DUK_DEC_OP(ins) == DUK_OP_CSREGI) {
67926 duk_tval *tv_ind = DUK__REGP(idx);
67928 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67929 }
67930
67931#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67932 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
67933 /* XXX: use duk_is_valid_index() instead? */
67934 /* XXX: improve check; check against nregs, not against top */
67935 DUK__INTERNAL_ERROR("CSREG out of bounds");
67936 }
67937#endif
67938
67939 duk_push_tval(ctx, DUK__REGP(b));
67940 duk_replace(ctx, (duk_idx_t) idx);
67941 duk_push_undefined(ctx);
67942 duk_replace(ctx, (duk_idx_t) (idx + 1));
67943 break;
67944 }
67945
67946 case DUK_OP_GETVAR: {
67947 duk_context *ctx = (duk_context *) thr;
67948 duk_activation *act;
67950 duk_uint_fast_t bc = DUK_DEC_BC(ins);
67951 duk_tval *tv1;
67953
67954 tv1 = DUK__CONSTP(bc);
67957 DUK_ASSERT(name != NULL);
67958 DUK_DDD(DUK_DDDPRINT("GETVAR: '%!O'", (duk_heaphdr *) name));
67959 act = thr->callstack + thr->callstack_top - 1;
67960 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
67961
67962 duk_pop(ctx); /* 'this' binding is not needed here */
67963 duk_replace(ctx, (duk_idx_t) a);
67964 break;
67965 }
67966
67967 case DUK_OP_PUTVAR: {
67968 duk_activation *act;
67970 duk_uint_fast_t bc = DUK_DEC_BC(ins);
67971 duk_tval *tv1;
67973
67974 tv1 = DUK__CONSTP(bc);
67977 DUK_ASSERT(name != NULL);
67978
67979 /* XXX: putvar takes a duk_tval pointer, which is awkward and
67980 * should be reworked.
67981 */
67982
67983 tv1 = DUK__REGP(a); /* val */
67984 act = thr->callstack + thr->callstack_top - 1;
67985 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
67986 break;
67987 }
67988
67989 case DUK_OP_DECLVAR: {
67990 duk_activation *act;
67991 duk_context *ctx = (duk_context *) thr;
67995 duk_tval *tv1;
67997 duk_small_uint_t prop_flags;
67998 duk_bool_t is_func_decl;
67999 duk_bool_t is_undef_value;
68000
68001 tv1 = DUK__REGCONSTP(b);
68004 DUK_ASSERT(name != NULL);
68005
68006 is_undef_value = ((a & DUK_BC_DECLVAR_FLAG_UNDEF_VALUE) != 0);
68007 is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
68008
68009 /* XXX: declvar takes an duk_tval pointer, which is awkward and
68010 * should be reworked.
68011 */
68012
68013 /* Compiler is responsible for selecting property flags (configurability,
68014 * writability, etc).
68015 */
68016 prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
68017
68018 if (is_undef_value) {
68019 duk_push_undefined(ctx);
68020 } else {
68022 }
68023 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
68024
68025 act = thr->callstack + thr->callstack_top - 1;
68026 if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
68027 /* already declared, must update binding value */
68028 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
68029 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
68030 }
68031
68032 duk_pop(ctx);
68033 break;
68034 }
68035
68036 case DUK_OP_DELVAR: {
68037 duk_activation *act;
68038 duk_context *ctx = (duk_context *) thr;
68041 duk_tval *tv1;
68043 duk_bool_t rc;
68044
68045 tv1 = DUK__REGCONSTP(b);
68048 DUK_ASSERT(name != NULL);
68049 DUK_DDD(DUK_DDDPRINT("DELVAR '%!O'", (duk_heaphdr *) name));
68050 act = thr->callstack + thr->callstack_top - 1;
68051 rc = duk_js_delvar_activation(thr, act, name);
68052
68053 duk_push_boolean(ctx, rc);
68054 duk_replace(ctx, (duk_idx_t) a);
68055 break;
68056 }
68057
68058 case DUK_OP_CSVAR:
68059 case DUK_OP_CSVARI: {
68060 /* 'this' value:
68061 * E5 Section 6.b.i
68062 *
68063 * The only (standard) case where the 'this' binding is non-null is when
68064 * (1) the variable is found in an object environment record, and
68065 * (2) that object environment record is a 'with' block.
68066 *
68067 */
68068
68069 duk_context *ctx = (duk_context *) thr;
68070 duk_activation *act;
68072 duk_uint_fast_t idx;
68073 duk_tval *tv1;
68075
68076 tv1 = DUK__REGCONSTP(b);
68079 DUK_ASSERT(name != NULL);
68080 act = thr->callstack + thr->callstack_top - 1;
68081 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
68082
68083 /* Note: target registers a and a+1 may overlap with DUK__REGCONSTP(b)
68084 * and DUK__REGCONSTP(c). Careful here.
68085 */
68086
68087 idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68088 if (DUK_DEC_OP(ins) == DUK_OP_CSVARI) {
68089 duk_tval *tv_ind = DUK__REGP(idx);
68091 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68092 }
68093
68094#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68095 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68096 /* XXX: use duk_is_valid_index() instead? */
68097 /* XXX: improve check; check against nregs, not against top */
68098 DUK__INTERNAL_ERROR("CSVAR out of bounds");
68099 }
68100#endif
68101
68102 duk_replace(ctx, (duk_idx_t) (idx + 1)); /* 'this' binding */
68103 duk_replace(ctx, (duk_idx_t) idx); /* variable value (function, we hope, not checked here) */
68104 break;
68105 }
68106
68107 case DUK_OP_CLOSURE: {
68108 duk_context *ctx = (duk_context *) thr;
68109 duk_activation *act;
68112 duk_uint_fast_t bc = DUK_DEC_BC(ins);
68113 duk_hobject *fun_temp;
68114
68115 /* A -> target reg
68116 * BC -> inner function index
68117 */
68118
68119 DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
68120 (long) a, (long) bc, (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
68121
68122 DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
68124
68125 act = thr->callstack + thr->callstack_top - 1;
68127 fun_temp = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, fun)[bc];
68128 DUK_ASSERT(fun_temp != NULL);
68130
68131 DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
68132 (void *) fun_temp, (duk_heaphdr *) fun_temp));
68133
68134 if (act->lex_env == NULL) {
68135 DUK_ASSERT(act->var_env == NULL);
68137 }
68138 DUK_ASSERT(act->lex_env != NULL);
68139 DUK_ASSERT(act->var_env != NULL);
68140
68141 /* functions always have a NEWENV flag, i.e. they get a
68142 * new variable declaration environment, so only lex_env
68143 * matters here.
68144 */
68146 (duk_hcompiledfunction *) fun_temp,
68147 act->var_env,
68148 act->lex_env,
68149 1 /*add_auto_proto*/);
68150 duk_replace(ctx, (duk_idx_t) a);
68151
68152 break;
68153 }
68154
68155 case DUK_OP_GETPROP: {
68156 duk_context *ctx = (duk_context *) thr;
68160 duk_tval *tv_obj;
68161 duk_tval *tv_key;
68162 duk_bool_t rc;
68163
68164 /* A -> target reg
68165 * B -> object reg/const (may be const e.g. in "'foo'[1]")
68166 * C -> key reg/const
68167 */
68168
68169 tv_obj = DUK__REGCONSTP(b);
68170 tv_key = DUK__REGCONSTP(c);
68171 DUK_DDD(DUK_DDDPRINT("GETPROP: a=%ld obj=%!T, key=%!T",
68172 (long) a,
68173 (duk_tval *) DUK__REGCONSTP(b),
68174 (duk_tval *) DUK__REGCONSTP(c)));
68175 rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
68176 DUK_UNREF(rc); /* ignore */
68177 DUK_DDD(DUK_DDDPRINT("GETPROP --> %!T",
68178 (duk_tval *) duk_get_tval(ctx, -1)));
68179 tv_obj = NULL; /* invalidated */
68180 tv_key = NULL; /* invalidated */
68181
68182 duk_replace(ctx, (duk_idx_t) a); /* val */
68183 break;
68184 }
68185
68186 case DUK_OP_PUTPROP: {
68190 duk_tval *tv_obj;
68191 duk_tval *tv_key;
68192 duk_tval *tv_val;
68193 duk_bool_t rc;
68194
68195 /* A -> object reg
68196 * B -> key reg/const
68197 * C -> value reg/const
68198 *
68199 * Note: intentional difference to register arrangement
68200 * of e.g. GETPROP; 'A' must contain a register-only value.
68201 */
68202
68203 tv_obj = DUK__REGP(a);
68204 tv_key = DUK__REGCONSTP(b);
68205 tv_val = DUK__REGCONSTP(c);
68206 DUK_DDD(DUK_DDDPRINT("PUTPROP: obj=%!T, key=%!T, val=%!T",
68207 (duk_tval *) DUK__REGP(a),
68208 (duk_tval *) DUK__REGCONSTP(b),
68209 (duk_tval *) DUK__REGCONSTP(c)));
68210 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
68211 DUK_UNREF(rc); /* ignore */
68212 DUK_DDD(DUK_DDDPRINT("PUTPROP --> obj=%!T, key=%!T, val=%!T",
68213 (duk_tval *) DUK__REGP(a),
68214 (duk_tval *) DUK__REGCONSTP(b),
68215 (duk_tval *) DUK__REGCONSTP(c)));
68216 tv_obj = NULL; /* invalidated */
68217 tv_key = NULL; /* invalidated */
68218 tv_val = NULL; /* invalidated */
68219
68220 break;
68221 }
68222
68223 case DUK_OP_DELPROP: {
68224 duk_context *ctx = (duk_context *) thr;
68228 duk_tval *tv_obj;
68229 duk_tval *tv_key;
68230 duk_bool_t rc;
68231
68232 /* A -> result reg
68233 * B -> object reg
68234 * C -> key reg/const
68235 */
68236
68237 tv_obj = DUK__REGP(b);
68238 tv_key = DUK__REGCONSTP(c);
68239 rc = duk_hobject_delprop(thr, tv_obj, tv_key, DUK__STRICT());
68240 tv_obj = NULL; /* invalidated */
68241 tv_key = NULL; /* invalidated */
68242
68243 duk_push_boolean(ctx, rc);
68244 duk_replace(ctx, (duk_idx_t) a); /* result */
68245 break;
68246 }
68247
68248 case DUK_OP_CSPROP:
68249 case DUK_OP_CSPROPI: {
68250 duk_context *ctx = (duk_context *) thr;
68253 duk_uint_fast_t idx;
68254 duk_tval *tv_obj;
68255 duk_tval *tv_key;
68256 duk_bool_t rc;
68257
68258 /* E5 Section 11.2.3, step 6.a.i */
68259 /* E5 Section 10.4.3 */
68260
68261 /* XXX: allow object to be a const, e.g. in 'foo'.toString()?
68262 * On the other hand, DUK_REGCONSTP() is slower and generates
68263 * more code.
68264 */
68265
68266 tv_obj = DUK__REGP(b);
68267 tv_key = DUK__REGCONSTP(c);
68268 rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
68269 DUK_UNREF(rc); /* unused */
68270 tv_obj = NULL; /* invalidated */
68271 tv_key = NULL; /* invalidated */
68272
68273 /* Note: target registers a and a+1 may overlap with DUK__REGP(b)
68274 * and DUK__REGCONSTP(c). Careful here.
68275 */
68276
68277 idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68278 if (DUK_DEC_OP(ins) == DUK_OP_CSPROPI) {
68279 duk_tval *tv_ind = DUK__REGP(idx);
68281 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68282 }
68283
68284#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68285 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68286 /* XXX: use duk_is_valid_index() instead? */
68287 /* XXX: improve check; check against nregs, not against top */
68288 DUK__INTERNAL_ERROR("CSPROP out of bounds");
68289 }
68290#endif
68291
68292 duk_push_tval(ctx, DUK__REGP(b)); /* [ ... val obj ] */
68293 duk_replace(ctx, (duk_idx_t) (idx + 1)); /* 'this' binding */
68294 duk_replace(ctx, (duk_idx_t) idx); /* val */
68295 break;
68296 }
68297
68298 case DUK_OP_ADD:
68299 case DUK_OP_SUB:
68300 case DUK_OP_MUL:
68301 case DUK_OP_DIV:
68302 case DUK_OP_MOD: {
68307
68308 if (op == DUK_OP_ADD) {
68309 /*
68310 * Handling DUK_OP_ADD this way is more compact (experimentally)
68311 * than a separate case with separate argument decoding.
68312 */
68314 } else {
68316 }
68317 break;
68318 }
68319
68320 case DUK_OP_BAND:
68321 case DUK_OP_BOR:
68322 case DUK_OP_BXOR:
68323 case DUK_OP_BASL:
68324 case DUK_OP_BLSR:
68325 case DUK_OP_BASR: {
68330
68332 break;
68333 }
68334
68335 case DUK_OP_EQ:
68336 case DUK_OP_NEQ: {
68337 duk_context *ctx = (duk_context *) thr;
68341 duk_bool_t tmp;
68342
68343 /* E5 Sections 11.9.1, 11.9.3 */
68344 tmp = duk_js_equals(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c));
68345 if (DUK_DEC_OP(ins) == DUK_OP_NEQ) {
68346 tmp = !tmp;
68347 }
68348 duk_push_boolean(ctx, tmp);
68349 duk_replace(ctx, (duk_idx_t) a);
68350 break;
68351 }
68352
68353 case DUK_OP_SEQ:
68354 case DUK_OP_SNEQ: {
68355 duk_context *ctx = (duk_context *) thr;
68359 duk_bool_t tmp;
68360
68361 /* E5 Sections 11.9.1, 11.9.3 */
68363 if (DUK_DEC_OP(ins) == DUK_OP_SNEQ) {
68364 tmp = !tmp;
68365 }
68366 duk_push_boolean(ctx, tmp);
68367 duk_replace(ctx, (duk_idx_t) a);
68368 break;
68369 }
68370
68371 /* Note: combining comparison ops must be done carefully because
68372 * of uncomparable values (NaN): it's not necessarily true that
68373 * (x >= y) === !(x < y). Also, evaluation order matters, and
68374 * although it would only seem to affect the compiler this is
68375 * actually not the case, because there are also run-time coercions
68376 * of the arguments (with potential side effects).
68377 *
68378 * XXX: can be combined; check code size.
68379 */
68380
68381 case DUK_OP_GT: {
68382 duk_context *ctx = (duk_context *) thr;
68386 duk_bool_t tmp;
68387
68388 /* x > y --> y < x */
68389 tmp = duk_js_compare_helper(thr,
68390 DUK__REGCONSTP(c), /* y */
68391 DUK__REGCONSTP(b), /* x */
68392 0); /* flags */
68393
68394 duk_push_boolean(ctx, tmp);
68395 duk_replace(ctx, (duk_idx_t) a);
68396 break;
68397 }
68398
68399 case DUK_OP_GE: {
68400 duk_context *ctx = (duk_context *) thr;
68404 duk_bool_t tmp;
68405
68406 /* x >= y --> not (x < y) */
68407 tmp = duk_js_compare_helper(thr,
68408 DUK__REGCONSTP(b), /* x */
68409 DUK__REGCONSTP(c), /* y */
68411 DUK_COMPARE_FLAG_NEGATE); /* flags */
68412
68413 duk_push_boolean(ctx, tmp);
68414 duk_replace(ctx, (duk_idx_t) a);
68415 break;
68416 }
68417
68418 case DUK_OP_LT: {
68419 duk_context *ctx = (duk_context *) thr;
68423 duk_bool_t tmp;
68424
68425 /* x < y */
68426 tmp = duk_js_compare_helper(thr,
68427 DUK__REGCONSTP(b), /* x */
68428 DUK__REGCONSTP(c), /* y */
68430
68431 duk_push_boolean(ctx, tmp);
68432 duk_replace(ctx, (duk_idx_t) a);
68433 break;
68434 }
68435
68436 case DUK_OP_LE: {
68437 duk_context *ctx = (duk_context *) thr;
68441 duk_bool_t tmp;
68442
68443 /* x <= y --> not (x > y) --> not (y < x) */
68444 tmp = duk_js_compare_helper(thr,
68445 DUK__REGCONSTP(c), /* y */
68446 DUK__REGCONSTP(b), /* x */
68447 DUK_COMPARE_FLAG_NEGATE); /* flags */
68448
68449 duk_push_boolean(ctx, tmp);
68450 duk_replace(ctx, (duk_idx_t) a);
68451 break;
68452 }
68453
68454 case DUK_OP_IF: {
68457 duk_bool_t tmp;
68458
68460 if (tmp == (duk_bool_t) a) {
68461 /* if boolean matches A, skip next inst */
68462 curr_pc++;
68463 } else {
68464 ;
68465 }
68466 break;
68467 }
68468
68469 case DUK_OP_JUMP: {
68470 duk_int_fast_t abc = DUK_DEC_ABC(ins);
68471
68472 curr_pc += abc - DUK_BC_JUMP_BIAS;
68473 break;
68474 }
68475
68476 case DUK_OP_RETURN: {
68477 duk_context *ctx = (duk_context *) thr;
68480 /* duk_small_uint_fast_t c = DUK_DEC_C(ins); */
68481 duk_small_uint_t ret_result;
68482
68483 /* A -> flags
68484 * B -> return value reg/const
68485 * C -> currently unused
68486 */
68487
68489
68490 /* duk__handle_return() is guaranteed never to throw, except
68491 * for potential out-of-memory situations which will then
68492 * propagate out of the executor longjmp handler.
68493 */
68494
68497 } else {
68498 duk_push_undefined(ctx);
68499 }
68500 ret_result = duk__handle_return(thr,
68501 entry_thread,
68502 entry_callstack_top);
68503 if (ret_result == DUK__RETHAND_RESTART) {
68504 goto restart_execution;
68505 }
68506 DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
68507
68508 DUK_DDD(DUK_DDDPRINT("exiting executor after RETURN handling"));
68509 return;
68510 }
68511
68512 case DUK_OP_CALL:
68513 case DUK_OP_CALLI: {
68514 duk_context *ctx = (duk_context *) thr;
68517 duk_uint_fast_t idx;
68518 duk_small_uint_t call_flags;
68519 duk_small_uint_t flag_tailcall;
68520 duk_small_uint_t flag_evalcall;
68521 duk_tval *tv_func;
68522 duk_hobject *obj_func;
68523 duk_bool_t setup_rc;
68524 duk_idx_t num_stack_args;
68525#if !defined(DUK_USE_EXEC_FUN_LOCAL)
68527#endif
68528
68529 /* A -> flags
68530 * B -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
68531 * (for DUK_OP_CALLI, 'b' is indirect)
68532 * C -> nargs
68533 */
68534
68535 /* these are not necessarily 0 or 1 (may be other non-zero), that's ok */
68536 flag_tailcall = (a & DUK_BC_CALL_FLAG_TAILCALL);
68537 flag_evalcall = (a & DUK_BC_CALL_FLAG_EVALCALL);
68538
68539 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
68540 if (DUK_DEC_OP(ins) == DUK_OP_CALLI) {
68541 duk_tval *tv_ind = DUK__REGP(idx);
68543 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68544 }
68545
68546#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68547 if (!duk_is_valid_index(ctx, (duk_idx_t) idx)) {
68548 /* XXX: improve check; check against nregs, not against top */
68549 DUK__INTERNAL_ERROR("CALL out of bounds");
68550 }
68551#endif
68552
68553 /*
68554 * To determine whether to use an optimized Ecmascript-to-Ecmascript
68555 * call, we need to know whether the final, non-bound function is an
68556 * Ecmascript function.
68557 *
68558 * This is now implemented so that we start to do an ecma-to-ecma call
68559 * setup which will resolve the bound chain as the first thing. If the
68560 * final function is not eligible, the return value indicates that the
68561 * ecma-to-ecma call is not possible. The setup will overwrite the call
68562 * target at DUK__REGP(idx) with the final, non-bound function (which
68563 * may be a lightfunc), and fudge arguments if necessary.
68564 *
68565 * XXX: If an ecma-to-ecma call is not possible, this initial call
68566 * setup will do bound function chain resolution but won't do the
68567 * "effective this binding" resolution which is quite confusing.
68568 * Perhaps add a helper for doing bound function and effective this
68569 * binding resolution - and call that explicitly? Ecma-to-ecma call
68570 * setup and normal function handling can then assume this prestep has
68571 * been done by the caller.
68572 */
68573
68574 duk_set_top(ctx, (duk_idx_t) (idx + c + 2)); /* [ ... func this arg1 ... argN ] */
68575
68576 call_flags = 0;
68577 if (flag_tailcall) {
68578 /* We request a tail call, but in some corner cases
68579 * call handling can decide that a tail call is
68580 * actually not possible.
68581 * See: test-bug-tailcall-preventyield-assert.c.
68582 */
68583 call_flags |= DUK_CALL_FLAG_IS_TAILCALL;
68584 }
68585
68586 /* Compared to duk_handle_call():
68587 * - protected call: never
68588 * - ignore recursion limit: never
68589 */
68590 num_stack_args = c;
68591 setup_rc = duk_handle_ecma_call_setup(thr,
68592 num_stack_args,
68593 call_flags);
68594
68595 if (setup_rc) {
68596 /* Ecma-to-ecma call possible, may or may not be a tail call.
68597 * Avoid C recursion by being clever.
68598 */
68599 DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
68600 /* curr_pc synced by duk_handle_ecma_call_setup() */
68601 goto restart_execution;
68602 }
68603 DUK_ASSERT(thr->ptr_curr_pc != NULL); /* restored if ecma-to-ecma setup fails */
68604
68605 DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call not possible, target is native (may be lightfunc)"));
68606
68607 /* Recompute argument count: bound function handling may have shifted. */
68608 num_stack_args = duk_get_top(ctx) - (idx + 2);
68609 DUK_DDD(DUK_DDDPRINT("recomputed arg count: %ld\n", (long) num_stack_args));
68610
68611 tv_func = DUK__REGP(idx); /* Relookup if relocated */
68612 if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
68613
68614 call_flags = 0; /* not protected, respect reclimit, not constructor */
68615
68616 /* There is no eval() special handling here: eval() is never
68617 * automatically converted to a lightfunc.
68618 */
68620
68622 num_stack_args,
68623 call_flags);
68624
68625 /* duk_js_call.c is required to restore the stack reserve
68626 * so we only need to reset the top.
68627 */
68628#if !defined(DUK_USE_EXEC_FUN_LOCAL)
68629 fun = DUK__FUN();
68630#endif
68631 duk_set_top(ctx, (duk_idx_t) fun->nregs);
68632
68633 /* No need to reinit setjmp() catchpoint, as call handling
68634 * will store and restore our state.
68635 */
68636 } else {
68637 /* Call setup checks callability. */
68639 obj_func = DUK_TVAL_GET_OBJECT(tv_func);
68640 DUK_ASSERT(obj_func != NULL);
68642
68643 /*
68644 * Other cases, use C recursion.
68645 *
68646 * If a tail call was requested we ignore it and execute a normal call.
68647 * Since Duktape 0.11.0 the compiler emits a RETURN opcode even after
68648 * a tail call to avoid test-bug-tailcall-thread-yield-resume.js.
68649 *
68650 * Direct eval call: (1) call target (before following bound function
68651 * chain) is the built-in eval() function, and (2) call was made with
68652 * the identifier 'eval'.
68653 */
68654
68655 call_flags = 0; /* not protected, respect reclimit, not constructor */
68656
68657 if (DUK_HOBJECT_IS_NATIVEFUNCTION(obj_func) &&
68658 ((duk_hnativefunction *) obj_func)->func == duk_bi_global_object_eval) {
68659 if (flag_evalcall) {
68660 DUK_DDD(DUK_DDDPRINT("call target is eval, call identifier was 'eval' -> direct eval"));
68661 call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
68662 } else {
68663 DUK_DDD(DUK_DDDPRINT("call target is eval, call identifier was not 'eval' -> indirect eval"));
68664 }
68665 }
68666
68668 num_stack_args,
68669 call_flags);
68670
68671 /* duk_js_call.c is required to restore the stack reserve
68672 * so we only need to reset the top.
68673 */
68674#if !defined(DUK_USE_EXEC_FUN_LOCAL)
68675 fun = DUK__FUN();
68676#endif
68677 duk_set_top(ctx, (duk_idx_t) fun->nregs);
68678
68679 /* No need to reinit setjmp() catchpoint, as call handling
68680 * will store and restore our state.
68681 */
68682 }
68683
68684 /* When debugger is enabled, we need to recheck the activation
68685 * status after returning. This is now handled by call handling
68686 * and heap->dbg_force_restart.
68687 */
68688 break;
68689 }
68690
68691 case DUK_OP_TRYCATCH: {
68692 duk_context *ctx = (duk_context *) thr;
68693 duk_activation *act;
68694 duk_catcher *cat;
68695 duk_tval *tv1;
68697 duk_uint_fast_t bc;
68698
68699 /* A -> flags
68700 * BC -> reg_catch; base register for two registers used both during
68701 * trycatch setup and when catch is triggered
68702 *
68703 * If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
68704 * reg_catch + 0: catch binding variable name (string).
68705 * Automatic declarative environment is established for
68706 * the duration of the 'catch' clause.
68707 *
68708 * If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
68709 * reg_catch + 0: with 'target value', which is coerced to
68710 * an object and then used as a bindind object for an
68711 * environment record. The binding is initialized here, for
68712 * the 'try' clause.
68713 *
68714 * Note that a TRYCATCH generated for a 'with' statement has no
68715 * catch or finally parts.
68716 */
68717
68718 /* XXX: TRYCATCH handling should be reworked to avoid creating
68719 * an explicit scope unless it is actually needed (e.g. function
68720 * instances or eval is executed inside the catch block). This
68721 * rework is not trivial because the compiler doesn't have an
68722 * intermediate representation. When the rework is done, the
68723 * opcode format can also be made more straightforward.
68724 */
68725
68726 /* XXX: side effect handling is quite awkward here */
68727
68728 DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
68729 "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
68730 (long) DUK_DEC_BC(ins),
68731 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
68732 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
68733 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
68734 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
68735 (unsigned long) DUK_DEC_A(ins)));
68736
68737 a = DUK_DEC_A(ins);
68738 bc = DUK_DEC_BC(ins);
68739
68740 act = thr->callstack + thr->callstack_top - 1;
68741 DUK_ASSERT(thr->callstack_top >= 1);
68742
68743 /* 'with' target must be created first, in case we run out of memory */
68744 /* XXX: refactor out? */
68745
68747 DUK_DDD(DUK_DDDPRINT("need to initialize a with binding object"));
68748
68749 if (act->lex_env == NULL) {
68750 DUK_ASSERT(act->var_env == NULL);
68751 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
68752
68753 /* must relookup act in case of side effects */
68755 act = thr->callstack + thr->callstack_top - 1;
68756 DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
68757 }
68758 DUK_ASSERT(act->lex_env != NULL);
68759 DUK_ASSERT(act->var_env != NULL);
68760
68761 (void) duk_push_object_helper(ctx,
68764 -1); /* no prototype, updated below */
68765
68766 duk_push_tval(ctx, DUK__REGP(bc));
68767 duk_to_object(ctx, -1);
68768 duk_dup(ctx, -1);
68769
68770 /* [ ... env target ] */
68771 /* [ ... env target target ] */
68772
68774 duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); /* always provideThis=true */
68775
68776 /* [ ... env ] */
68777
68778 DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iT",
68779 (duk_tval *) duk_get_tval(ctx, -1)));
68780 }
68781
68782 /* allocate catcher and populate it (should be atomic) */
68783
68785 cat = thr->catchstack + thr->catchstack_top;
68786 DUK_ASSERT(thr->catchstack_top + 1 <= thr->catchstack_size);
68787 thr->catchstack_top++;
68788
68789 cat->flags = DUK_CAT_TYPE_TCF;
68790 cat->h_varname = NULL;
68791
68794 }
68797 }
68799 DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
68801 tv1 = DUK__REGP(bc);
68803
68804 /* borrowed reference; although 'tv1' comes from a register,
68805 * its value was loaded using LDCONST so the constant will
68806 * also exist and be reachable.
68807 */
68808 cat->h_varname = DUK_TVAL_GET_STRING(tv1);
68809 } else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
68810 /* env created above to stack top */
68811 duk_hobject *new_env;
68812
68813 DUK_DDD(DUK_DDDPRINT("lexenv active flag set to catcher"));
68815
68816 DUK_DDD(DUK_DDDPRINT("activating object env: %!iT",
68817 (duk_tval *) duk_get_tval(ctx, -1)));
68818 DUK_ASSERT(act->lex_env != NULL);
68819 new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
68820 DUK_ASSERT(new_env != NULL);
68821
68822 act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
68823 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env); /* side effects */
68824
68825 act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
68826 act->lex_env = new_env;
68827 DUK_HOBJECT_INCREF(thr, new_env);
68828 duk_pop(ctx);
68829 } else {
68830 ;
68831 }
68832
68833 /* Registers 'bc' and 'bc + 1' are written in longjmp handling
68834 * and if their previous values (which are temporaries) become
68835 * unreachable -and- have a finalizer, there'll be a function
68836 * call during error handling which is not supported now (GH-287).
68837 * Ensure that both 'bc' and 'bc + 1' have primitive values to
68838 * guarantee no finalizer calls in error handling. Scrubbing also
68839 * ensures finalizers for the previous values run here rather than
68840 * later. Error handling related values are also written to 'bc'
68841 * and 'bc + 1' but those values never become unreachable during
68842 * error handling, so there's no side effect problem even if the
68843 * error value has a finalizer.
68844 */
68845 duk_to_undefined(ctx, bc);
68846 duk_to_undefined(ctx, bc + 1);
68847
68848 cat = thr->catchstack + thr->catchstack_top - 1; /* relookup (side effects) */
68849 cat->callstack_index = thr->callstack_top - 1;
68850 cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
68851 cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
68852
68853 DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
68854 "idx_base=%ld, h_varname=%!O",
68855 (unsigned long) cat->flags, (long) cat->callstack_index,
68856 (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
68857
68858 curr_pc += 2; /* skip jump slots */
68859 break;
68860 }
68861
68862 /* Pre/post inc/dec for register variables, important for loops. */
68863 case DUK_OP_PREINCR:
68864 case DUK_OP_PREDECR:
68865 case DUK_OP_POSTINCR:
68866 case DUK_OP_POSTDECR: {
68867 duk_context *ctx = (duk_context *) thr;
68869 duk_uint_fast_t bc = DUK_DEC_BC(ins);
68870 duk_tval *tv1, *tv2;
68871 duk_double_t x, y, z;
68872
68873 /* Two lowest bits of opcode are used to distinguish
68874 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
68875 */
68876 DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
68877 DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
68878 DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
68879 DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
68880
68881 tv1 = DUK__REGP(bc);
68882#if defined(DUK_USE_FASTINT)
68883 if (DUK_TVAL_IS_FASTINT(tv1)) {
68884 duk_int64_t x_fi, y_fi, z_fi;
68885 x_fi = DUK_TVAL_GET_FASTINT(tv1);
68886 if (ins & DUK_ENC_OP(0x01)) {
68887 if (x_fi == DUK_FASTINT_MIN) {
68888 goto skip_fastint;
68889 }
68890 y_fi = x_fi - 1;
68891 } else {
68892 if (x_fi == DUK_FASTINT_MAX) {
68893 goto skip_fastint;
68894 }
68895 y_fi = x_fi + 1;
68896 }
68897
68898 DUK_TVAL_SET_FASTINT(tv1, y_fi); /* no need for refcount update */
68899
68900 tv2 = DUK__REGP(a);
68901 z_fi = (ins & DUK_ENC_OP(0x02)) ? x_fi : y_fi;
68902 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv2, z_fi); /* side effects */
68903 break;
68904 }
68905 skip_fastint:
68906#endif
68907 if (DUK_TVAL_IS_NUMBER(tv1)) {
68908 /* Fast path for the case where the register
68909 * is a number (e.g. loop counter).
68910 */
68911
68912 x = DUK_TVAL_GET_NUMBER(tv1);
68913 if (ins & DUK_ENC_OP(0x01)) {
68914 y = x - 1.0;
68915 } else {
68916 y = x + 1.0;
68917 }
68918
68919 DUK_TVAL_SET_NUMBER(tv1, y); /* no need for refcount update */
68920 } else {
68921 x = duk_to_number(ctx, bc);
68922
68923 if (ins & DUK_ENC_OP(0x01)) {
68924 y = x - 1.0;
68925 } else {
68926 y = x + 1.0;
68927 }
68928
68929 duk_push_number(ctx, y);
68930 duk_replace(ctx, bc);
68931 }
68932
68933 tv2 = DUK__REGP(a);
68934 z = (ins & DUK_ENC_OP(0x02)) ? x : y;
68935 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv2, z); /* side effects */
68936 break;
68937 }
68938
68939 /* Preinc/predec for var-by-name, slow path. */
68940 case DUK_OP_PREINCV:
68941 case DUK_OP_PREDECV:
68942 case DUK_OP_POSTINCV:
68943 case DUK_OP_POSTDECV: {
68944 duk_context *ctx = (duk_context *) thr;
68945 duk_activation *act;
68947 duk_uint_fast_t bc = DUK_DEC_BC(ins);
68948 duk_double_t x, y;
68949 duk_tval *tv1;
68951
68952 /* Two lowest bits of opcode are used to distinguish
68953 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
68954 */
68955 DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
68956 DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
68957 DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
68958 DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
68959
68960 tv1 = DUK__CONSTP(bc);
68963 DUK_ASSERT(name != NULL);
68964 act = thr->callstack + thr->callstack_top - 1;
68965 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
68966
68967 /* XXX: fastint fast path would be very useful here */
68968
68969 x = duk_to_number(ctx, -2);
68970 duk_pop_2(ctx);
68971 if (ins & DUK_ENC_OP(0x01)) {
68972 y = x - 1.0;
68973 } else {
68974 y = x + 1.0;
68975 }
68976
68977 duk_push_number(ctx, y);
68978 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
68979 DUK_ASSERT(tv1 != NULL);
68980 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
68981 duk_pop(ctx);
68982
68983 duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
68984 duk_replace(ctx, (duk_idx_t) a);
68985 break;
68986 }
68987
68988 /* Preinc/predec for object properties. */
68989 case DUK_OP_PREINCP:
68990 case DUK_OP_PREDECP:
68991 case DUK_OP_POSTINCP:
68992 case DUK_OP_POSTDECP: {
68993 duk_context *ctx = (duk_context *) thr;
68997 duk_tval *tv_obj;
68998 duk_tval *tv_key;
68999 duk_tval *tv_val;
69000 duk_bool_t rc;
69001 duk_double_t x, y;
69002
69003 /* A -> target reg
69004 * B -> object reg/const (may be const e.g. in "'foo'[1]")
69005 * C -> key reg/const
69006 */
69007
69008 /* Two lowest bits of opcode are used to distinguish
69009 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69010 */
69011 DUK_ASSERT((DUK_OP_PREINCP & 0x03) == 0x00);
69012 DUK_ASSERT((DUK_OP_PREDECP & 0x03) == 0x01);
69013 DUK_ASSERT((DUK_OP_POSTINCP & 0x03) == 0x02);
69014 DUK_ASSERT((DUK_OP_POSTDECP & 0x03) == 0x03);
69015
69016 tv_obj = DUK__REGCONSTP(b);
69017 tv_key = DUK__REGCONSTP(c);
69018 rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
69019 DUK_UNREF(rc); /* ignore */
69020 tv_obj = NULL; /* invalidated */
69021 tv_key = NULL; /* invalidated */
69022
69023 x = duk_to_number(ctx, -1);
69024 duk_pop(ctx);
69025 if (ins & DUK_ENC_OP(0x01)) {
69026 y = x - 1.0;
69027 } else {
69028 y = x + 1.0;
69029 }
69030
69031 duk_push_number(ctx, y);
69032 tv_val = DUK_GET_TVAL_NEGIDX(ctx, -1);
69033 DUK_ASSERT(tv_val != NULL);
69034 tv_obj = DUK__REGCONSTP(b);
69035 tv_key = DUK__REGCONSTP(c);
69036 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
69037 DUK_UNREF(rc); /* ignore */
69038 tv_obj = NULL; /* invalidated */
69039 tv_key = NULL; /* invalidated */
69040 duk_pop(ctx);
69041
69042 duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
69043 duk_replace(ctx, (duk_idx_t) a);
69044 break;
69045 }
69046
69047 case DUK_OP_EXTRA: {
69048 /* XXX: shared decoding of 'b' and 'c'? */
69049
69050 duk_small_uint_fast_t extraop = DUK_DEC_A(ins);
69051 switch ((int) extraop) {
69052 /* XXX: switch cast? */
69053
69054 case DUK_EXTRAOP_NOP: {
69055 /* nop */
69056 break;
69057 }
69058
69059 case DUK_EXTRAOP_INVALID: {
69060 DUK_ERROR_FMT1(thr, DUK_ERR_INTERNAL_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_BC(ins));
69061 break;
69062 }
69063
69064 case DUK_EXTRAOP_LDTHIS: {
69065 /* Note: 'this' may be bound to any value, not just an object */
69066 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69067 duk_tval *tv1, *tv2;
69068
69069 tv1 = DUK__REGP(bc);
69070 tv2 = thr->valstack_bottom - 1; /* 'this binding' is just under bottom */
69071 DUK_ASSERT(tv2 >= thr->valstack);
69072
69073 DUK_DDD(DUK_DDDPRINT("LDTHIS: %!T to r%ld", (duk_tval *) tv2, (long) bc));
69074
69075 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
69076 break;
69077 }
69078
69079 case DUK_EXTRAOP_LDUNDEF: {
69080 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69081 duk_tval *tv1;
69082
69083 tv1 = DUK__REGP(bc);
69084 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
69085 break;
69086 }
69087
69088 case DUK_EXTRAOP_LDNULL: {
69089 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69090 duk_tval *tv1;
69091
69092 tv1 = DUK__REGP(bc);
69093 DUK_TVAL_SET_NULL_UPDREF(thr, tv1); /* side effects */
69094 break;
69095 }
69096
69097 case DUK_EXTRAOP_LDTRUE:
69098 case DUK_EXTRAOP_LDFALSE: {
69099 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69100 duk_tval *tv1;
69101 duk_small_uint_fast_t bval = (extraop == DUK_EXTRAOP_LDTRUE ? 1 : 0);
69102
69103 tv1 = DUK__REGP(bc);
69104 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, bval); /* side effects */
69105 break;
69106 }
69107
69108 case DUK_EXTRAOP_NEWOBJ: {
69109 duk_context *ctx = (duk_context *) thr;
69111
69112 duk_push_object(ctx);
69113 duk_replace(ctx, (duk_idx_t) b);
69114 break;
69115 }
69116
69117 case DUK_EXTRAOP_NEWARR: {
69118 duk_context *ctx = (duk_context *) thr;
69120
69121 duk_push_array(ctx);
69122 duk_replace(ctx, (duk_idx_t) b);
69123 break;
69124 }
69125
69126 case DUK_EXTRAOP_SETALEN: {
69129 duk_tval *tv1;
69130 duk_hobject *h;
69131 duk_uint32_t len;
69132
69133 b = DUK_DEC_B(ins); tv1 = DUK__REGP(b);
69135 h = DUK_TVAL_GET_OBJECT(tv1);
69136
69137 c = DUK_DEC_C(ins); tv1 = DUK__REGP(c);
69139 len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
69140
69141 duk_hobject_set_length(thr, h, len);
69142
69143 break;
69144 }
69145
69146 case DUK_EXTRAOP_TYPEOF: {
69147 duk_context *ctx = (duk_context *) thr;
69148 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69150 duk_replace(ctx, (duk_idx_t) bc);
69151 break;
69152 }
69153
69154 case DUK_EXTRAOP_TYPEOFID: {
69155 duk_context *ctx = (duk_context *) thr;
69156 duk_activation *act;
69160 duk_tval *tv;
69161
69162 /* B -> target register
69163 * C -> constant index of identifier name
69164 */
69165
69166 tv = DUK__REGCONSTP(c); /* XXX: this could be a DUK__CONSTP instead */
69169 act = thr->callstack + thr->callstack_top - 1;
69170 if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
69171 /* -> [... val this] */
69172 tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
69173 duk_push_hstring(ctx, duk_js_typeof(thr, tv));
69174 duk_replace(ctx, (duk_idx_t) b);
69175 duk_pop_2(ctx);
69176 } else {
69177 /* unresolvable, no stack changes */
69179 duk_replace(ctx, (duk_idx_t) b);
69180 }
69181
69182 break;
69183 }
69184
69185 case DUK_EXTRAOP_INITENUM: {
69186 duk_context *ctx = (duk_context *) thr;
69189
69190 /*
69191 * Enumeration semantics come from for-in statement, E5 Section 12.6.4.
69192 * If called with 'null' or 'undefined', this opcode returns 'null' as
69193 * the enumerator, which is special cased in NEXTENUM. This simplifies
69194 * the compiler part
69195 */
69196
69197 /* B -> register for writing enumerator object
69198 * C -> value to be enumerated (register)
69199 */
69200
69201 if (duk_is_null_or_undefined(ctx, (duk_idx_t) c)) {
69202 duk_push_null(ctx);
69203 duk_replace(ctx, (duk_idx_t) b);
69204 } else {
69205 duk_dup(ctx, (duk_idx_t) c);
69206 duk_to_object(ctx, -1);
69207 duk_hobject_enumerator_create(ctx, 0 /*enum_flags*/); /* [ ... val ] --> [ ... enum ] */
69208 duk_replace(ctx, (duk_idx_t) b);
69209 }
69210 break;
69211 }
69212
69213 case DUK_EXTRAOP_NEXTENUM: {
69214 duk_context *ctx = (duk_context *) thr;
69217
69218 /*
69219 * NEXTENUM checks whether the enumerator still has unenumerated
69220 * keys. If so, the next key is loaded to the target register
69221 * and the next instruction is skipped. Otherwise the next instruction
69222 * will be executed, jumping out of the enumeration loop.
69223 */
69224
69225 /* B -> target register for next key
69226 * C -> enum register
69227 */
69228
69229 DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
69230 (duk_tval *) duk_get_tval(ctx, (duk_idx_t) b),
69231 (duk_tval *) duk_get_tval(ctx, (duk_idx_t) c)));
69232
69233 if (duk_is_object(ctx, (duk_idx_t) c)) {
69234 /* XXX: assert 'c' is an enumerator */
69235 duk_dup(ctx, (duk_idx_t) c);
69236 if (duk_hobject_enumerator_next(ctx, 0 /*get_value*/)) {
69237 /* [ ... enum ] -> [ ... next_key ] */
69238 DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
69239 (duk_tval *) duk_get_tval(ctx, -1)));
69240 curr_pc++;
69241 } else {
69242 /* [ ... enum ] -> [ ... ] */
69243 DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
69244 duk_push_undefined(ctx);
69245 }
69246 duk_replace(ctx, (duk_idx_t) b);
69247 } else {
69248 /* 'null' enumerator case -> behave as with an empty enumerator */
69249 DUK_ASSERT(duk_is_null(ctx, (duk_idx_t) c));
69250 DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
69251 }
69252 break;
69253 }
69254
69258 case DUK_EXTRAOP_INITGETI: {
69259 duk_context *ctx = (duk_context *) thr;
69260 duk_bool_t is_set = (extraop == DUK_EXTRAOP_INITSET || extraop == DUK_EXTRAOP_INITSETI);
69262 duk_uint_fast_t idx;
69263
69264 /* B -> object register
69265 * C -> C+0 contains key, C+1 closure (value)
69266 */
69267
69268 /*
69269 * INITSET/INITGET are only used to initialize object literal keys.
69270 * The compiler ensures that there cannot be a previous data property
69271 * of the same name. It also ensures that setter and getter can only
69272 * be initialized once (or not at all).
69273 */
69274
69275 idx = (duk_uint_fast_t) DUK_DEC_C(ins);
69276 if (extraop == DUK_EXTRAOP_INITSETI || extraop == DUK_EXTRAOP_INITGETI) {
69277 duk_tval *tv_ind = DUK__REGP(idx);
69279 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
69280 }
69281
69282#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
69283 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
69284 /* XXX: use duk_is_valid_index() instead? */
69285 /* XXX: improve check; check against nregs, not against top */
69286 DUK__INTERNAL_ERROR("INITSET/INITGET out of bounds");
69287 }
69288#endif
69289
69290 /* XXX: this is now a very unoptimal implementation -- this can be
69291 * made very simple by direct manipulation of the object internals,
69292 * given the guarantees above.
69293 */
69294
69297 duk_push_undefined(ctx);
69298 duk_dup(ctx, (duk_idx_t) b);
69299 duk_dup(ctx, (duk_idx_t) (idx + 0));
69300 duk_push_object(ctx); /* -> [ Object defineProperty undefined obj key desc ] */
69301
69302 duk_push_true(ctx);
69304 duk_push_true(ctx);
69306 duk_dup(ctx, (duk_idx_t) (idx + 1));
69307 duk_put_prop_stridx(ctx, -2, (is_set ? DUK_STRIDX_SET : DUK_STRIDX_GET));
69308
69309 DUK_DDD(DUK_DDDPRINT("INITGET/INITSET: obj=%!T, key=%!T, desc=%!T",
69310 (duk_tval *) duk_get_tval(ctx, -3),
69311 (duk_tval *) duk_get_tval(ctx, -2),
69312 (duk_tval *) duk_get_tval(ctx, -1)));
69313
69314 duk_call_method(ctx, 3); /* -> [ Object res ] */
69315 duk_pop_2(ctx);
69316
69317 DUK_DDD(DUK_DDDPRINT("INITGET/INITSET AFTER: obj=%!T",
69318 (duk_tval *) duk_get_tval(ctx, (duk_idx_t) b)));
69319 break;
69320 }
69321
69322 case DUK_EXTRAOP_ENDTRY: {
69323 duk_catcher *cat;
69324 duk_tval *tv1;
69325
69326 DUK_ASSERT(thr->catchstack_top >= 1);
69327 DUK_ASSERT(thr->callstack_top >= 1);
69328 DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69329
69330 cat = thr->catchstack + thr->catchstack_top - 1;
69331
69332 DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
69334
69335 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69336 DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
69337
69338 tv1 = thr->valstack + cat->idx_base;
69339 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69340 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
69341 tv1 = NULL;
69342
69343 tv1 = thr->valstack + cat->idx_base + 1;
69344 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69345 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
69346 tv1 = NULL;
69347
69349 } else {
69350 DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
69351 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69352 /* no need to unwind callstack */
69353 }
69354
69355 curr_pc = cat->pc_base + 1;
69356 break;
69357 }
69358
69359 case DUK_EXTRAOP_ENDCATCH: {
69360 duk_activation *act;
69361 duk_catcher *cat;
69362 duk_tval *tv1;
69363
69364 DUK_ASSERT(thr->catchstack_top >= 1);
69365 DUK_ASSERT(thr->callstack_top >= 1);
69366 DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69367
69368 cat = thr->catchstack + thr->catchstack_top - 1;
69369 DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat)); /* cleared before entering catch part */
69370
69371 act = thr->callstack + thr->callstack_top - 1;
69372
69373 if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
69374 duk_hobject *prev_env;
69375
69376 /* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
69378 DUK_ASSERT(act->lex_env != NULL);
69379
69380 DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
69381
69382 prev_env = act->lex_env;
69383 DUK_ASSERT(prev_env != NULL);
69384 act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
69386 DUK_HOBJECT_DECREF(thr, prev_env); /* side effects */
69387 }
69388
69389 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69390 DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
69391
69392 tv1 = thr->valstack + cat->idx_base;
69393 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69394 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
69395 tv1 = NULL;
69396
69397 tv1 = thr->valstack + cat->idx_base + 1;
69398 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69399 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
69400 tv1 = NULL;
69401
69403 } else {
69404 DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
69405 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69406 /* no need to unwind callstack */
69407 }
69408
69409 curr_pc = cat->pc_base + 1;
69410 break;
69411 }
69412
69413 case DUK_EXTRAOP_ENDFIN: {
69414 duk_context *ctx = (duk_context *) thr;
69415 duk_catcher *cat;
69416 duk_tval *tv1;
69417 duk_small_uint_t cont_type;
69418 duk_small_uint_t ret_result;
69419
69420 /* Sync and NULL early. */
69422
69423 DUK_ASSERT(thr->catchstack_top >= 1);
69424 DUK_ASSERT(thr->callstack_top >= 1);
69425 DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69426
69427 cat = thr->catchstack + thr->catchstack_top - 1;
69428
69429 /* CATCH flag may be enabled or disabled here; it may be enabled if
69430 * the statement has a catch block but the try block does not throw
69431 * an error.
69432 */
69433 DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat)); /* cleared before entering finally */
69434 /* XXX: assert idx_base */
69435
69436 DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
69437 (duk_tval *) (thr->valstack + cat->idx_base + 0),
69438 (duk_tval *) (thr->valstack + cat->idx_base + 1)));
69439
69440 tv1 = thr->valstack + cat->idx_base + 1; /* type */
69442 cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
69443
69444 switch (cont_type) {
69445 case DUK_LJ_TYPE_NORMAL: {
69446 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
69447 "dismantle catcher, resume execution after ENDFIN"));
69448 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69449 /* no need to unwind callstack */
69450 goto restart_execution;
69451 }
69452 case DUK_LJ_TYPE_RETURN: {
69453 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
69454 "catcher, handle return, lj.value1=%!T", thr->valstack + cat->idx_base));
69455
69456 /* Not necessary to unwind catchstack: return handling will
69457 * do it. The finally flag of 'cat' is no longer set. The
69458 * catch flag may be set, but it's not checked by return handling.
69459 */
69460 DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat)); /* cleared before entering finally */
69461#if 0
69462 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69463#endif
69464
69465 duk_push_tval(ctx, thr->valstack + cat->idx_base);
69466 ret_result = duk__handle_return(thr,
69467 entry_thread,
69468 entry_callstack_top);
69469 if (ret_result == DUK__RETHAND_RESTART) {
69470 goto restart_execution;
69471 }
69472 DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
69473
69474 DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
69475 return;
69476 }
69477 case DUK_LJ_TYPE_BREAK:
69478 case DUK_LJ_TYPE_CONTINUE: {
69479 duk_uint_t label_id;
69480 duk_small_uint_t lj_type;
69481
69482 /* Not necessary to unwind catchstack: break/continue
69483 * handling will do it. The finally flag of 'cat' is
69484 * no longer set. The catch flag may be set, but it's
69485 * not checked by break/continue handling.
69486 */
69487#if 0
69488 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69489#endif
69490
69491 tv1 = thr->valstack + cat->idx_base;
69493#if defined(DUK_USE_FASTINT)
69494 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
69495 label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
69496#else
69497 label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
69498#endif
69499 lj_type = cont_type;
69500 duk__handle_break_or_continue(thr, label_id, lj_type);
69501 goto restart_execution;
69502 }
69503 default: {
69504 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
69505 "dismantle catcher, re-throw error",
69506 (long) cont_type));
69507
69508 duk_push_tval(ctx, thr->valstack + cat->idx_base);
69509
69511
69512 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
69513 duk_err_longjmp(thr);
69515 }
69516 }
69517
69518 /* Must restart in all cases because we NULLed thr->ptr_curr_pc. */
69520 break;
69521 }
69522
69523 case DUK_EXTRAOP_THROW: {
69524 duk_context *ctx = (duk_context *) thr;
69525 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69526
69527 /* Note: errors are augmented when they are created, not
69528 * when they are thrown. So, don't augment here, it would
69529 * break re-throwing for instance.
69530 */
69531
69532 /* Sync so that augmentation sees up-to-date activations, NULL
69533 * thr->ptr_curr_pc so that it's not used if side effects occur
69534 * in augmentation or longjmp handling.
69535 */
69537
69538 duk_dup(ctx, (duk_idx_t) bc);
69539 DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
69540 (duk_tval *) duk_get_tval(ctx, -1)));
69541#if defined(DUK_USE_AUGMENT_ERROR_THROW)
69543 DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
69544 (duk_tval *) duk_get_tval(ctx, -1)));
69545#endif
69546
69548
69549 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
69550 duk_err_longjmp(thr);
69552 break;
69553 }
69554
69555 case DUK_EXTRAOP_INVLHS: {
69556 DUK_ERROR(thr, DUK_ERR_REFERENCE_ERROR, "invalid lvalue");
69557
69559 break;
69560 }
69561
69562 case DUK_EXTRAOP_UNM:
69563 case DUK_EXTRAOP_UNP: {
69564 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69565 duk__vm_arith_unary_op(thr, DUK__REGP(bc), bc, extraop);
69566 break;
69567 }
69568
69569 case DUK_EXTRAOP_DEBUGGER: {
69570 /* Opcode only emitted by compiler when debugger
69571 * support is enabled. Ignore it silently without
69572 * debugger support, in case it has been loaded
69573 * from precompiled bytecode.
69574 */
69575#if defined(DUK_USE_DEBUGGER_SUPPORT)
69576 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
69577 DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
69579 duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
69580 DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
69581 goto restart_execution;
69582 } else {
69583 DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
69584 }
69585#else
69586 DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
69587#endif
69588 break;
69589 }
69590
69591 case DUK_EXTRAOP_BREAK: {
69592 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69593
69594 DUK_DDD(DUK_DDDPRINT("BREAK: %ld", (long) bc));
69595
69598 goto restart_execution;
69599 }
69600
69601 case DUK_EXTRAOP_CONTINUE: {
69602 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69603
69604 DUK_DDD(DUK_DDDPRINT("CONTINUE: %ld", (long) bc));
69605
69608 goto restart_execution;
69609 }
69610
69611 case DUK_EXTRAOP_BNOT: {
69612 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69613
69614 duk__vm_bitwise_not(thr, DUK__REGP(bc), bc);
69615 break;
69616 }
69617
69618 case DUK_EXTRAOP_LNOT: {
69619 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69620 duk_tval *tv1;
69621
69622 tv1 = DUK__REGP(bc);
69623 duk__vm_logical_not(thr, tv1, tv1);
69624 break;
69625 }
69626
69627 case DUK_EXTRAOP_INSTOF: {
69628 duk_context *ctx = (duk_context *) thr;
69631 duk_bool_t tmp;
69632
69633 tmp = duk_js_instanceof(thr, DUK__REGP(b), DUK__REGCONSTP(c));
69634 duk_push_boolean(ctx, tmp);
69635 duk_replace(ctx, (duk_idx_t) b);
69636 break;
69637 }
69638
69639 case DUK_EXTRAOP_IN: {
69640 duk_context *ctx = (duk_context *) thr;
69643 duk_bool_t tmp;
69644
69645 tmp = duk_js_in(thr, DUK__REGP(b), DUK__REGCONSTP(c));
69646 duk_push_boolean(ctx, tmp);
69647 duk_replace(ctx, (duk_idx_t) b);
69648 break;
69649 }
69650
69651 case DUK_EXTRAOP_LABEL: {
69652 duk_catcher *cat;
69653 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69654
69655 /* allocate catcher and populate it (should be atomic) */
69656
69658 cat = thr->catchstack + thr->catchstack_top;
69659 thr->catchstack_top++;
69660
69662 cat->callstack_index = thr->callstack_top - 1;
69663 cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
69664 cat->idx_base = 0; /* unused for label */
69665 cat->h_varname = NULL;
69666
69667 DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
69668 "idx_base=%ld, h_varname=%!O, label_id=%ld",
69669 (long) cat->flags, (long) cat->callstack_index, (long) cat->pc_base,
69670 (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
69671
69672 curr_pc += 2; /* skip jump slots */
69673 break;
69674 }
69675
69676 case DUK_EXTRAOP_ENDLABEL: {
69677 duk_catcher *cat;
69678#if defined(DUK_USE_DDDPRINT) || defined(DUK_USE_ASSERTIONS)
69679 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69680#endif
69681#if defined(DUK_USE_DDDPRINT)
69682 DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
69683#endif
69684
69685 DUK_ASSERT(thr->catchstack_top >= 1);
69686
69687 cat = thr->catchstack + thr->catchstack_top - 1;
69688 DUK_UNREF(cat);
69691
69692 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69693 /* no need to unwind callstack */
69694 break;
69695 }
69696
69697 default: {
69698 DUK__INTERNAL_ERROR("invalid extra opcode");
69699 }
69700
69701 } /* end switch */
69702
69703 break;
69704 }
69705
69706 default: {
69707 /* this should never be possible, because the switch-case is
69708 * comprehensive
69709 */
69710 DUK__INTERNAL_ERROR("invalid opcode");
69711 break;
69712 }
69713
69714 } /* end switch */
69715 }
69717
69718#ifndef DUK_USE_VERBOSE_EXECUTOR_ERRORS
69719 internal_error:
69720 DUK_ERROR_INTERNAL(thr, "internal error in bytecode executor");
69721#endif
69722}
69723
69724#undef DUK__LONGJMP_RESTART
69725#undef DUK__LONGJMP_FINISHED
69726#undef DUK__LONGJMP_RETHROW
69727
69728#undef DUK__RETHAND_RESTART
69729#undef DUK__RETHAND_FINISHED
69730
69731#undef DUK__FUN
69732#undef DUK__STRICT
69733#undef DUK__REG
69734#undef DUK__REGP
69735#undef DUK__CONST
69736#undef DUK__CONSTP
69737#undef DUK__RCISREG
69738#undef DUK__REGCONST
69739#undef DUK__REGCONSTP
69740
69741#undef DUK__INTERNAL_ERROR
69742#undef DUK__SYNC_CURR_PC
69743#undef DUK__SYNC_AND_NULL_CURR_PC
69744/*
69745 * Ecmascript specification algorithm and conversion helpers.
69746 *
69747 * These helpers encapsulate the primitive Ecmascript operation
69748 * semantics, and are used by the bytecode executor and the API
69749 * (among other places). Note that some primitives are only
69750 * implemented as part of the API and have no "internal" helper.
69751 * (This is the case when an internal helper would not really be
69752 * useful; e.g. the operation is rare, uses value stack heavily,
69753 * etc.)
69754 *
69755 * The operation arguments depend on what is required to implement
69756 * the operation:
69757 *
69758 * - If an operation is simple and stateless, and has no side
69759 * effects, it won't take an duk_hthread argument and its
69760 * arguments may be duk_tval pointers (which are safe as long
69761 * as no side effects take place).
69762 *
69763 * - If complex coercions are required (e.g. a "ToNumber" coercion)
69764 * or errors may be thrown, the operation takes an duk_hthread
69765 * argument. This also implies that the operation may have
69766 * arbitrary side effects, invalidating any duk_tval pointers.
69767 *
69768 * - For operations with potential side effects, arguments can be
69769 * taken in several ways:
69770 *
69771 * a) as duk_tval pointers, which makes sense if the "common case"
69772 * can be resolved without side effects (e.g. coercion); the
69773 * arguments are pushed to the valstack for coercion if
69774 * necessary
69775 *
69776 * b) as duk_tval values
69777 *
69778 * c) implicitly on value stack top
69779 *
69780 * d) as indices to the value stack
69781 *
69782 * Future work:
69783 *
69784 * - Argument styles may not be the most sensible in every case now.
69785 *
69786 * - In-place coercions might be useful for several operations, if
69787 * in-place coercion is OK for the bytecode executor and the API.
69788 */
69789
69790/* include removed: duk_internal.h */
69792/*
69793 * [[DefaultValue]] (E5 Section 8.12.8)
69794 *
69795 * ==> implemented in the API.
69796 */
69797
69798/*
69799 * ToPrimitive() (E5 Section 9.1)
69800 *
69801 * ==> implemented in the API.
69802 */
69803
69804/*
69805 * ToBoolean() (E5 Section 9.2)
69806 */
69807
69809 switch (DUK_TVAL_GET_TAG(tv)) {
69810 case DUK_TAG_UNDEFINED:
69811 case DUK_TAG_NULL:
69812 return 0;
69813 case DUK_TAG_BOOLEAN:
69814 return DUK_TVAL_GET_BOOLEAN(tv);
69815 case DUK_TAG_STRING: {
69817 DUK_ASSERT(h != NULL);
69818 return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
69819 }
69820 case DUK_TAG_OBJECT: {
69821 return 1;
69822 }
69823 case DUK_TAG_BUFFER: {
69824 /* mimic semantics for strings */
69826 DUK_ASSERT(h != NULL);
69827 return (DUK_HBUFFER_GET_SIZE(h) > 0 ? 1 : 0);
69828 }
69829 case DUK_TAG_POINTER: {
69830 void *p = DUK_TVAL_GET_POINTER(tv);
69831 return (p != NULL ? 1 : 0);
69832 }
69833 case DUK_TAG_LIGHTFUNC: {
69834 return 1;
69835 }
69836#if defined(DUK_USE_FASTINT)
69837 case DUK_TAG_FASTINT:
69838 if (DUK_TVAL_GET_FASTINT(tv) != 0) {
69839 return 1;
69840 } else {
69841 return 0;
69842 }
69843#endif
69844 default: {
69845 /* number */
69846 duk_double_t d;
69847 int c;
69850 d = DUK_TVAL_GET_DOUBLE(tv);
69851 c = DUK_FPCLASSIFY((double) d);
69852 if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
69853 return 0;
69854 } else {
69855 return 1;
69856 }
69857 }
69858 }
69860}
69861
69862/*
69863 * ToNumber() (E5 Section 9.3)
69864 *
69865 * Value to convert must be on stack top, and is popped before exit.
69866 *
69867 * See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
69868 * http://www.cs.indiana.edu/~burger/fp/index.html
69869 *
69870 * Notes on the conversion:
69871 *
69872 * - There are specific requirements on the accuracy of the conversion
69873 * through a "Mathematical Value" (MV), so this conversion is not
69874 * trivial.
69875 *
69876 * - Quick rejects (e.g. based on first char) are difficult because
69877 * the grammar allows leading and trailing white space.
69878 *
69879 * - Quick reject based on string length is difficult even after
69880 * accounting for white space; there may be arbitrarily many
69881 * decimal digits.
69882 *
69883 * - Standard grammar allows decimal values ("123"), hex values
69884 * ("0x123") and infinities
69885 *
69886 * - Unlike source code literals, ToNumber() coerces empty strings
69887 * and strings with only whitespace to zero (not NaN).
69888 */
69889
69890/* E5 Section 9.3.1 */
69892 duk_context *ctx = (duk_context *) thr;
69893 duk_small_uint_t s2n_flags;
69894 duk_double_t d;
69895
69896 /* Quite lenient, e.g. allow empty as zero, but don't allow trailing
69897 * garbage.
69898 */
69899 s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
69910
69911 duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
69912 d = duk_get_number(ctx, -1);
69913 duk_pop(ctx);
69914
69915 return d;
69916}
69917
69919 duk_context *ctx = (duk_hthread *) thr;
69920
69921 DUK_ASSERT(thr != NULL);
69922 DUK_ASSERT(tv != NULL);
69923
69924 switch (DUK_TVAL_GET_TAG(tv)) {
69925 case DUK_TAG_UNDEFINED: {
69926 /* return a specific NaN (although not strictly necessary) */
69930 return du.d;
69931 }
69932 case DUK_TAG_NULL: {
69933 /* +0.0 */
69934 return 0.0;
69935 }
69936 case DUK_TAG_BOOLEAN: {
69937 if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
69938 return 1.0;
69939 }
69940 return 0.0;
69941 }
69942 case DUK_TAG_STRING: {
69944 duk_push_hstring(ctx, h);
69945 return duk__tonumber_string_raw(thr);
69946 }
69947 case DUK_TAG_OBJECT: {
69948 /* Note: ToPrimitive(object,hint) == [[DefaultValue]](object,hint),
69949 * so use [[DefaultValue]] directly.
69950 */
69951 duk_double_t d;
69952 duk_push_tval(ctx, tv);
69953 duk_to_defaultvalue(ctx, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */
69954
69955 /* recursive call for a primitive value (guaranteed not to cause second
69956 * recursion).
69957 */
69958 d = duk_js_tonumber(thr, duk_require_tval(ctx, -1));
69959
69960 duk_pop(ctx);
69961 return d;
69962 }
69963 case DUK_TAG_BUFFER: {
69964 /* Coerce like a string. This makes sense because addition also treats
69965 * buffers like strings.
69966 */
69968 duk_push_hbuffer(ctx, h);
69969 duk_to_string(ctx, -1); /* XXX: expensive, but numconv now expects to see a string */
69970 return duk__tonumber_string_raw(thr);
69971 }
69972 case DUK_TAG_POINTER: {
69973 /* Coerce like boolean */
69974 void *p = DUK_TVAL_GET_POINTER(tv);
69975 return (p != NULL ? 1.0 : 0.0);
69976 }
69977 case DUK_TAG_LIGHTFUNC: {
69978 /* +(function(){}) -> NaN */
69979 return DUK_DOUBLE_NAN;
69980 }
69981#if defined(DUK_USE_FASTINT)
69982 case DUK_TAG_FASTINT:
69983 return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
69984#endif
69985 default: {
69986 /* number */
69989 return DUK_TVAL_GET_DOUBLE(tv);
69990 }
69991 }
69992
69994}
69995
69996/*
69997 * ToInteger() (E5 Section 9.4)
69998 */
69999
70000/* exposed, used by e.g. duk_bi_date.c */
70003
70004 if (c == DUK_FP_NAN) {
70005 return 0.0;
70006 } else if (c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
70007 /* XXX: FP_ZERO check can be removed, the else clause handles it
70008 * correctly (preserving sign).
70009 */
70010 return x;
70011 } else {
70013 x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */
70014 if (s) {
70015 x = -x;
70016 }
70017 return x;
70018 }
70019}
70020
70022 /* XXX: fastint */
70023 duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */
70024 return duk_js_tointeger_number(d);
70025}
70026
70027/*
70028 * ToInt32(), ToUint32(), ToUint16() (E5 Sections 9.5, 9.6, 9.7)
70029 */
70030
70031/* combined algorithm matching E5 Sections 9.5 and 9.6 */
70035
70036 if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
70037 return 0.0;
70038 }
70039
70040
70041 /* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
70043 x = DUK_FLOOR(DUK_FABS(x));
70044 if (s) {
70045 x = -x;
70046 }
70047
70048 /* NOTE: fmod(x) result sign is same as sign of x, which
70049 * differs from what Javascript wants (see Section 9.6).
70050 */
70051
70052 x = DUK_FMOD(x, DUK_DOUBLE_2TO32); /* -> x in ]-2**32, 2**32[ */
70054 if (x < 0.0) {
70055 x += DUK_DOUBLE_2TO32;
70056 }
70057 /* -> x in [0, 2**32[ */
70058
70059 if (is_toint32) {
70060 if (x >= DUK_DOUBLE_2TO31) {
70061 /* x in [2**31, 2**32[ */
70062
70063 x -= DUK_DOUBLE_2TO32; /* -> x in [-2**31,2**31[ */
70064 }
70065 }
70066
70067 return x;
70068}
70069
70070DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
70072
70073#if defined(DUK_USE_FASTINT)
70074 if (DUK_TVAL_IS_FASTINT(tv)) {
70075 return DUK_TVAL_GET_FASTINT_I32(tv);
70076 }
70077#endif
70078
70079 d = duk_js_tonumber(thr, tv); /* invalidates tv */
70082 DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */
70083 DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */
70084 return (duk_int32_t) d;
70085}
70086
70087
70088DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
70090
70091#if defined(DUK_USE_FASTINT)
70092 if (DUK_TVAL_IS_FASTINT(tv)) {
70093 return DUK_TVAL_GET_FASTINT_U32(tv);
70094 }
70095#endif
70096
70097 d = duk_js_tonumber(thr, tv); /* invalidates tv */
70100 DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */
70101 DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */
70102 return (duk_uint32_t) d;
70103
70104}
70105
70106DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
70107 /* should be a safe way to compute this */
70108 return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
70109}
70110
70111/*
70112 * ToString() (E5 Section 9.8)
70113 *
70114 * ==> implemented in the API.
70115 */
70116
70117/*
70118 * ToObject() (E5 Section 9.9)
70119 *
70120 * ==> implemented in the API.
70121 */
70122
70123/*
70124 * CheckObjectCoercible() (E5 Section 9.10)
70125 *
70126 * Note: no API equivalent now.
70127 */
70128
70129#if 0 /* unused */
70130DUK_INTERNAL void duk_js_checkobjectcoercible(duk_hthread *thr, duk_tval *tv_x) {
70132
70133 /* Note: this must match ToObject() behavior */
70134
70135 if (tag == DUK_TAG_UNDEFINED ||
70136 tag == DUK_TAG_NULL ||
70137 tag == DUK_TAG_POINTER ||
70138 tag == DUK_TAG_BUFFER) {
70139 DUK_ERROR_TYPE(thr, "not object coercible");
70140 }
70141}
70142#endif
70143
70144/*
70145 * IsCallable() (E5 Section 9.11)
70146 *
70147 * XXX: API equivalent is a separate implementation now, and this has
70148 * currently no callers.
70149 */
70150
70151#if 0 /* unused */
70152DUK_INTERNAL duk_bool_t duk_js_iscallable(duk_tval *tv_x) {
70153 duk_hobject *obj;
70154
70155 if (!DUK_TVAL_IS_OBJECT(tv_x)) {
70156 return 0;
70157 }
70158 obj = DUK_TVAL_GET_OBJECT(tv_x);
70159 DUK_ASSERT(obj != NULL);
70160
70161 return DUK_HOBJECT_IS_CALLABLE(obj);
70162}
70163#endif
70164
70165/*
70166 * Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
70167 * 9.12). These have much in common so they can share some helpers.
70168 *
70169 * Future work notes:
70170 *
70171 * - Current implementation (and spec definition) has recursion; this should
70172 * be fixed if possible.
70173 *
70174 * - String-to-number coercion should be possible without going through the
70175 * value stack (and be more compact) if a shared helper is invoked.
70176 */
70177
70178/* Note that this is the same operation for strict and loose equality:
70179 * - E5 Section 11.9.3, step 1.c (loose)
70180 * - E5 Section 11.9.6, step 4 (strict)
70181 */
70182
70184#if defined(DUK_USE_PARANOID_MATH)
70185 /* Straightforward algorithm, makes fewer compiler assumptions. */
70188 if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
70189 return 0;
70190 }
70191 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
70192 return 1;
70193 }
70194 if (x == y) {
70195 return 1;
70196 }
70197 return 0;
70198#else /* DUK_USE_PARANOID_MATH */
70199 /* Better equivalent algorithm. If the compiler is compliant, C and
70200 * Ecmascript semantics are identical for this particular comparison.
70201 * In particular, NaNs must never compare equal and zeroes must compare
70202 * equal regardless of sign. Could also use a macro, but this inlines
70203 * already nicely (no difference on gcc, for instance).
70205 if (x == y) {
70206 /* IEEE requires that NaNs compare false */
70209 return 1;
70210 } else {
70211 /* IEEE requires that zeros compare the same regardless
70212 * of their signed, so if both x and y are zeroes, they
70213 * are caught above.
70214 */
70216 return 0;
70217 }
70218#endif /* DUK_USE_PARANOID_MATH */
70219}
70220
70222#if defined(DUK_USE_PARANOID_MATH)
70225
70226 if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
70227 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
70228 return 1;
70229 }
70230 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
70231 /* Note: cannot assume that a non-zero return value of signbit() would
70232 * always be the same -- hence cannot (portably) use something like:
70233 *
70234 * signbit(x) == signbit(y)
70235 */
70236 duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
70237 duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
70238 return (sx == sy);
70239 }
70240
70241 /* normal comparison; known:
70242 * - both x and y are not NaNs (but one of them can be)
70243 * - both x and y are not zero (but one of them can be)
70244 * - x and y may be denormal or infinite
70245 */
70246
70247 return (x == y);
70248#else /* DUK_USE_PARANOID_MATH */
70251
70252 if (x == y) {
70253 /* IEEE requires that NaNs compare false */
70256
70257 /* Using classification has smaller footprint than direct comparison. */
70258 if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
70259 /* Note: cannot assume that a non-zero return value of signbit() would
70260 * always be the same -- hence cannot (portably) use something like:
70261 *
70262 * signbit(x) == signbit(y)
70263 */
70264 duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
70265 duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
70266 return (sx == sy);
70267 }
70268 return 1;
70269 } else {
70270 /* IEEE requires that zeros compare the same regardless
70271 * of their signed, so if both x and y are zeroes, they
70272 * are caught above.
70273 */
70275
70276 /* Difference to non-strict/strict comparison is that NaNs compare
70277 * equal and signed zero signs matter.
70278 */
70279 if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
70280 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
70281 return 1;
70282 }
70283 return 0;
70284 }
70285#endif /* DUK_USE_PARANOID_MATH */
70286}
70287
70289 duk_context *ctx = (duk_context *) thr;
70290 duk_tval *tv_tmp;
70291
70292 /* If flags != 0 (strict or SameValue), thr can be NULL. For loose
70293 * equals comparison it must be != NULL.
70294 */
70295 DUK_ASSERT(flags != 0 || thr != NULL);
70296
70297 /*
70298 * Same type?
70299 *
70300 * Note: since number values have no explicit tag in the 8-byte
70301 * representation, need the awkward if + switch.
70302 */
70303
70304#if defined(DUK_USE_FASTINT)
70305 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
70306 if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
70307 return 1;
70308 } else {
70309 return 0;
70310 }
70311 }
70312 else
70313#endif
70314 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
70315 /* Catches both doubles and cases where only one argument is a fastint */
70316 if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
70317 /* SameValue */
70319 DUK_TVAL_GET_NUMBER(tv_y));
70320 } else {
70321 /* equals and strict equals */
70323 DUK_TVAL_GET_NUMBER(tv_y));
70324 }
70325 } else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
70326 switch (DUK_TVAL_GET_TAG(tv_x)) {
70327 case DUK_TAG_UNDEFINED:
70328 case DUK_TAG_NULL: {
70329 return 1;
70330 }
70331 case DUK_TAG_BOOLEAN: {
70332 return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
70333 }
70334 case DUK_TAG_POINTER: {
70335 return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
70336 }
70337 case DUK_TAG_STRING:
70338 case DUK_TAG_OBJECT: {
70339 /* heap pointer comparison suffices */
70340 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
70341 }
70342 case DUK_TAG_BUFFER: {
70343 if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
70344 /* heap pointer comparison suffices */
70345 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
70346 } else {
70347 /* non-strict equality for buffers compares contents */
70348 duk_hbuffer *h_x = DUK_TVAL_GET_BUFFER(tv_x);
70349 duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
70350 duk_size_t len_x = DUK_HBUFFER_GET_SIZE(h_x);
70351 duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
70352 void *buf_x;
70353 void *buf_y;
70354 if (len_x != len_y) {
70355 return 0;
70356 }
70357 buf_x = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_x);
70358 buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
70359 /* if len_x == len_y == 0, buf_x and/or buf_y may
70360 * be NULL, but that's OK.
70361 */
70362 DUK_ASSERT(len_x == len_y);
70363 DUK_ASSERT(len_x == 0 || buf_x != NULL);
70364 DUK_ASSERT(len_y == 0 || buf_y != NULL);
70365 return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
70366 }
70367 }
70368 case DUK_TAG_LIGHTFUNC: {
70369 /* At least 'magic' has a significant impact on function
70370 * identity.
70371 */
70372 duk_small_uint_t lf_flags_x;
70373 duk_small_uint_t lf_flags_y;
70374 duk_c_function func_x;
70375 duk_c_function func_y;
70376
70377 DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
70378 DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
70379 return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
70380 }
70381#if defined(DUK_USE_FASTINT)
70382 case DUK_TAG_FASTINT:
70383#endif
70384 default: {
70390 return 0;
70391 }
70392 }
70393 }
70394
70395 if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
70396 return 0;
70397 }
70398
70399 DUK_ASSERT(flags == 0); /* non-strict equality from here on */
70400
70401 /*
70402 * Types are different; various cases for non-strict comparison
70403 *
70404 * Since comparison is symmetric, we use a "swap trick" to reduce
70405 * code size.
70406 */
70407
70408 /* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
70409 if ((DUK_TVAL_IS_UNDEFINED(tv_x) && DUK_TVAL_IS_NULL(tv_y)) ||
70410 (DUK_TVAL_IS_NULL(tv_x) && DUK_TVAL_IS_UNDEFINED(tv_y))) {
70411 return 1;
70412 }
70413
70414 /* Number/string-or-buffer -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
70415 if (DUK_TVAL_IS_NUMBER(tv_x) && (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
70416 /* the next 'if' is guaranteed to match after swap */
70417 tv_tmp = tv_x;
70418 tv_x = tv_y;
70419 tv_y = tv_tmp;
70420 }
70421 if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) && DUK_TVAL_IS_NUMBER(tv_y)) {
70422 /* XXX: this is possible without resorting to the value stack */
70423 duk_double_t d1, d2;
70424 d2 = DUK_TVAL_GET_NUMBER(tv_y);
70425 duk_push_tval(ctx, tv_x);
70426 duk_to_string(ctx, -1); /* buffer values are coerced first to string here */
70427 duk_to_number(ctx, -1);
70428 d1 = duk_require_number(ctx, -1);
70429 duk_pop(ctx);
70430 return duk__js_equals_number(d1, d2);
70431 }
70432
70433 /* Buffer/string -> compare contents. */
70434 if (DUK_TVAL_IS_BUFFER(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
70435 tv_tmp = tv_x;
70436 tv_x = tv_y;
70437 tv_y = tv_tmp;
70438 }
70439 if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_BUFFER(tv_y)) {
70440 duk_hstring *h_x = DUK_TVAL_GET_STRING(tv_x);
70441 duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
70443 duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
70444 const void *buf_x;
70445 const void *buf_y;
70446 if (len_x != len_y) {
70447 return 0;
70448 }
70449 buf_x = (const void *) DUK_HSTRING_GET_DATA(h_x);
70450 buf_y = (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
70451 /* if len_x == len_y == 0, buf_x and/or buf_y may
70452 * be NULL, but that's OK.
70453 */
70454 DUK_ASSERT(len_x == len_y);
70455 DUK_ASSERT(len_x == 0 || buf_x != NULL);
70456 DUK_ASSERT(len_y == 0 || buf_y != NULL);
70457 return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
70458 }
70459
70460 /* Boolean/any -> coerce boolean to number and try again. If boolean is
70461 * compared to a pointer, the final comparison after coercion now always
70462 * yields false (as pointer vs. number compares to false), but this is
70463 * not special cased.
70464 */
70465 if (DUK_TVAL_IS_BOOLEAN(tv_x)) {
70466 tv_tmp = tv_x;
70467 tv_x = tv_y;
70468 tv_y = tv_tmp;
70469 }
70470 if (DUK_TVAL_IS_BOOLEAN(tv_y)) {
70471 /* ToNumber(bool) is +1.0 or 0.0. Tagged boolean value is always 0 or 1. */
70472 duk_bool_t rc;
70473 DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
70474 duk_push_tval(ctx, tv_x);
70476 rc = duk_js_equals_helper(thr,
70477 DUK_GET_TVAL_NEGIDX(ctx, -2),
70478 DUK_GET_TVAL_NEGIDX(ctx, -1),
70479 0 /*flags:nonstrict*/);
70480 duk_pop_2(ctx);
70481 return rc;
70482 }
70483
70484 /* String-number-buffer/object -> coerce object to primitive (apparently without hint), then try again. */
70485 if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_NUMBER(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) &&
70486 DUK_TVAL_IS_OBJECT(tv_y)) {
70487 tv_tmp = tv_x;
70488 tv_x = tv_y;
70489 tv_y = tv_tmp;
70490 }
70491 if (DUK_TVAL_IS_OBJECT(tv_x) &&
70492 (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_NUMBER(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
70493 duk_bool_t rc;
70494 duk_push_tval(ctx, tv_x);
70495 duk_push_tval(ctx, tv_y);
70496 duk_to_primitive(ctx, -2, DUK_HINT_NONE); /* apparently no hint? */
70497 rc = duk_js_equals_helper(thr,
70498 DUK_GET_TVAL_NEGIDX(ctx, -2),
70499 DUK_GET_TVAL_NEGIDX(ctx, -1),
70500 0 /*flags:nonstrict*/);
70501 duk_pop_2(ctx);
70502 return rc;
70504
70505 /* Nothing worked -> not equal. */
70506 return 0;
70507}
70508
70509/*
70510 * Comparisons (x >= y, x > y, x <= y, x < y)
70511 *
70512 * E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
70513 * flags to get the rest.
70514 */
70515
70516/* XXX: this should probably just operate on the stack top, because it
70517 * needs to push stuff on the stack anyway...
70518 */
70519
70520DUK_INTERNAL 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) {
70521 duk_size_t prefix_len;
70522 duk_small_int_t rc;
70523
70524 prefix_len = (len1 <= len2 ? len1 : len2);
70525
70526 /* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
70527 * inputs so no zero length check is needed.
70528 */
70529 rc = DUK_MEMCMP((const void *) buf1,
70530 (const void *) buf2,
70531 (size_t) prefix_len);
70532
70533 if (rc < 0) {
70534 return -1;
70535 } else if (rc > 0) {
70536 return 1;
70537 }
70538
70539 /* prefix matches, lengths matter now */
70540 if (len1 < len2) {
70541 /* e.g. "x" < "xx" */
70542 return -1;
70543 } else if (len1 > len2) {
70544 return 1;
70545 }
70546
70547 return 0;
70548}
70549
70551 /*
70552 * String comparison (E5 Section 11.8.5, step 4), which
70553 * needs to compare codepoint by codepoint.
70554 *
70555 * However, UTF-8 allows us to use strcmp directly: the shared
70556 * prefix will be encoded identically (UTF-8 has unique encoding)
70557 * and the first differing character can be compared with a simple
70558 * unsigned byte comparison (which strcmp does).
70559 *
70560 * This will not work properly for non-xutf-8 strings, but this
70561 * is not an issue for compliance.
70562 */
70563
70564 DUK_ASSERT(h1 != NULL);
70565 DUK_ASSERT(h2 != NULL);
70566
70567 return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
70568 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
70572
70573#if 0 /* unused */
70574DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
70575 /* Similar to String comparison. */
70576
70577 DUK_ASSERT(h1 != NULL);
70578 DUK_ASSERT(h2 != NULL);
70579 DUK_UNREF(heap);
70580
70581 return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
70582 (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
70585}
70586#endif
70587
70589 duk_context *ctx = (duk_context *) thr;
70590 duk_double_t d1, d2;
70591 duk_small_int_t c1, c2;
70592 duk_small_int_t s1, s2;
70593 duk_small_int_t rc;
70594 duk_bool_t retval;
70595
70596 /* Fast path for fastints */
70597#if defined(DUK_USE_FASTINT)
70598 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
70599 duk_int64_t v1 = DUK_TVAL_GET_FASTINT(tv_x);
70600 duk_int64_t v2 = DUK_TVAL_GET_FASTINT(tv_y);
70601 if (v1 < v2) {
70602 /* 'lt is true' */
70603 retval = 1;
70604 } else {
70605 retval = 0;
70606 }
70607 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70608 retval ^= 1;
70609 }
70610 return retval;
70611 }
70612#endif /* DUK_USE_FASTINT */
70613
70614 /* Fast path for numbers (one of which may be a fastint) */
70615#if 1 /* XXX: make fast paths optional for size minimization? */
70616 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
70617 d1 = DUK_TVAL_GET_NUMBER(tv_x);
70618 d2 = DUK_TVAL_GET_NUMBER(tv_y);
70619 c1 = DUK_FPCLASSIFY(d1);
70620 c2 = DUK_FPCLASSIFY(d2);
70621
70622 if (c1 == DUK_FP_NORMAL && c2 == DUK_FP_NORMAL) {
70623 /* XXX: this is a very narrow check, and doesn't cover
70624 * zeroes, subnormals, infinities, which compare normally.
70625 */
70626
70627 if (d1 < d2) {
70628 /* 'lt is true' */
70629 retval = 1;
70630 } else {
70631 retval = 0;
70632 }
70633 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70634 retval ^= 1;
70635 }
70636 return retval;
70637 }
70638 }
70639#endif
70640
70641 /* Slow path */
70642
70643 duk_push_tval(ctx, tv_x);
70644 duk_push_tval(ctx, tv_y);
70645
70649 } else {
70652 }
70653
70654 /* Note: reuse variables */
70655 tv_x = DUK_GET_TVAL_NEGIDX(ctx, -2);
70656 tv_y = DUK_GET_TVAL_NEGIDX(ctx, -1);
70657
70658 if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
70659 duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
70660 duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
70661 DUK_ASSERT(h1 != NULL);
70662 DUK_ASSERT(h2 != NULL);
70663
70664 rc = duk_js_string_compare(h1, h2);
70665 if (rc < 0) {
70666 goto lt_true;
70667 } else {
70668 goto lt_false;
70669 }
70670 } else {
70671 /* Ordering should not matter (E5 Section 11.8.5, step 3.a) but
70672 * preserve it just in case.
70673 */
70674
70676 d1 = duk_to_number(ctx, -2);
70677 d2 = duk_to_number(ctx, -1);
70678 } else {
70679 d2 = duk_to_number(ctx, -1);
70680 d1 = duk_to_number(ctx, -2);
70681 }
70682
70684 s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
70686 s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
70687
70688 if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
70689 goto lt_undefined;
70690 }
70691
70692 if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
70693 /* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
70694 * steps e, f, and g.
70695 */
70696 goto lt_false;
70697 }
70698
70699 if (d1 == d2) {
70700 goto lt_false;
70701 }
70702
70703 if (c1 == DUK_FP_INFINITE && s1 == 0) {
70704 /* x == +Infinity */
70705 goto lt_false;
70706 }
70707
70708 if (c2 == DUK_FP_INFINITE && s2 == 0) {
70709 /* y == +Infinity */
70710 goto lt_true;
70711 }
70712
70713 if (c2 == DUK_FP_INFINITE && s2 != 0) {
70714 /* y == -Infinity */
70715 goto lt_false;
70716 }
70717
70718 if (c1 == DUK_FP_INFINITE && s1 != 0) {
70719 /* x == -Infinity */
70720 goto lt_true;
70721 }
70722
70723 if (d1 < d2) {
70724 goto lt_true;
70725 }
70726
70727 goto lt_false;
70728 }
70729
70730 lt_undefined:
70731 /* Note: undefined from Section 11.8.5 always results in false
70732 * return (see e.g. Section 11.8.3) - hence special treatment here.
70733 */
70734 retval = 0;
70735 goto cleanup;
70736
70737 lt_true:
70738 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70739 retval = 0;
70740 goto cleanup;
70741 } else {
70742 retval = 1;
70743 goto cleanup;
70744 }
70745 /* never here */
70746
70747 lt_false:
70748 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70749 retval = 1;
70750 goto cleanup;
70751 } else {
70752 retval = 0;
70753 goto cleanup;
70754 }
70755 /* never here */
70756
70757 cleanup:
70758 duk_pop_2(ctx);
70759 return retval;
70760}
70761
70762/*
70763 * instanceof
70764 */
70766/*
70767 * E5 Section 11.8.6 describes the main algorithm, which uses
70768 * [[HasInstance]]. [[HasInstance]] is defined for only
70769 * function objects:
70770 *
70771 * - Normal functions:
70772 * E5 Section 15.3.5.3
70773 * - Functions established with Function.prototype.bind():
70774 * E5 Section 15.3.4.5.3
70775 *
70776 * For other objects, a TypeError is thrown.
70777 *
70778 * Limited Proxy support: don't support 'getPrototypeOf' trap but
70779 * continue lookup in Proxy target if the value is a Proxy.
70780 */
70781
70783 duk_context *ctx = (duk_context *) thr;
70784 duk_hobject *func;
70785 duk_hobject *val;
70787 duk_uint_t sanity;
70788
70789 /*
70790 * Get the values onto the stack first. It would be possible to cover
70791 * some normal cases without resorting to the value stack.
70792 *
70793 * The right hand side could be a light function (as they generally
70794 * behave like objects). Light functions never have a 'prototype'
70795 * property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
70796 * Using duk_require_hobject() is thus correct (except for error msg).
70797 */
70798
70799 duk_push_tval(ctx, tv_x);
70800 duk_push_tval(ctx, tv_y);
70801 func = duk_require_hobject(ctx, -1);
70802
70803 /*
70804 * For bound objects, [[HasInstance]] just calls the target function
70805 * [[HasInstance]]. If that is again a bound object, repeat until
70806 * we find a non-bound Function object.
70807 */
70808
70809 /* XXX: this bound function resolution also happens elsewhere,
70810 * move into a shared helper.
70811 */
70812
70814 do {
70815 /* check func supports [[HasInstance]] (this is checked for every function
70816 * in the bound chain, including the final one)
70817 */
70818
70819 if (!DUK_HOBJECT_IS_CALLABLE(func)) {
70820 /*
70821 * Note: of native Ecmascript objects, only Function instances
70822 * have a [[HasInstance]] internal property. Custom objects might
70823 * also have it, but not in current implementation.
70824 *
70825 * XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
70826 */
70827 DUK_ERROR_TYPE(thr, "invalid instanceof rval");
70828 }
70829
70830 if (!DUK_HOBJECT_HAS_BOUND(func)) {
70831 break;
70832 }
70833
70834 /* [ ... lval rval ] */
70835
70836 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [ ... lval rval new_rval ] */
70837 duk_replace(ctx, -1); /* -> [ ... lval new_rval ] */
70838 func = duk_require_hobject(ctx, -1);
70839
70840 /* func support for [[HasInstance]] checked in the beginning of the loop */
70841 } while (--sanity > 0);
70842
70843 if (sanity == 0) {
70845 }
70846
70847 /*
70848 * 'func' is now a non-bound object which supports [[HasInstance]]
70849 * (which here just means DUK_HOBJECT_FLAG_CALLABLE). Move on
70850 * to execute E5 Section 15.3.5.3.
70851 */
70852
70855
70856 /* [ ... lval rval(func) ] */
70857
70858 /* Handle lightfuncs through object coercion for now. */
70859 /* XXX: direct implementation */
70860 val = duk_get_hobject_or_lfunc_coerce(ctx, -2);
70861 if (!val) {
70862 goto pop_and_false;
70863 }
70864
70865 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_PROTOTYPE); /* -> [ ... lval rval rval.prototype ] */
70866 proto = duk_require_hobject(ctx, -1);
70867 duk_pop(ctx); /* -> [ ... lval rval ] */
70868
70869 DUK_ASSERT(val != NULL);
70870
70871#if defined(DUK_USE_ES6_PROXY)
70872 val = duk_hobject_resolve_proxy_target(thr, val);
70873 DUK_ASSERT(val != NULL);
70874#endif
70875
70877 do {
70878 /*
70879 * Note: prototype chain is followed BEFORE first comparison. This
70880 * means that the instanceof lval is never itself compared to the
70881 * rval.prototype property. This is apparently intentional, see E5
70882 * Section 15.3.5.3, step 4.a.
70883 *
70884 * Also note:
70885 *
70886 * js> (function() {}) instanceof Function
70887 * true
70888 * js> Function instanceof Function
70889 * true
70890 *
70891 * For the latter, h_proto will be Function.prototype, which is the
70892 * built-in Function prototype. Because Function.[[Prototype]] is
70893 * also the built-in Function prototype, the result is true.
70894 */
70895
70896 DUK_ASSERT(val != NULL);
70897 val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
70898
70899 if (!val) {
70900 goto pop_and_false;
70901 }
70902
70903 DUK_ASSERT(val != NULL);
70904#if defined(DUK_USE_ES6_PROXY)
70905 val = duk_hobject_resolve_proxy_target(thr, val);
70906#endif
70907
70908 if (val == proto) {
70909 goto pop_and_true;
70910 }
70911
70912 /* follow prototype chain */
70913 } while (--sanity > 0);
70914
70915 if (sanity == 0) {
70917 }
70919
70920 pop_and_false:
70921 duk_pop_2(ctx);
70922 return 0;
70923
70924 pop_and_true:
70925 duk_pop_2(ctx);
70926 return 1;
70927}
70928
70929/*
70930 * in
70931 */
70932
70933/*
70934 * E5 Sections 11.8.7, 8.12.6.
70935 *
70936 * Basically just a property existence check using [[HasProperty]].
70937 */
70938
70940 duk_context *ctx = (duk_context *) thr;
70941 duk_bool_t retval;
70942
70943 /*
70944 * Get the values onto the stack first. It would be possible to cover
70945 * some normal cases without resorting to the value stack (e.g. if
70946 * lval is already a string).
70947 */
70948
70949 /* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
70950 * must be string coerced before the internal HasProperty() algorithm is
70951 * invoked. A fast path skipping coercion could be safely implemented for
70952 * numbers (as number-to-string coercion has no side effects). For ES6
70953 * proxy behavior, the trap 'key' argument must be in a string coerced
70954 * form (which is a shame).
70955 */
70956
70957 /* TypeError if rval is not an object (or lightfunc which should behave
70958 * like a Function instance).
70959 */
70960 duk_push_tval(ctx, tv_x);
70961 duk_push_tval(ctx, tv_y);
70963 duk_to_string(ctx, -2); /* coerce lval with ToString() */
70964
70965 retval = duk_hobject_hasprop(thr,
70966 DUK_GET_TVAL_NEGIDX(ctx, -1),
70967 DUK_GET_TVAL_NEGIDX(ctx, -2));
70968
70969 duk_pop_2(ctx);
70970 return retval;
70971}
70972
70973/*
70974 * typeof
70975 *
70976 * E5 Section 11.4.3.
70977 *
70978 * Very straightforward. The only question is what to return for our
70979 * non-standard tag / object types.
70980 *
70981 * There is an unfortunate string constant define naming problem with
70982 * typeof return values for e.g. "Object" and "object"; careful with
70983 * the built-in string defines. The LC_XXX defines are used for the
70984 * lowercase variants now.
70985 */
70986
70988 duk_small_int_t stridx = 0;
70989
70990 DUK_UNREF(thr);
70991
70992 switch (DUK_TVAL_GET_TAG(tv_x)) {
70993 case DUK_TAG_UNDEFINED: {
70994 stridx = DUK_STRIDX_LC_UNDEFINED;
70995 break;
70996 }
70997 case DUK_TAG_NULL: {
70998 /* Note: not a typo, "object" is returned for a null value */
70999 stridx = DUK_STRIDX_LC_OBJECT;
71000 break;
71001 }
71002 case DUK_TAG_BOOLEAN: {
71003 stridx = DUK_STRIDX_LC_BOOLEAN;
71004 break;
71005 }
71006 case DUK_TAG_POINTER: {
71007 /* implementation specific */
71008 stridx = DUK_STRIDX_LC_POINTER;
71009 break;
71010 }
71011 case DUK_TAG_STRING: {
71012 stridx = DUK_STRIDX_LC_STRING;
71013 break;
71014 }
71015 case DUK_TAG_OBJECT: {
71016 duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
71017 DUK_ASSERT(obj != NULL);
71018 if (DUK_HOBJECT_IS_CALLABLE(obj)) {
71019 stridx = DUK_STRIDX_LC_FUNCTION;
71020 } else {
71021 stridx = DUK_STRIDX_LC_OBJECT;
71022 }
71023 break;
71024 }
71025 case DUK_TAG_BUFFER: {
71026 /* implementation specific */
71027 stridx = DUK_STRIDX_LC_BUFFER;
71028 break;
71029 }
71030 case DUK_TAG_LIGHTFUNC: {
71031 stridx = DUK_STRIDX_LC_FUNCTION;
71032 break;
71033 }
71034#if defined(DUK_USE_FASTINT)
71035 case DUK_TAG_FASTINT:
71036#endif
71037 default: {
71038 /* number */
71041 stridx = DUK_STRIDX_LC_NUMBER;
71042 break;
71044 }
71045
71046 DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
71047 return DUK_HTHREAD_GET_STRING(thr, stridx);
71048}
71049
71050/*
71051 * Array index and length
71052 *
71053 * Array index: E5 Section 15.4
71054 * Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
71055 *
71056 * The DUK_HSTRING_GET_ARRIDX_SLOW() and DUK_HSTRING_GET_ARRIDX_FAST() macros
71057 * call duk_js_to_arrayindex_string_helper().
71058 */
71059
71060DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx) {
71061 duk_uarridx_t res, new_res;
71062
71063 if (blen == 0 || blen > 10) {
71064 goto parse_fail;
71065 }
71066 if (str[0] == (duk_uint8_t) '0' && blen > 1) {
71067 goto parse_fail;
71068 }
71069
71070 /* Accept 32-bit decimal integers, no leading zeroes, signs, etc.
71071 * Leading zeroes are not accepted (zero index "0" is an exception
71072 * handled above).
71073 */
71074
71075 res = 0;
71076 while (blen-- > 0) {
71077 duk_uint8_t c = *str++;
71078 if (c >= (duk_uint8_t) '0' && c <= (duk_uint8_t) '9') {
71079 new_res = res * 10 + (duk_uint32_t) (c - (duk_uint8_t) '0');
71080 if (new_res < res) {
71081 /* overflow, more than 32 bits -> not an array index */
71082 goto parse_fail;
71083 }
71084 res = new_res;
71085 } else {
71086 goto parse_fail;
71087 }
71088 }
71089
71090 *out_idx = res;
71091 return 1;
71092
71093 parse_fail:
71094 *out_idx = DUK_HSTRING_NO_ARRAY_INDEX;
71095 return 0;
71096}
71097
71098/* Called by duk_hstring.h macros */
71100 duk_uarridx_t res;
71101 duk_small_int_t rc;
71102
71103 if (!DUK_HSTRING_HAS_ARRIDX(h)) {
71105 }
71106
71109 &res);
71110 DUK_UNREF(rc);
71111 DUK_ASSERT(rc != 0);
71112 return res;
71113}
71114/*
71115 * Identifier access and function closure handling.
71116 *
71117 * Provides the primitives for slow path identifier accesses: GETVAR,
71118 * PUTVAR, DELVAR, etc. The fast path, direct register accesses, should
71119 * be used for most identifier accesses. Consequently, these slow path
71120 * primitives should be optimized for maximum compactness.
71121 *
71122 * Ecmascript environment records (declarative and object) are represented
71123 * as internal objects with control keys. Environment records have a
71124 * parent record ("outer environment reference") which is represented by
71125 * the implicit prototype for technical reasons (in other words, it is a
71126 * convenient field). The prototype chain is not followed in the ordinary
71127 * sense for variable lookups.
71128 *
71129 * See identifier-handling.rst for more details on the identifier algorithms
71130 * and the internal representation. See function-objects.rst for details on
71131 * what function templates and instances are expected to look like.
71132 *
71133 * Care must be taken to avoid duk_tval pointer invalidation caused by
71134 * e.g. value stack or object resizing.
71136 * TODO: properties for function instances could be initialized much more
71137 * efficiently by creating a property allocation for a certain size and
71138 * filling in keys and values directly (and INCREFing both with "bulk incref"
71139 * primitives.
71141 * XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
71142 * awkward (especially because they follow the prototype chain); rework
71143 * if "raw" own property helpers are added.
71144 */
71145
71146/* include removed: duk_internal.h */
71147
71148/*
71149 * Local result type for duk__get_identifier_reference() lookup.
71150 */
71151
71152typedef struct {
71153 duk_hobject *holder; /* for object-bound identifiers */
71154 duk_tval *value; /* for register-bound and declarative env identifiers */
71155 duk_int_t attrs; /* property attributes for identifier (relevant if value != NULL) */
71156 duk_tval *this_binding;
71157 duk_hobject *env;
71159
71160/*
71161 * Create a new function object based on a "template function" which contains
71162 * compiled bytecode, constants, etc, but lacks a lexical environment.
71163 *
71164 * Ecmascript requires that each created closure is a separate object, with
71165 * its own set of editable properties. However, structured property values
71166 * (such as the formal arguments list and the variable map) are shared.
71167 * Also the bytecode, constants, and inner functions are shared.
71168 *
71169 * See E5 Section 13.2 for detailed requirements on the function objects;
71170 * there are no similar requirements for function "templates" which are an
71171 * implementation dependent internal feature. Also see function-objects.rst
71172 * for a discussion on the function instance properties provided by this
71173 * implementation.
71174 *
71175 * Notes:
71176 *
71177 * * Order of internal properties should match frequency of use, since the
71178 * properties will be linearly scanned on lookup (functions usually don't
71179 * have enough properties to warrant a hash part).
71180 *
71181 * * The created closure is independent of its template; they do share the
71182 * same 'data' buffer object, but the template object itself can be freed
71183 * even if the closure object remains reachable.
71184 */
71185
71187 duk_tval *tv, *tv_end;
71188 duk_hobject **funcs, **funcs_end;
71189
71190 /* If function creation fails due to out-of-memory, the data buffer
71191 * pointer may be NULL in some cases. That's actually possible for
71192 * GC code, but shouldn't be possible here because the incomplete
71193 * function will be unwound from the value stack and never instantiated.
71194 */
71196 DUK_UNREF(thr);
71197
71200 while (tv < tv_end) {
71201 DUK_TVAL_INCREF(thr, tv);
71202 tv++;
71204
71206 funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
71207 while (funcs < funcs_end) {
71209 funcs++;
71210 }
71211}
71212
71213/* Push a new closure on the stack.
71215 * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
71216 * is created when the function is called, only outer_lex_env matters
71217 * (outer_var_env is ignored and may or may not be same as outer_lex_env).
71218 */
71219
71220DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
71221 /* order: most frequent to least frequent */
71228};
71229
71232 duk_hcompiledfunction *fun_temp,
71233 duk_hobject *outer_var_env,
71234 duk_hobject *outer_lex_env,
71235 duk_bool_t add_auto_proto) {
71236 duk_context *ctx = (duk_context *) thr;
71237 duk_hcompiledfunction *fun_clos;
71239 duk_uint_t len_value;
71240
71241 DUK_ASSERT(fun_temp != NULL);
71245 DUK_ASSERT(outer_var_env != NULL);
71246 DUK_ASSERT(outer_lex_env != NULL);
71247 DUK_UNREF(len_value);
71248
71250 duk_push_hobject(ctx, &fun_temp->obj); /* -> [ ... closure template ] */
71251
71252 fun_clos = (duk_hcompiledfunction *) duk_get_hcompiledfunction(ctx, -2);
71253 DUK_ASSERT(fun_clos != NULL);
71258
71262
71263 /* Note: all references inside 'data' need to get their refcounts
71264 * upped too. This is the case because refcounts are decreased
71265 * through every function referencing 'data' independently.
71266 */
71267
71269 duk__inc_data_inner_refcounts(thr, fun_temp);
71270
71271 fun_clos->nregs = fun_temp->nregs;
71272 fun_clos->nargs = fun_temp->nargs;
71273#if defined(DUK_USE_DEBUGGER_SUPPORT)
71274 fun_clos->start_line = fun_temp->start_line;
71275 fun_clos->end_line = fun_temp->end_line;
71276#endif
71277
71281
71282 /* XXX: could also copy from template, but there's no way to have any
71283 * other value here now (used code has no access to the template).
71284 */
71286
71287 /*
71288 * Init/assert flags, copying them where appropriate. Some flags
71289 * (like NEWENV) are processed separately below.
71290 */
71291
71292 /* XXX: copy flags using a mask */
71293
71295 DUK_HOBJECT_SET_CONSTRUCTABLE(&fun_clos->obj); /* Note: not set in template (has no "prototype") */
71297 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&fun_clos->obj));
71301 /* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
71302 if (DUK_HOBJECT_HAS_STRICT(&fun_temp->obj)) {
71303 DUK_HOBJECT_SET_STRICT(&fun_clos->obj);
71304 }
71305 if (DUK_HOBJECT_HAS_NOTAIL(&fun_temp->obj)) {
71306 DUK_HOBJECT_SET_NOTAIL(&fun_clos->obj);
71307 }
71308 /* DUK_HOBJECT_FLAG_NEWENV: handled below */
71309 if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) {
71310 /* Although NAMEBINDING is not directly needed for using
71311 * function instances, it's needed by bytecode dump/load
71312 * so copy it too.
71313 */
71314 DUK_HOBJECT_SET_NAMEBINDING(&fun_clos->obj);
71315 }
71316 if (DUK_HOBJECT_HAS_CREATEARGS(&fun_temp->obj)) {
71317 DUK_HOBJECT_SET_CREATEARGS(&fun_clos->obj);
71318 }
71322
71323 /*
71324 * Setup environment record properties based on the template and
71325 * its flags.
71326 *
71327 * If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
71328 * records represent identifiers "outside" the function; the
71329 * "inner" environment records are created on demand. Otherwise,
71330 * the environment records are those that will be directly used
71331 * (e.g. for declarations).
71332 *
71333 * _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
71334 * so _Varenv is only set if _Lexenv != _Varenv.
71335 *
71336 * This is relatively complex, see doc/identifier-handling.rst.
71337 */
71338
71339 if (DUK_HOBJECT_HAS_NEWENV(&fun_temp->obj)) {
71340 DUK_HOBJECT_SET_NEWENV(&fun_clos->obj);
71341
71342 if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) {
71344
71345 /*
71346 * Named function expression, name needs to be bound
71347 * in an intermediate environment record. The "outer"
71348 * lexical/variable environment will thus be:
71349 *
71350 * a) { funcname: <func>, __prototype: outer_lex_env }
71351 * b) { funcname: <func>, __prototype: <globalenv> } (if outer_lex_env missing)
71352 */
71353
71354 DUK_ASSERT(duk_has_prop_stridx(ctx, -1, DUK_STRIDX_NAME)); /* required if NAMEBINDING set */
71355
71356 if (outer_lex_env) {
71357 proto = outer_lex_env;
71358 } else {
71360 }
71361
71362 /* -> [ ... closure template env ] */
71366 proto);
71367
71368 /* It's important that duk_xdef_prop() is a 'raw define' so that any
71369 * properties in an ancestor are never an issue (they should never be
71370 * e.g. non-writable, but just in case).
71371 */
71372 duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME); /* -> [ ... closure template env funcname ] */
71373 duk_dup(ctx, -4); /* -> [ ... closure template env funcname closure ] */
71374 duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template env ] */
71375 /* env[funcname] = closure */
71376
71377 /* [ ... closure template env ] */
71378
71380 /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
71381 * will be ignored anyway
71382 */
71383
71384 /* [ ... closure template ] */
71385 } else {
71386 /*
71387 * Other cases (function declaration, anonymous function expression,
71388 * strict direct eval code). The "outer" environment will be whatever
71389 * the caller gave us.
71390 */
71391
71392 duk_push_hobject(ctx, outer_lex_env); /* -> [ ... closure template env ] */
71394 /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
71395 * will be ignored anyway
71396 */
71397
71398 /* [ ... closure template ] */
71399 }
71400 } else {
71401 /*
71402 * Function gets no new environment when called. This is the
71403 * case for global code, indirect eval code, and non-strict
71404 * direct eval code. There is no direct correspondence to the
71405 * E5 specification, as global/eval code is not exposed as a
71406 * function.
71407 */
71408
71410
71411 duk_push_hobject(ctx, outer_lex_env); /* -> [ ... closure template env ] */
71413
71414 if (outer_var_env != outer_lex_env) {
71415 duk_push_hobject(ctx, outer_var_env); /* -> [ ... closure template env ] */
71417 }
71418 }
71419#ifdef DUK_USE_DDDPRINT
71422 DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipT, lexenv -> %!ipT",
71423 (duk_tval *) duk_get_tval(ctx, -2),
71424 (duk_tval *) duk_get_tval(ctx, -1)));
71425 duk_pop_2(ctx);
71426#endif
71427
71428 /*
71429 * Copy some internal properties directly
71430 *
71431 * The properties will be writable and configurable, but not enumerable.
71432 */
71433
71434 /* [ ... closure template ] */
71435
71436 DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
71437 (duk_tval *) duk_get_tval(ctx, -2),
71438 (duk_tval *) duk_get_tval(ctx, -1)));
71439
71440 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
71442 if (duk_get_prop_stridx(ctx, -1, stridx)) {
71443 /* [ ... closure template val ] */
71444 DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
71446 } else {
71447 DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
71448 duk_pop(ctx);
71449 }
71450 }
71451
71452 /*
71453 * "length" maps to number of formals (E5 Section 13.2) for function
71454 * declarations/expressions (non-bound functions). Note that 'nargs'
71455 * is NOT necessarily equal to the number of arguments.
71456 */
71457
71458 /* [ ... closure template ] */
71459
71460 len_value = 0;
71461
71462 /* XXX: use helper for size optimization */
71464 /* [ ... closure template formals ] */
71466 DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_UINT_MAX); /* formal arg limits */
71467 len_value = (duk_uint_t) duk_get_length(ctx, -1);
71468 } else {
71469 /* XXX: what to do if _Formals is not empty but compiler has
71470 * optimized it away -- read length from an explicit property
71471 * then?
71472 */
71473 }
71474 duk_pop(ctx);
71475
71476 duk_push_uint(ctx, len_value); /* [ ... closure template len_value ] */
71478
71479 /*
71480 * "prototype" is, by default, a fresh object with the "constructor"
71481 * property.
71482 *
71483 * Note that this creates a circular reference for every function
71484 * instance (closure) which prevents refcount-based collection of
71485 * function instances.
71486 *
71487 * XXX: Try to avoid creating the default prototype object, because
71488 * many functions are not used as constructors and the default
71489 * prototype is unnecessary. Perhaps it could be created on-demand
71490 * when it is first accessed?
71491 */
71492
71493 /* [ ... closure template ] */
71494
71495 if (add_auto_proto) {
71496 duk_push_object(ctx); /* -> [ ... closure template newobj ] */
71497 duk_dup(ctx, -3); /* -> [ ... closure template newobj closure ] */
71498 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* -> [ ... closure template newobj ] */
71499 duk_compact(ctx, -1); /* compact the prototype */
71500 duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); /* -> [ ... closure template ] */
71501 }
71502
71503 /*
71504 * "arguments" and "caller" must be mapped to throwers for strict
71505 * mode and bound functions (E5 Section 15.3.5).
71506 *
71507 * XXX: This is expensive to have for every strict function instance.
71508 * Try to implement as virtual properties or on-demand created properties.
71509 */
71510
71511 /* [ ... closure template ] */
71512
71513 if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
71516 } else {
71517#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
71518 DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
71519 duk_push_null(ctx);
71521#else
71522 DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
71523#endif
71524 }
71525
71526 /*
71527 * "name" is a non-standard property found in at least V8, Rhino, smjs.
71528 * For Rhino and smjs it is non-writable, non-enumerable, and non-configurable;
71529 * for V8 it is writable, non-enumerable, non-configurable. It is also defined
71530 * for an anonymous function expression in which case the value is an empty string.
71531 * We could also leave name 'undefined' for anonymous functions but that would
71532 * differ from behavior of other engines, so use an empty string.
71533 *
71534 * XXX: make optional? costs something per function.
71535 */
71536
71537 /* [ ... closure template ] */
71538
71539 if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME)) {
71540 /* [ ... closure template name ] */
71541 DUK_ASSERT(duk_is_string(ctx, -1));
71542 } else {
71543 /* [ ... closure template undefined ] */
71544 duk_pop(ctx);
71546 }
71547 duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template ] */
71548
71549 /*
71550 * Compact the closure, in most cases no properties will be added later.
71551 * Also, without this the closures end up having unused property slots
71552 * (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
71553 * A better future solution would be to allocate the closure directly
71554 * to correct size (and setup the properties directly without going
71555 * through the API).
71556 */
71557
71558 duk_compact(ctx, -2);
71559
71560 /*
71561 * Some assertions (E5 Section 13.2).
71562 */
71563
71568 DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE) != 0);
71569 DUK_ASSERT(duk_has_prop_stridx(ctx, -2, DUK_STRIDX_NAME) != 0); /* non-standard */
71570 DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
71571 duk_has_prop_stridx(ctx, -2, DUK_STRIDX_CALLER) != 0);
71572 DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
71574
71575 /*
71576 * Finish
71577 */
71578
71579 /* [ ... closure template ] */
71580
71581 DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
71583 (duk_tval *) duk_get_tval(ctx, -2)));
71584
71585 duk_pop(ctx);
71586
71587 /* [ ... closure ] */
71588}
71589
71590/*
71591 * Delayed activation environment record initialization (for functions
71592 * with NEWENV).
71593 *
71594 * The non-delayed initialization is handled by duk_handle_call().
71595 */
71596
71597/* shared helper */
71600 duk_hobject *func,
71601 duk_size_t idx_bottom) {
71602 duk_context *ctx = (duk_context *) thr;
71603 duk_hobject *env;
71604 duk_hobject *parent;
71605 duk_tval *tv;
71606
71607 DUK_ASSERT(thr != NULL);
71608 DUK_ASSERT(func != NULL);
71609
71611 if (tv) {
71614 parent = DUK_TVAL_GET_OBJECT(tv);
71615 } else {
71616 parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
71617 }
71618
71619 (void) duk_push_object_helper(ctx,
71622 -1); /* no prototype, updated below */
71623 env = duk_require_hobject(ctx, -1);
71624 DUK_ASSERT(env != NULL);
71625 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, env, parent); /* parent env is the prototype */
71626
71627 /* open scope information, for compiled functions only */
71628
71630 duk_push_hthread(ctx, thr);
71632 duk_push_hobject(ctx, func);
71634 duk_push_size_t(ctx, idx_bottom);
71636 }
71637
71638 return env;
71639}
71640
71643 duk_activation *act) {
71644 duk_context *ctx = (duk_context *) thr;
71645 duk_hobject *func;
71646 duk_hobject *env;
71647
71648 func = DUK_ACT_GET_FUNC(act);
71649 DUK_ASSERT(func != NULL);
71650 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func)); /* bound functions are never in act 'func' */
71651
71652 /*
71653 * Delayed initialization only occurs for 'NEWENV' functions.
71654 */
71655
71657 DUK_ASSERT(act->lex_env == NULL);
71658 DUK_ASSERT(act->var_env == NULL);
71659
71661 DUK_ASSERT(env != NULL);
71662
71663 DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
71664#ifdef DUK_USE_DDDPRINT
71665 {
71666 duk_hobject *p = env;
71667 while (p) {
71668 DUK_DDD(DUK_DDDPRINT(" -> %!ipO", (duk_heaphdr *) p));
71669 p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
71670 }
71671 }
71672#endif
71673
71674 act->lex_env = env;
71675 act->var_env = env;
71676 DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (here 2 times) */
71677 DUK_HOBJECT_INCREF(thr, env);
71678
71679 duk_pop(ctx);
71681
71682/*
71683 * Closing environment records.
71684 *
71685 * The environment record MUST be closed with the thread where its activation
71686 * is. In other words (if 'env' is open):
71687 *
71688 * - 'thr' must match _env.thread
71689 * - 'func' must match _env.callee
71690 * - 'regbase' must match _env.regbase
71691 *
71692 * These are not looked up from the env to minimize code size.
71693 *
71694 * XXX: should access the own properties directly instead of using the API
71695 */
71696
71698 duk_context *ctx = (duk_context *) thr;
71700
71701 DUK_ASSERT(thr != NULL);
71702 DUK_ASSERT(env != NULL);
71703 /* func is NULL for lightfuncs */
71704
71706 DUK_DDD(DUK_DDDPRINT("environment record not a declarative record, "
71707 "or already closed: %!iO",
71708 (duk_heaphdr *) env));
71709 return;
71710 }
71711
71712 DUK_DDD(DUK_DDDPRINT("closing environment record: %!iO, func: %!iO, regbase: %ld",
71713 (duk_heaphdr *) env, (duk_heaphdr *) func, (long) regbase));
71714
71715 duk_push_hobject(ctx, env);
71716
71717 /* assertions: env must be closed in the same thread as where it runs */
71718#ifdef DUK_USE_ASSERTIONS
71719 {
71720 /* [... env] */
71721
71723 DUK_ASSERT(duk_is_object(ctx, -1));
71724 DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) func);
71725 }
71726 duk_pop(ctx);
71727
71729 DUK_ASSERT(duk_is_object(ctx, -1));
71730 DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) thr);
71731 }
71732 duk_pop(ctx);
71733
71735 DUK_ASSERT(duk_is_number(ctx, -1));
71736 DUK_ASSERT(duk_get_number(ctx, -1) == (double) regbase);
71737 }
71738 duk_pop(ctx);
71739
71740 /* [... env] */
71741 }
71742#endif
71743
71744 if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
71745 duk_hobject *varmap;
71746 duk_hstring *key;
71747 duk_tval *tv;
71748 duk_uint_t regnum;
71749
71750 /* XXX: additional conditions when to close variables? we don't want to do it
71751 * unless the environment may have "escaped" (referenced in a function closure).
71752 * With delayed environments, the existence is probably good enough of a check.
71753 */
71754
71755 /* XXX: any way to detect faster whether something needs to be closed?
71756 * We now look up _Callee and then skip the rest.
71757 */
71758
71759 /* Note: we rely on the _Varmap having a bunch of nice properties, like:
71760 * - being compacted and unmodified during this process
71761 * - not containing an array part
71762 * - having correct value types
71763 */
71764
71765 /* [... env] */
71766
71768 DUK_DDD(DUK_DDDPRINT("env has no callee property, nothing to close; re-delete the control properties just in case"));
71769 duk_pop(ctx);
71770 goto skip_varmap;
71771 }
71772
71773 /* [... env callee] */
71774
71776 DUK_DDD(DUK_DDDPRINT("callee has no varmap property, nothing to close; delete the control properties"));
71777 duk_pop_2(ctx);
71778 goto skip_varmap;
71779 }
71780 varmap = duk_require_hobject(ctx, -1);
71781 DUK_ASSERT(varmap != NULL);
71782
71783 DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
71784
71785 /* [... env callee varmap] */
71786
71787 DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
71788
71789 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
71790 key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
71791 DUK_ASSERT(key != NULL); /* assume keys are compacted */
71792
71793 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
71794
71795 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
71796 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* assume value is a number */
71797 regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
71798 DUK_ASSERT_DISABLE(regnum >= 0); /* unsigned */
71799 DUK_ASSERT(regnum < ((duk_hcompiledfunction *) func)->nregs); /* regnum is sane */
71800 DUK_ASSERT(thr->valstack + regbase + regnum >= thr->valstack);
71801 DUK_ASSERT(thr->valstack + regbase + regnum < thr->valstack_top);
71802
71803 /* XXX: slightly awkward */
71804 duk_push_hstring(ctx, key);
71805 duk_push_tval(ctx, thr->valstack + regbase + regnum);
71806 DUK_DDD(DUK_DDDPRINT("closing identifier '%s' -> reg %ld, value %!T",
71807 (const char *) duk_require_string(ctx, -2),
71808 (long) regnum,
71809 (duk_tval *) duk_get_tval(ctx, -1)));
71810
71811 /* [... env callee varmap key val] */
71812
71813 /* if property already exists, overwrites silently */
71814 duk_xdef_prop(ctx, -5, DUK_PROPDESC_FLAGS_WE); /* writable but not deletable */
71815 }
71816
71817 duk_pop_2(ctx);
71818
71819 /* [... env] */
71820 }
71821
71822 skip_varmap:
71823
71824 /* [... env] */
71825
71829
71830 duk_pop(ctx);
71831
71833
71834 DUK_DDD(DUK_DDDPRINT("environment record after being closed: %!O",
71835 (duk_heaphdr *) env));
71836}
71837
71838/*
71839 * GETIDREF: a GetIdentifierReference-like helper.
71840 *
71841 * Provides a parent traversing lookup and a single level lookup
71842 * (for HasBinding).
71843 *
71844 * Instead of returning the value, returns a bunch of values allowing
71845 * the caller to read, write, or delete the binding. Value pointers
71846 * are duk_tval pointers which can be mutated directly as long as
71847 * refcounts are properly updated. Note that any operation which may
71848 * reallocate valstacks or compact objects may invalidate the returned
71849 * duk_tval (but not object) pointers, so caller must be very careful.
71850 *
71851 * If starting environment record 'env' is given, 'act' is ignored.
71852 * However, if 'env' is NULL, the caller may identify, in 'act', an
71853 * activation which hasn't had its declarative environment initialized
71854 * yet. The activation registers are then looked up, and its parent
71855 * traversed normally.
71856 *
71857 * The 'out' structure values are only valid if the function returns
71858 * success (non-zero).
71859 */
71860
71861/* lookup name from an open declarative record's registers */
71865 duk_hobject *env,
71866 duk__id_lookup_result *out) {
71867 duk_hthread *env_thr;
71868 duk_hobject *env_func;
71869 duk_size_t env_regbase;
71870 duk_hobject *varmap;
71871 duk_tval *tv;
71872 duk_size_t reg_rel;
71873 duk_size_t idx;
71874
71875 DUK_ASSERT(thr != NULL);
71876 DUK_ASSERT(name != NULL);
71877 DUK_ASSERT(env != NULL);
71878 DUK_ASSERT(out != NULL);
71879
71881
71883 if (!tv) {
71884 /* env is closed, should be missing _Callee, _Thread, _Regbase */
71888 return 0;
71889 }
71890
71894 env_func = DUK_TVAL_GET_OBJECT(tv);
71895 DUK_ASSERT(env_func != NULL);
71896
71898 if (!tv) {
71899 return 0;
71900 }
71902 varmap = DUK_TVAL_GET_OBJECT(tv);
71903 DUK_ASSERT(varmap != NULL);
71904
71906 if (!tv) {
71907 return 0;
71908 }
71910 reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
71911 DUK_ASSERT_DISABLE(reg_rel >= 0); /* unsigned */
71912 DUK_ASSERT(reg_rel < ((duk_hcompiledfunction *) env_func)->nregs);
71913
71915 DUK_ASSERT(tv != NULL);
71919 env_thr = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
71920 DUK_ASSERT(env_thr != NULL);
71921
71922 /* Note: env_thr != thr is quite possible and normal, so careful
71923 * with what thread is used for valstack lookup.
71924 */
71925
71927 DUK_ASSERT(tv != NULL);
71929 env_regbase = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
71930
71931 idx = env_regbase + reg_rel;
71932 tv = env_thr->valstack + idx;
71933 DUK_ASSERT(tv >= env_thr->valstack && tv < env_thr->valstack_end); /* XXX: more accurate? */
71934
71935 out->value = tv;
71936 out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
71937 out->this_binding = NULL; /* implicit this value always undefined for
71938 * declarative environment records.
71939 */
71940 out->env = env;
71941 out->holder = NULL;
71942
71943 return 1;
71944}
71945
71946/* lookup name from current activation record's functions' registers */
71950 duk_activation *act,
71951 duk__id_lookup_result *out) {
71952 duk_tval *tv;
71953 duk_hobject *func;
71954 duk_hobject *varmap;
71955 duk_size_t reg_rel;
71956 duk_size_t idx;
71957
71958 DUK_ASSERT(thr != NULL);
71959 DUK_ASSERT(name != NULL);
71960 DUK_ASSERT(act != NULL);
71961 DUK_ASSERT(out != NULL);
71962
71963 func = DUK_ACT_GET_FUNC(act);
71964 DUK_ASSERT(func != NULL);
71966
71968 return 0;
71969 }
71970
71972 if (!tv) {
71973 return 0;
71974 }
71976 varmap = DUK_TVAL_GET_OBJECT(tv);
71977 DUK_ASSERT(varmap != NULL);
71978
71980 if (!tv) {
71981 return 0;
71982 }
71984 reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
71985 DUK_ASSERT_DISABLE(reg_rel >= 0);
71986 DUK_ASSERT(reg_rel < ((duk_hcompiledfunction *) func)->nregs);
71988 idx = act->idx_bottom + reg_rel;
71989 DUK_ASSERT(idx >= act->idx_bottom);
71990 tv = thr->valstack + idx;
71991
71992 out->value = tv;
71993 out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
71994 out->this_binding = NULL; /* implicit this value always undefined for
71995 * declarative environment records.
71996 */
71997 out->env = NULL;
71998 out->holder = NULL;
71999
72000 return 1;
72001}
72002
72005 duk_hobject *env,
72007 duk_activation *act,
72008 duk_bool_t parents,
72009 duk__id_lookup_result *out) {
72010 duk_tval *tv;
72011 duk_tval *tv_target;
72012 duk_tval tv_name;
72013 duk_uint_t sanity;
72014
72015 DUK_ASSERT(thr != NULL);
72016 DUK_ASSERT(env != NULL || act != NULL);
72017 DUK_ASSERT(name != NULL);
72018 DUK_ASSERT(out != NULL);
72019
72020 DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
72022
72023 /*
72024 * Conceptually, we look for the identifier binding by starting from
72025 * 'env' and following to chain of environment records (represented
72026 * by the prototype chain).
72027 *
72028 * If 'env' is NULL, the current activation does not yet have an
72029 * allocated declarative environment record; this should be treated
72030 * exactly as if the environment record existed but had no bindings
72031 * other than register bindings.
72032 *
72033 * Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
72034 * the environment will always be initialized immediately; hence
72035 * a NULL 'env' should only happen with the flag set. This is the
72036 * case for: (1) function calls, and (2) strict, direct eval calls.
72037 */
72038
72039 if (env == NULL && act != NULL) {
72040 duk_hobject *func;
72041
72042 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
72043 "delayed env case, look up activation regs first"));
72044
72045 /*
72046 * Try registers
72047 */
72048
72049 if (duk__getid_activation_regs(thr, name, act, out)) {
72050 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72051 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72052 "(found from register bindings when env=NULL)",
72053 (duk_heaphdr *) name, (duk_tval *) out->value,
72054 (long) out->attrs, (duk_tval *) out->this_binding,
72055 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72056 return 1;
72057 }
72058
72059 DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
72060
72061 /*
72062 * Not found in registers, proceed to the parent record.
72063 * Here we need to determine what the parent would be,
72064 * if 'env' was not NULL (i.e. same logic as when initializing
72065 * the record).
72066 *
72067 * Note that environment initialization is only deferred when
72068 * DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
72069 * - Function code
72070 * - Strict eval code
72071 *
72072 * We only need to check _Lexenv here; _Varenv exists only if it
72073 * differs from _Lexenv (and thus _Lexenv will also be present).
72074 */
72075
72076 if (!parents) {
72077 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
72078 "(not found from register bindings when env=NULL)"));
72079 goto fail_not_found;
72080 }
72081
72082 func = DUK_ACT_GET_FUNC(act);
72083 DUK_ASSERT(func != NULL);
72085
72087 if (tv) {
72089 env = DUK_TVAL_GET_OBJECT(tv);
72090 } else {
72092 env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
72093 }
72094
72095 DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
72096 (duk_heaphdr *) env));
72097 }
72098
72099 /*
72100 * Prototype walking starting from 'env'.
72101 *
72102 * ('act' is not needed anywhere here.)
72103 */
72104
72106 while (env != NULL) {
72107 duk_small_int_t cl;
72108 duk_int_t attrs;
72109
72110 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
72111 (duk_heaphdr *) name,
72112 (void *) env,
72113 (duk_heaphdr *) env));
72114
72115 DUK_ASSERT(env != NULL);
72118
72121 if (cl == DUK_HOBJECT_CLASS_DECENV) {
72122 /*
72123 * Declarative environment record.
72124 *
72125 * Identifiers can never be stored in ancestors and are
72126 * always plain values, so we can use an internal helper
72127 * and access the value directly with an duk_tval ptr.
72128 *
72129 * A closed environment is only indicated by it missing
72130 * the "book-keeping" properties required for accessing
72131 * register-bound variables.
72132 */
72133
72135 /* already closed */
72136 goto skip_regs;
72137 }
72138
72139 if (duk__getid_open_decl_env_regs(thr, name, env, out)) {
72140 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72141 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72142 "(declarative environment record, scope open, found in regs)",
72143 (duk_heaphdr *) name, (duk_tval *) out->value,
72144 (long) out->attrs, (duk_tval *) out->this_binding,
72145 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72146 return 1;
72147 }
72148 skip_regs:
72149
72151 if (tv) {
72152 out->value = tv;
72153 out->attrs = attrs;
72154 out->this_binding = NULL; /* implicit this value always undefined for
72155 * declarative environment records.
72156 */
72157 out->env = env;
72158 out->holder = env;
72159
72160 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72161 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72162 "(declarative environment record, found in properties)",
72163 (duk_heaphdr *) name, (duk_tval *) out->value,
72164 (long) out->attrs, (duk_tval *) out->this_binding,
72165 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72166 return 1;
72167 }
72168 } else {
72169 /*
72170 * Object environment record.
72171 *
72172 * Binding (target) object is an external, uncontrolled object.
72173 * Identifier may be bound in an ancestor property, and may be
72174 * an accessor. Target can also be a Proxy which we must support
72175 * here.
72176 */
72177
72178 /* XXX: we could save space by using _Target OR _This. If _Target, assume
72179 * this binding is undefined. If _This, assumes this binding is _This, and
72180 * target is also _This. One property would then be enough.
72181 */
72182
72183 duk_hobject *target;
72184 duk_bool_t found;
72185
72187
72189 DUK_ASSERT(tv_target != NULL);
72190 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
72191 target = DUK_TVAL_GET_OBJECT(tv_target);
72192 DUK_ASSERT(target != NULL);
72193
72194 /* Target may be a Proxy or property may be an accessor, so we must
72195 * use an actual, Proxy-aware hasprop check here.
72196 *
72197 * out->holder is NOT set to the actual duk_hobject where the
72198 * property is found, but rather the object binding target object.
72199 */
72200
72201 if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(target)) {
72202 DUK_ASSERT(name != NULL);
72203 DUK_TVAL_SET_STRING(&tv_name, name);
72204
72205 found = duk_hobject_hasprop(thr, tv_target, &tv_name);
72206 } else {
72207 /* XXX: duk_hobject_hasprop() would be correct for
72208 * non-Proxy objects too, but it is about ~20-25%
72209 * slower at present so separate code paths for
72210 * Proxy and non-Proxy now.
72211 */
72212 found = duk_hobject_hasprop_raw(thr, target, name);
72213 }
72214
72215 if (found) {
72216 out->value = NULL; /* can't get value, may be accessor */
72217 out->attrs = 0; /* irrelevant when out->value == NULL */
72219 out->this_binding = tv; /* may be NULL */
72220 out->env = env;
72221 out->holder = target;
72222
72223 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72224 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72225 "(object environment record)",
72226 (duk_heaphdr *) name, (duk_tval *) out->value,
72227 (long) out->attrs, (duk_tval *) out->this_binding,
72228 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72229 return 1;
72230 }
72231 }
72232
72233 if (!parents) {
72234 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
72235 "(not found from first traversed env)"));
72236 goto fail_not_found;
72237 }
72238
72239 if (sanity-- == 0) {
72241 }
72242 env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
72243 };
72244
72245 /*
72246 * Not found (even in global object)
72247 */
72248
72249 fail_not_found:
72250 return 0;
72251}
72252
72253/*
72254 * HASVAR: check identifier binding from a given environment record
72255 * without traversing its parents.
72256 *
72257 * This primitive is not exposed to user code as such, but is used
72258 * internally for e.g. declaration binding instantiation.
72259 *
72260 * See E5 Sections:
72261 * 10.2.1.1.1 HasBinding(N)
72262 * 10.2.1.2.1 HasBinding(N)
72263 *
72264 * Note: strictness has no bearing on this check. Hence we don't take
72265 * a 'strict' parameter.
72266 */
72267
72268#if 0 /*unused*/
72270duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
72271 duk_hobject *env,
72272 duk_hstring *name) {
72274 duk_bool_t parents;
72275
72276 DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
72277 "(env -> %!dO)",
72278 (void *) thr, (void *) env, (duk_heaphdr *) name,
72279 (duk_heaphdr *) env));
72280
72281 DUK_ASSERT(thr != NULL);
72282 DUK_ASSERT(env != NULL);
72283 DUK_ASSERT(name != NULL);
72284
72287
72290
72291 /* lookup results is ignored */
72292 parents = 0;
72293 return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
72294}
72295#endif
72296
72297/*
72298 * GETVAR
72299 *
72300 * See E5 Sections:
72301 * 11.1.2 Identifier Reference
72302 * 10.3.1 Identifier Resolution
72303 * 11.13.1 Simple Assignment [example of where the Reference is GetValue'd]
72304 * 8.7.1 GetValue (V)
72305 * 8.12.1 [[GetOwnProperty]] (P)
72306 * 8.12.2 [[GetProperty]] (P)
72307 * 8.12.3 [[Get]] (P)
72308 *
72309 * If 'throw' is true, always leaves two values on top of stack: [val this].
72310 *
72311 * If 'throw' is false, returns 0 if identifier cannot be resolved, and the
72312 * stack will be unaffected in this case. If identifier is resolved, returns
72313 * 1 and leaves [val this] on top of stack.
72314 *
72315 * Note: the 'strict' flag of a reference returned by GetIdentifierReference
72316 * is ignored by GetValue. Hence we don't take a 'strict' parameter.
72317 *
72318 * The 'throw' flag is needed for implementing 'typeof' for an unreferenced
72319 * identifier. An unreference identifier in other contexts generates a
72320 * ReferenceError.
72321 */
72322
72325 duk_hobject *env,
72326 duk_activation *act,
72328 duk_bool_t throw_flag) {
72329 duk_context *ctx = (duk_context *) thr;
72331 duk_tval tv_tmp_obj;
72332 duk_tval tv_tmp_key;
72333 duk_bool_t parents;
72334
72335 DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
72336 "(env -> %!dO)",
72337 (void *) thr, (void *) env, (void *) act,
72338 (duk_heaphdr *) name, (duk_heaphdr *) env));
72339
72340 DUK_ASSERT(thr != NULL);
72341 DUK_ASSERT(name != NULL);
72342 /* env and act may be NULL */
72343
72346
72347 parents = 1; /* follow parent chain */
72348 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72349 if (ref.value) {
72350 DUK_ASSERT(ref.this_binding == NULL); /* always for register bindings */
72351 duk_push_tval(ctx, ref.value);
72352 duk_push_undefined(ctx);
72353 } else {
72354 DUK_ASSERT(ref.holder != NULL);
72355
72356 /* Note: getprop may invoke any getter and invalidate any
72357 * duk_tval pointers, so this must be done first.
72358 */
72359
72360 if (ref.this_binding) {
72361 duk_push_tval(ctx, ref.this_binding);
72362 } else {
72363 duk_push_undefined(ctx);
72364 }
72365
72366 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
72367 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72368 (void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key); /* [this value] */
72369
72370 /* ref.value, ref.this.binding invalidated here by getprop call */
72372 duk_insert(ctx, -2); /* [this value] -> [value this] */
72373 }
72374
72375 return 1;
72376 } else {
72377 if (throw_flag) {
72379 "identifier '%s' undefined",
72380 (const char *) DUK_HSTRING_GET_DATA(name));
72381 }
72382
72383 return 0;
72384 }
72385}
72386
72389 duk_hobject *env,
72391 duk_bool_t throw_flag) {
72392 return duk__getvar_helper(thr, env, NULL, name, throw_flag);
72393}
72394
72397 duk_activation *act,
72399 duk_bool_t throw_flag) {
72400 DUK_ASSERT(act != NULL);
72401 return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
72402}
72404/*
72405 * PUTVAR
72406 *
72407 * See E5 Sections:
72408 * 11.1.2 Identifier Reference
72409 * 10.3.1 Identifier Resolution
72410 * 11.13.1 Simple Assignment [example of where the Reference is PutValue'd]
72411 * 8.7.2 PutValue (V,W) [see especially step 3.b, undefined -> automatic global in non-strict mode]
72412 * 8.12.4 [[CanPut]] (P)
72413 * 8.12.5 [[Put]] (P)
72414 *
72415 * Note: may invalidate any valstack (or object) duk_tval pointers because
72416 * putting a value may reallocate any object or any valstack. Caller beware.
72417 */
72418
72421 duk_hobject *env,
72422 duk_activation *act,
72424 duk_tval *val,
72425 duk_bool_t strict) {
72427 duk_tval tv_tmp_obj;
72428 duk_tval tv_tmp_key;
72429 duk_bool_t parents;
72430
72431 DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
72432 "(env -> %!dO, val -> %!T)",
72433 (void *) thr, (void *) env, (void *) act,
72434 (duk_heaphdr *) name, (void *) val, (long) strict,
72435 (duk_heaphdr *) env, (duk_tval *) val));
72436
72437 DUK_ASSERT(thr != NULL);
72438 DUK_ASSERT(name != NULL);
72439 DUK_ASSERT(val != NULL);
72440 /* env and act may be NULL */
72441
72445
72446 /*
72447 * In strict mode E5 protects 'eval' and 'arguments' from being
72448 * assigned to (or even declared anywhere). Attempt to do so
72449 * should result in a compile time SyntaxError. See the internal
72450 * design documentation for details.
72451 *
72452 * Thus, we should never come here, run-time, for strict code,
72453 * and name 'eval' or 'arguments'.
72454 */
72455
72456 DUK_ASSERT(!strict ||
72457 (name != DUK_HTHREAD_STRING_EVAL(thr) &&
72459
72460 /*
72461 * Lookup variable and update in-place if found.
72462 */
72463
72464 parents = 1; /* follow parent chain */
72465
72466 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72467 if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
72468 /* Update duk_tval in-place if pointer provided and the
72469 * property is writable. If the property is not writable
72470 * (immutable binding), use duk_hobject_putprop() which
72471 * will respect mutability.
72472 */
72473 duk_tval *tv_val;
72474
72475 DUK_ASSERT(ref.this_binding == NULL); /* always for register bindings */
72476
72477 tv_val = ref.value;
72478 DUK_ASSERT(tv_val != NULL);
72479 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val); /* side effects */
72480
72481 /* ref.value and ref.this_binding invalidated here */
72482 } else {
72483 DUK_ASSERT(ref.holder != NULL);
72484
72485 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
72486 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72487 (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
72488
72489 /* ref.value and ref.this_binding invalidated here */
72490 }
72491
72492 return;
72493 }
72494
72495 /*
72496 * Not found: write to global object (non-strict) or ReferenceError
72497 * (strict); see E5 Section 8.7.2, step 3.
72498 */
72499
72500 if (strict) {
72501 DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
72502 DUK_ERROR(thr, DUK_ERR_REFERENCE_ERROR, "identifier not defined");
72503 }
72504
72505 DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
72506
72507 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
72508 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72509 (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0); /* 0 = no throw */
72510
72511 /* NB: 'val' may be invalidated here because put_value may realloc valstack,
72512 * caller beware.
72513 */
72514}
72515
72518 duk_hobject *env,
72520 duk_tval *val,
72521 duk_bool_t strict) {
72522 duk__putvar_helper(thr, env, NULL, name, val, strict);
72523}
72524
72527 duk_activation *act,
72529 duk_tval *val,
72530 duk_bool_t strict) {
72531 DUK_ASSERT(act != NULL);
72532 duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
72533}
72534
72535/*
72536 * DELVAR
72537 *
72538 * See E5 Sections:
72539 * 11.4.1 The delete operator
72540 * 10.2.1.1.5 DeleteBinding (N) [declarative environment record]
72541 * 10.2.1.2.5 DeleteBinding (N) [object environment record]
72542 *
72543 * Variable bindings established inside eval() are deletable (configurable),
72544 * other bindings are not, including variables declared in global level.
72545 * Registers are always non-deletable, and the deletion of other bindings
72546 * is controlled by the configurable flag.
72547 *
72548 * For strict mode code, the 'delete' operator should fail with a compile
72549 * time SyntaxError if applied to identifiers. Hence, no strict mode
72550 * run-time deletion of identifiers should ever happen. This function
72551 * should never be called from strict mode code!
72552 */
72553
72556 duk_hobject *env,
72557 duk_activation *act,
72558 duk_hstring *name) {
72560 duk_bool_t parents;
72561
72562 DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
72563 "(env -> %!dO)",
72564 (void *) thr, (void *) env, (void *) act,
72565 (duk_heaphdr *) name, (duk_heaphdr *) env));
72566
72567 DUK_ASSERT(thr != NULL);
72568 DUK_ASSERT(name != NULL);
72569 /* env and act may be NULL */
72570
72572
72573 parents = 1; /* follow parent chain */
72574
72575 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72576 if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
72577 /* Identifier found in registers (always non-deletable)
72578 * or declarative environment record and non-configurable.
72579 */
72580 return 0;
72581 }
72582 DUK_ASSERT(ref.holder != NULL);
72583
72584 return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
72585 }
72586
72587 /*
72588 * Not found (even in global object).
72589 *
72590 * In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
72591 * step 3.b. In strict mode this case is a compile time SyntaxError so
72592 * we should not come here.
72593 */
72595 DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
72596 "(treated as silent success)",
72597 (duk_heaphdr *) name));
72598 return 1;
72599}
72600
72601#if 0 /*unused*/
72603duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
72604 duk_hobject *env,
72605 duk_hstring *name) {
72606 return duk__delvar_helper(thr, env, NULL, name);
72607}
72608#endif
72609
72612 duk_activation *act,
72613 duk_hstring *name) {
72614 DUK_ASSERT(act != NULL);
72615 return duk__delvar_helper(thr, act->lex_env, act, name);
72616}
72617
72618/*
72619 * DECLVAR
72620 *
72621 * See E5 Sections:
72622 * 10.4.3 Entering Function Code
72623 * 10.5 Declaration Binding Instantion
72624 * 12.2 Variable Statement
72625 * 11.1.2 Identifier Reference
72626 * 10.3.1 Identifier Resolution
72627 *
72628 * Variable declaration behavior is mainly discussed in Section 10.5,
72629 * and is not discussed in the execution semantics (Sections 11-13).
72630 *
72631 * Conceptually declarations happen when code (global, eval, function)
72632 * is entered, before any user code is executed. In practice, register-
72633 * bound identifiers are 'declared' automatically (by virtue of being
72634 * allocated to registers with the initial value 'undefined'). Other
72635 * identifiers are declared in the function prologue with this primitive.
72636 *
72637 * Since non-register bindings eventually back to an internal object's
72638 * properties, the 'prop_flags' argument is used to specify binding
72639 * type:
72640 *
72641 * - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
72642 * - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
72643 * - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
72644 * doesn't really matter for internal objects
72645 *
72646 * All bindings are non-deletable mutable bindings except:
72647 *
72648 * - Declarations in eval code (mutable, deletable)
72649 * - 'arguments' binding in strict function code (immutable)
72650 * - Function name binding of a function expression (immutable)
72651 *
72652 * Declarations may go to declarative environment records (always
72653 * so for functions), but may also go to object environment records
72654 * (e.g. global code). The global object environment has special
72655 * behavior when re-declaring a function (but not a variable); see
72656 * E5.1 specification, Section 10.5, step 5.e.
72657 *
72658 * Declarations always go to the 'top-most' environment record, i.e.
72659 * we never check the record chain. It's not an error even if a
72660 * property (even an immutable or non-deletable one) of the same name
72661 * already exists.
72662 *
72663 * If a declared variable already exists, its value needs to be updated
72664 * (if possible). Returns 1 if a PUTVAR needs to be done by the caller;
72665 * otherwise returns 0.
72666 */
72667
72670 duk_hobject *env,
72672 duk_tval *val,
72673 duk_small_int_t prop_flags,
72674 duk_bool_t is_func_decl) {
72675 duk_context *ctx = (duk_context *) thr;
72676 duk_hobject *holder;
72677 duk_bool_t parents;
72679 duk_tval *tv;
72680
72681 DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
72682 "(env -> %!iO)",
72683 (void *) thr, (void *) env, (duk_heaphdr *) name,
72684 (duk_tval *) val, (unsigned long) prop_flags,
72685 (unsigned int) is_func_decl, (duk_heaphdr *) env));
72686
72687 DUK_ASSERT(thr != NULL);
72688 DUK_ASSERT(env != NULL);
72689 DUK_ASSERT(name != NULL);
72690 DUK_ASSERT(val != NULL);
72691
72692 /* Note: in strict mode the compiler should reject explicit
72693 * declaration of 'eval' or 'arguments'. However, internal
72694 * bytecode may declare 'arguments' in the function prologue.
72695 * We don't bother checking (or asserting) for these now.
72696 */
72697
72698 /* Note: val is a stable duk_tval pointer. The caller makes
72699 * a value copy into its stack frame, so 'tv_val' is not subject
72700 * to side effects here.
72701 */
72702
72703 /*
72704 * Check whether already declared.
72705 *
72706 * We need to check whether the binding exists in the environment
72707 * without walking its parents. However, we still need to check
72708 * register-bound identifiers and the prototype chain of an object
72709 * environment target object.
72710 */
72711
72712 parents = 0; /* just check 'env' */
72713 if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
72714 duk_int_t e_idx;
72715 duk_int_t h_idx;
72716 duk_small_int_t flags;
72717
72718 /*
72719 * Variable already declared, ignore re-declaration.
72720 * The only exception is the updated behavior of E5.1 for
72721 * global function declarations, E5.1 Section 10.5, step 5.e.
72722 * This behavior does not apply to global variable declarations.
72723 */
72724
72725 if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
72726 DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
72727 return 1; /* 1 -> needs a PUTVAR */
72728 }
72729
72730 /*
72731 * Special behavior in E5.1.
72732 *
72733 * Note that even though parents == 0, the conflicting property
72734 * may be an inherited property (currently our global object's
72735 * prototype is Object.prototype). Step 5.e first operates on
72736 * the existing property (which is potentially in an ancestor)
72737 * and then defines a new property in the global object (and
72738 * never modifies the ancestor).
72739 *
72740 * Also note that this logic would become even more complicated
72741 * if the conflicting property might be a virtual one. Object
72742 * prototype has no virtual properties, though.
72743 *
72744 * XXX: this is now very awkward, rework.
72745 */
72746
72747 DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
72748 "updated E5.1 processing"));
72749
72750 DUK_ASSERT(ref.holder != NULL);
72751 holder = ref.holder;
72752
72753 /* holder will be set to the target object, not the actual object
72754 * where the property was found (see duk__get_identifier_reference()).
72755 */
72757 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder)); /* global object doesn't have array part */
72758
72759 /* XXX: use a helper for prototype traversal; no loop check here */
72760 /* must be found: was found earlier, and cannot be inherited */
72761 for (;;) {
72762 DUK_ASSERT(holder != NULL);
72763 duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx);
72764 if (e_idx >= 0) {
72765 break;
72766 }
72767 /* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
72768 * asserted above.
72769 */
72770 holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
72771 }
72772 DUK_ASSERT(holder != NULL);
72773 DUK_ASSERT(e_idx >= 0);
72774 /* SCANBUILD: scan-build produces a NULL pointer dereference warning
72775 * below; it never actually triggers because holder is actually never
72776 * NULL.
72777 */
72778
72779 /* ref.holder is global object, holder is the object with the
72780 * conflicting property.
72781 */
72782
72783 flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
72784 if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
72785 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
72786 DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
72787 "accessor -> reject"));
72788 goto fail_existing_attributes;
72789 }
72790 if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
72791 (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
72792 DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
72793 "plain property which is not writable and "
72794 "enumerable -> reject"));
72795 goto fail_existing_attributes;
72796 }
72797
72798 DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
72799 "is plain, enumerable, and writable -> "
72800 "allow redeclaration"));
72801 }
72802
72803 if (holder == ref.holder) {
72804 /* XXX: if duk_hobject_define_property_internal() was updated
72805 * to handle a pre-existing accessor property, this would be
72806 * a simple call (like for the ancestor case).
72807 */
72808 DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
72809
72810 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
72811 duk_hobject *tmp;
72812
72813 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
72814 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
72816 DUK_UNREF(tmp);
72817 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
72818 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
72820 DUK_UNREF(tmp);
72821 } else {
72822 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
72824 }
72825
72826 /* Here val would be potentially invalid if we didn't make
72827 * a value copy at the caller.
72828 */
72829
72830 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
72831 DUK_TVAL_SET_TVAL(tv, val);
72832 DUK_TVAL_INCREF(thr, tv);
72833 DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
72834
72835 DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
72836 "value -> %!T, prop_flags=0x%08lx",
72837 (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
72838 (unsigned long) prop_flags));
72839 } else {
72840 DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
72841
72843 duk_push_tval(ctx, val);
72844 duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
72845 }
72846
72847 return 0;
72848 }
72849
72850 /*
72851 * Not found (in registers or record objects). Declare
72852 * to current variable environment.
72853 */
72854
72855 /*
72856 * Get holder object
72857 */
72858
72859 if (DUK_HOBJECT_IS_DECENV(env)) {
72860 holder = env;
72861 } else {
72863
72865 DUK_ASSERT(tv != NULL);
72867 holder = DUK_TVAL_GET_OBJECT(tv);
72868 DUK_ASSERT(holder != NULL);
72869 }
72870
72871 /*
72872 * Define new property
72873 *
72874 * Note: this may fail if the holder is not extensible.
72875 */
72876
72877 /* XXX: this is awkward as we use an internal method which doesn't handle
72878 * extensibility etc correctly. Basically we'd want to do a [[DefineOwnProperty]]
72879 * or Object.defineProperty() here.
72880 */
72881
72882 if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
72883 goto fail_not_extensible;
72885
72886 duk_push_hobject(ctx, holder);
72887 duk_push_hstring(ctx, name);
72888 duk_push_tval(ctx, val);
72889 duk_xdef_prop(ctx, -3, prop_flags); /* [holder name val] -> [holder] */
72890 duk_pop(ctx);
72891
72892 return 0;
72893
72894 fail_existing_attributes:
72895 fail_not_extensible:
72896 DUK_ERROR_TYPE(thr, "declaration failed");
72897 return 0;
72898}
72899
72902 duk_activation *act,
72904 duk_tval *val,
72905 duk_small_int_t prop_flags,
72906 duk_bool_t is_func_decl) {
72907 duk_hobject *env;
72908 duk_tval tv_val_copy;
72909
72910 /*
72911 * Make a value copy of the input val. This ensures that
72912 * side effects cannot invalidate the pointer.
72913 */
72914
72915 DUK_TVAL_SET_TVAL(&tv_val_copy, val);
72916 val = &tv_val_copy;
72917
72918 /*
72919 * Delayed env creation check
72920 */
72921
72922 if (!act->var_env) {
72923 DUK_ASSERT(act->lex_env == NULL);
72925 }
72926 DUK_ASSERT(act->lex_env != NULL);
72927 DUK_ASSERT(act->var_env != NULL);
72928
72929 env = act->var_env;
72930 DUK_ASSERT(env != NULL);
72932
72933 return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
72934}
72935/*
72936 * Lexer for source files, ToNumber() string conversions, RegExp expressions,
72937 * and JSON.
72938 *
72939 * Provides a stream of Ecmascript tokens from an UTF-8/CESU-8 buffer. The
72940 * caller can also rewind the token stream into a certain position which is
72941 * needed by the compiler part for multi-pass scanning. Tokens are
72942 * represented as duk_token structures, and contain line number information.
72943 * Token types are identified with DUK_TOK_* defines.
72944 *
72945 * Characters are decoded into a fixed size lookup window consisting of
72946 * decoded Unicode code points, with window positions past the end of the
72947 * input filled with an invalid codepoint (-1). The tokenizer can thus
72948 * perform multiple character lookups efficiently and with few sanity
72949 * checks (such as access outside the end of the input), which keeps the
72950 * tokenization code small at the cost of performance.
72951 *
72952 * Character data in tokens, such as identifier names and string literals,
72953 * is encoded into CESU-8 format on-the-fly while parsing the token in
72954 * question. The string data is made reachable to garbage collection by
72955 * placing the token-related values in value stack entries allocated for
72956 * this purpose by the caller. The characters exist in Unicode code point
72957 * form only in the fixed size lookup window, which keeps character data
72958 * expansion (of especially ASCII data) low.
72959 *
72960 * Token parsing supports the full range of Unicode characters as described
72961 * in the E5 specification. Parsing has been optimized for ASCII characters
72962 * because ordinary Ecmascript code consists almost entirely of ASCII
72963 * characters. Matching of complex Unicode codepoint sets (such as in the
72964 * IdentifierStart and IdentifierPart productions) is optimized for size,
72965 * and is done using a linear scan of a bit-packed list of ranges. This is
72966 * very slow, but should never be entered unless the source code actually
72967 * contains Unicode characters.
72968 *
72969 * Ecmascript tokenization is partially context sensitive. First,
72970 * additional future reserved words are recognized in strict mode (see E5
72971 * Section 7.6.1.2). Second, a forward slash character ('/') can be
72972 * recognized either as starting a RegExp literal or as a division operator,
72973 * depending on context. The caller must provide necessary context flags
72974 * when requesting a new token.
72975 *
72976 * Future work:
72977 *
72978 * * Make line number tracking optional, as it consumes space.
72979 *
72980 * * Add a feature flag for disabling UTF-8 decoding of input, as most
72981 * source code is ASCII. Because of Unicode escapes written in ASCII,
72982 * this does not allow Unicode support to be removed from e.g.
72983 * duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
72984 * encoding of e.g. string literals.
72985 *
72986 * * Add a feature flag for disabling Unicode compliance of e.g. identifier
72987 * names. This allows for a build more than a kilobyte smaller, because
72988 * Unicode ranges needed by duk_unicode_is_identifier_start() and
72989 * duk_unicode_is_identifier_part() can be dropped. String literals
72990 * should still be allowed to contain escaped Unicode, so this still does
72991 * not allow removal of CESU-8 encoding of e.g. string literals.
72992 *
72993 * * Character lookup tables for codepoints above BMP could be stripped.
72994 *
72995 * * Strictly speaking, E5 specification requires that source code consists
72996 * of 16-bit code units, and if not, must be conceptually converted to
72997 * that format first. The current lexer processes Unicode code points
72998 * and allows characters outside the BMP. These should be converted to
72999 * surrogate pairs while reading the source characters into the window,
73000 * not after tokens have been formed (as is done now). However, the fix
73001 * is not trivial because two characters are decoded from one codepoint.
73003 * * Optimize for speed as well as size. Large if-else ladders are (at
73004 * least potentially) slow.
73005 */
73006
73007/* include removed: duk_internal.h */
73010 * Various defines and file specific helper macros
73012
73013#define DUK__MAX_RE_DECESC_DIGITS 9
73014#define DUK__MAX_RE_QUANT_DIGITS 9 /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
73016/* whether to use macros or helper function depends on call count */
73017#define DUK__ISDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
73018#define DUK__ISHEXDIGIT(x) duk__is_hex_digit((x))
73019#define DUK__ISOCTDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
73020#define DUK__ISDIGIT03(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
73021#define DUK__ISDIGIT47(x) ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
73023/* lexer character window helpers */
73024#define DUK__LOOKUP(lex_ctx,index) ((lex_ctx)->window[(index)].codepoint)
73025#define DUK__ADVANCECHARS(lex_ctx,count) duk__advance_bytes((lex_ctx), (count) * sizeof(duk_lexer_codepoint))
73026#define DUK__ADVANCEBYTES(lex_ctx,count) duk__advance_bytes((lex_ctx), (count))
73027#define DUK__INITBUFFER(lex_ctx) duk__initbuffer((lex_ctx))
73028#define DUK__APPENDBUFFER(lex_ctx,x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
73029
73030/* lookup shorthands (note: assume context variable is named 'lex_ctx') */
73031#define DUK__L0() DUK__LOOKUP(lex_ctx, 0)
73032#define DUK__L1() DUK__LOOKUP(lex_ctx, 1)
73033#define DUK__L2() DUK__LOOKUP(lex_ctx, 2)
73034#define DUK__L3() DUK__LOOKUP(lex_ctx, 3)
73035#define DUK__L4() DUK__LOOKUP(lex_ctx, 4)
73036#define DUK__L5() DUK__LOOKUP(lex_ctx, 5)
73037
73038/* packed advance/token number macro used by multiple functions */
73039#define DUK__ADVTOK(advbytes,tok) ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
73040
73041/*
73042 * Advance lookup window by N characters, filling in new characters as
73043 * necessary. After returning caller is guaranteed a character window of
73044 * at least DUK_LEXER_WINDOW_SIZE characters.
73045 *
73046 * The main function duk__advance_bytes() is called at least once per every
73047 * token so it has a major lexer/compiler performance impact. There are two
73048 * variants for the main duk__advance_bytes() algorithm: a sliding window
73049 * approach which is slightly faster at the cost of larger code footprint,
73050 * and a simple copying one.
73051 *
73052 * Decoding directly from the source string would be another lexing option.
73053 * But the lookup window based approach has the advantage of hiding the
73054 * source string and its encoding effectively which gives more flexibility
73055 * going forward to e.g. support chunked streaming of source from flash.
73056 *
73057 * Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
73058 * U+10FFFF, causing an error if the input is unparseable. Leniency means:
73059 *
73060 * * Unicode code point validation is intentionally not performed,
73061 * except to check that the codepoint does not exceed 0x10ffff.
73062 *
73063 * * In particular, surrogate pairs are allowed and not combined, which
73064 * allows source files to represent all SourceCharacters with CESU-8.
73065 * Broken surrogate pairs are allowed, as Ecmascript does not mandate
73066 * their validation.
73067 *
73068 * * Allow non-shortest UTF-8 encodings.
73069 *
73070 * Leniency here causes few security concerns because all character data is
73071 * decoded into Unicode codepoints before lexer processing, and is then
73072 * re-encoded into CESU-8. The source can be parsed as strict UTF-8 with
73073 * a compiler option. However, Ecmascript source characters include -all-
73074 * 16-bit unsigned integer codepoints, so leniency seems to be appropriate.
73075 *
73076 * Note that codepoints above the BMP are not strictly SourceCharacters,
73077 * but the lexer still accepts them as such. Before ending up in a string
73078 * or an identifier name, codepoints above BMP are converted into surrogate
73079 * pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
73080 * expected by Ecmascript.
73081 *
73082 * An alternative approach to dealing with invalid or partial sequences
73083 * would be to skip them and replace them with e.g. the Unicode replacement
73084 * character U+FFFD. This has limited utility because a replacement character
73085 * will most likely cause a parse error, unless it occurs inside a string.
73086 * Further, Ecmascript source is typically pure ASCII.
73087 *
73088 * See:
73089 *
73090 * http://en.wikipedia.org/wiki/UTF-8
73091 * http://en.wikipedia.org/wiki/CESU-8
73092 * http://tools.ietf.org/html/rfc3629
73093 * http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
73095 * Future work:
73096 *
73097 * * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
73098 * in strict UTF-8 mode.
73099 *
73100 * * Size optimize. An attempt to use a 16-byte lookup table for the first
73101 * byte resulted in a code increase though.
73102 *
73103 * * Is checking against maximum 0x10ffff really useful? 4-byte encoding
73104 * imposes a certain limit anyway.
73105 *
73106 * * Support chunked streaming of source code. Can be implemented either
73107 * by streaming chunks of bytes or chunks of codepoints.
73108 */
73109
73110#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
73111DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
73112 duk_lexer_codepoint *cp, *cp_end;
73114 duk_small_uint_t contlen;
73115 const duk_uint8_t *p, *p_end;
73116#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73117 duk_ucodepoint_t mincp;
73118#endif
73119 duk_int_t input_line;
73120
73121 /* Use temporaries and update lex_ctx only when finished. */
73122 input_line = lex_ctx->input_line;
73123 p = lex_ctx->input + lex_ctx->input_offset;
73124 p_end = lex_ctx->input + lex_ctx->input_length;
73125
73126 cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
73127 cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
73128
73129 for (; cp != cp_end; cp++) {
73130 cp->offset = (duk_size_t) (p - lex_ctx->input);
73131 cp->line = input_line;
73132
73133 /* XXX: potential issue with signed pointers, p_end < p. */
73134 if (DUK_UNLIKELY(p >= p_end)) {
73135 /* If input_offset were assigned a negative value, it would
73136 * result in a large positive value. Most likely it would be
73137 * larger than input_length and be caught here. In any case
73138 * no memory unsafe behavior would happen.
73139 */
73140 cp->codepoint = -1;
73141 continue;
73142 }
73143
73144 x = (duk_ucodepoint_t) (*p++);
73145
73146 /* Fast path. */
73147
73148 if (DUK_LIKELY(x < 0x80UL)) {
73149 DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
73150 if (DUK_UNLIKELY(x <= 0x000dUL)) {
73151 if ((x == 0x000aUL) ||
73152 ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
73153 /* lookup for 0x000a above assumes shortest encoding now */
73154
73155 /* E5 Section 7.3, treat the following as newlines:
73156 * LF
73157 * CR [not followed by LF]
73158 * LS
73159 * PS
73160 *
73161 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
73162 * the line number.
73163 */
73164 input_line++;
73165 }
73166 }
73167
73168 cp->codepoint = (duk_codepoint_t) x;
73169 continue;
73170 }
73171
73172 /* Slow path. */
73173
73174 if (x < 0xc0UL) {
73175 /* 10xx xxxx -> invalid */
73176 goto error_encoding;
73177 } else if (x < 0xe0UL) {
73178 /* 110x xxxx 10xx xxxx */
73179 contlen = 1;
73180#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73181 mincp = 0x80UL;
73182#endif
73183 x = x & 0x1fUL;
73184 } else if (x < 0xf0UL) {
73185 /* 1110 xxxx 10xx xxxx 10xx xxxx */
73186 contlen = 2;
73187#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73188 mincp = 0x800UL;
73189#endif
73190 x = x & 0x0fUL;
73191 } else if (x < 0xf8UL) {
73192 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
73193 contlen = 3;
73194#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73195 mincp = 0x10000UL;
73196#endif
73197 x = x & 0x07UL;
73198 } else {
73199 /* no point in supporting encodings of 5 or more bytes */
73200 goto error_encoding;
73201 }
73202
73203 DUK_ASSERT(p_end >= p);
73204 if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
73205 goto error_clipped;
73206 }
73207
73208 while (contlen > 0) {
73210 y = *p++;
73211 if ((y & 0xc0U) != 0x80U) {
73212 /* check that byte has the form 10xx xxxx */
73213 goto error_encoding;
73214 }
73215 x = x << 6;
73216 x += y & 0x3fUL;
73217 contlen--;
73218 }
73219
73220 /* check final character validity */
73221
73222 if (x > 0x10ffffUL) {
73223 goto error_encoding;
73224 }
73225#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73226 if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
73227 goto error_encoding;
73228 }
73229#endif
73230
73231 DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
73232 if ((x == 0x2028UL) || (x == 0x2029UL)) {
73233 input_line++;
73235
73236 cp->codepoint = (duk_codepoint_t) x;
73237 }
73238
73239 lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
73240 lex_ctx->input_line = input_line;
73241 return;
73242
73243 error_clipped: /* clipped codepoint */
73244 error_encoding: /* invalid codepoint encoding or codepoint */
73245 lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
73246 lex_ctx->input_line = input_line;
73247
73248 DUK_ERROR_SYNTAX(lex_ctx->thr, "utf-8 decode failed");
73249}
73250
73251DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
73252 duk_small_uint_t used_bytes, avail_bytes;
73253
73254 DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
73256 DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
73257 DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
73258 DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
73259
73260 /* Zero 'count' is also allowed to make call sites easier.
73261 * Arithmetic in bytes generates better code in GCC.
73263
73264 lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes); /* avoid multiply */
73265 used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
73266 avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
73267 if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
73268 /* Not enough data to provide a full window, so "scroll" window to
73269 * start of buffer and fill up the rest.
73270 */
73271 DUK_MEMMOVE((void *) lex_ctx->buffer,
73272 (const void *) lex_ctx->window,
73273 (size_t) avail_bytes);
73274 lex_ctx->window = lex_ctx->buffer;
73275 duk__fill_lexer_buffer(lex_ctx, avail_bytes);
73276 }
73277}
73278
73280 lex_ctx->window = lex_ctx->buffer;
73281 duk__fill_lexer_buffer(lex_ctx, 0);
73282}
73283#else /* DUK_USE_LEXER_SLIDING_WINDOW */
73284DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
73286 duk_small_uint_t len;
73288 const duk_uint8_t *p;
73289#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73290 duk_ucodepoint_t mincp;
73291#endif
73292 duk_size_t input_offset;
73293
73294 input_offset = lex_ctx->input_offset;
73295 if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
73296 /* If input_offset were assigned a negative value, it would
73297 * result in a large positive value. Most likely it would be
73298 * larger than input_length and be caught here. In any case
73299 * no memory unsafe behavior would happen.
73300 */
73301 return -1;
73302 }
73303
73304 p = lex_ctx->input + input_offset;
73305 x = (duk_ucodepoint_t) (*p);
73306
73307 if (DUK_LIKELY(x < 0x80UL)) {
73308 /* 0xxx xxxx -> fast path */
73309
73310 /* input offset tracking */
73311 lex_ctx->input_offset++;
73312
73313 DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
73314 if (DUK_UNLIKELY(x <= 0x000dUL)) {
73315 if ((x == 0x000aUL) ||
73316 ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
73317 lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
73318 /* lookup for 0x000a above assumes shortest encoding now */
73319
73320 /* E5 Section 7.3, treat the following as newlines:
73321 * LF
73322 * CR [not followed by LF]
73323 * LS
73324 * PS
73325 *
73326 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
73327 * the line number.
73328 */
73329 lex_ctx->input_line++;
73330 }
73331 }
73332
73333 return (duk_codepoint_t) x;
73334 }
73335
73336 /* Slow path. */
73337
73338 if (x < 0xc0UL) {
73339 /* 10xx xxxx -> invalid */
73340 goto error_encoding;
73341 } else if (x < 0xe0UL) {
73342 /* 110x xxxx 10xx xxxx */
73343 len = 2;
73344#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73345 mincp = 0x80UL;
73346#endif
73347 x = x & 0x1fUL;
73348 } else if (x < 0xf0UL) {
73349 /* 1110 xxxx 10xx xxxx 10xx xxxx */
73350 len = 3;
73351#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73352 mincp = 0x800UL;
73353#endif
73354 x = x & 0x0fUL;
73355 } else if (x < 0xf8UL) {
73356 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
73357 len = 4;
73358#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73359 mincp = 0x10000UL;
73360#endif
73361 x = x & 0x07UL;
73362 } else {
73363 /* no point in supporting encodings of 5 or more bytes */
73364 goto error_encoding;
73365 }
73366
73367 DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
73368 if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
73369 goto error_clipped;
73370 }
73371
73372 p++;
73373 for (i = 1; i < len; i++) {
73375 y = *p++;
73376 if ((y & 0xc0U) != 0x80U) {
73377 /* check that byte has the form 10xx xxxx */
73378 goto error_encoding;
73379 }
73380 x = x << 6;
73381 x += y & 0x3fUL;
73382 }
73383
73384 /* check final character validity */
73385
73386 if (x > 0x10ffffUL) {
73387 goto error_encoding;
73388 }
73389#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73390 if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
73391 goto error_encoding;
73392 }
73393#endif
73394
73395 /* input offset tracking */
73396 lex_ctx->input_offset += len;
73397
73398 /* line tracking */
73399 DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
73400 if ((x == 0x2028UL) || (x == 0x2029UL)) {
73401 lex_ctx->input_line++;
73402 }
73403
73404 return (duk_codepoint_t) x;
73405
73406 error_clipped: /* clipped codepoint */
73407 error_encoding: /* invalid codepoint encoding or codepoint */
73408 DUK_ERROR_SYNTAX(lex_ctx->thr, "utf-8 decode failed");
73409 return 0;
73410}
73411
73412DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
73413 duk_small_uint_t keep_bytes;
73414 duk_lexer_codepoint *cp, *cp_end;
73415
73416 DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
73418
73419 /* Zero 'count' is also allowed to make call sites easier. */
73420
73421 keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
73422 DUK_MEMMOVE((void *) lex_ctx->window,
73423 (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
73424 (size_t) keep_bytes);
73425
73426 cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
73427 cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
73428 for (; cp != cp_end; cp++) {
73429 cp->offset = lex_ctx->input_offset;
73430 cp->line = lex_ctx->input_line;
73431 cp->codepoint = duk__read_char(lex_ctx);
73432 }
73433}
73434
73436 /* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
73437 duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)); /* fill window */
73438}
73439#endif /* DUK_USE_LEXER_SLIDING_WINDOW */
73440
73441/*
73442 * (Re)initialize the temporary byte buffer. May be called extra times
73443 * with little impact.
73444 */
73445
73447 /* Reuse buffer as is unless buffer has grown large. */
73449 /* Keep current size */
73450 } else {
73452 }
73453
73454 DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
73455}
73456
73457/*
73458 * Append a Unicode codepoint to the temporary byte buffer. Performs
73459 * CESU-8 surrogate pair encoding for codepoints above the BMP.
73460 * Existing surrogate pairs are allowed and also encoded into CESU-8.
73461 */
73462
73464 /*
73465 * Since character data is only generated by decoding the source or by
73466 * the compiler itself, we rely on the input codepoints being correct
73467 * and avoid a check here.
73468 *
73469 * Character data can also come here through decoding of Unicode
73470 * escapes ("\udead\ubeef") so all 16-but unsigned values can be
73471 * present, even when the source file itself is strict UTF-8.
73472 */
73473
73474 DUK_ASSERT(x >= 0 && x <= 0x10ffff);
73475
73476 DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
73477}
73478
73479/*
73480 * Intern the temporary byte buffer into a valstack slot
73481 * (in practice, slot1 or slot2).
73482 */
73483
73484DUK_LOCAL void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
73485 duk_context *ctx = (duk_context *) lex_ctx->thr;
73486
73487 DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
73488
73489 DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
73490 duk_replace(ctx, valstack_idx);
73491}
73492
73493/*
73494 * Init lexer context
73495 */
73496
73498 DUK_ASSERT(lex_ctx != NULL);
73499
73500 DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx));
73501#if defined(DUK_USE_EXPLICIT_NULL_INIT)
73502#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
73503 lex_ctx->window = NULL;
73504#endif
73505 lex_ctx->thr = NULL;
73506 lex_ctx->input = NULL;
73507 lex_ctx->buf = NULL;
73508#endif
73509}
73510
73511/*
73512 * Set lexer input position and reinitialize lookup window.
73514
73515/* NB: duk_lexer_getpoint() is a macro only */
73516
73518 DUK_ASSERT_DISABLE(pt->offset >= 0); /* unsigned */
73519 DUK_ASSERT(pt->line >= 1);
73520 lex_ctx->input_offset = pt->offset;
73521 lex_ctx->input_line = pt->line;
73522 duk__init_lexer_window(lex_ctx);
73523}
73524
73525/*
73526 * Lexing helpers
73527 */
73528
73529/* numeric value of a hex digit (also covers octal and decimal digits) */
73533 /* Here 'x' is a Unicode codepoint */
73534 if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
73535 t = duk_hex_dectab[x];
73536 if (DUK_LIKELY(t >= 0)) {
73537 return t;
73538 }
73540
73541 /* Throwing an error this deep makes the error rather vague, but
73542 * saves hundreds of bytes of code.
73543 */
73544 DUK_ERROR_SYNTAX(lex_ctx->thr, "decode error");
73545 return 0;
73546}
73547
73548/* having this as a separate function provided a size benefit */
73550 if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
73551 return (duk_hex_dectab[x] >= 0);
73552 }
73553 return 0;
73554}
73555
73557 /* validation performed by duk__hexval */
73558 return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 4) |
73559 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint));
73560}
73561
73563 /* validation performed by duk__hexval */
73564 return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 12) |
73565 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint) << 8) |
73566 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 2].codepoint) << 4) |
73567 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 3].codepoint));
73568}
73569
73570/*
73571 * Parse Ecmascript source InputElementDiv or InputElementRegExp
73572 * (E5 Section 7), skipping whitespace, comments, and line terminators.
73573 *
73574 * Possible results are:
73575 * (1) a token
73576 * (2) a line terminator (skipped)
73577 * (3) a comment (skipped)
73578 * (4) EOF
73579 *
73580 * White space is automatically skipped from the current position (but
73581 * not after the input element). If input has already ended, returns
73582 * DUK_TOK_EOF indefinitely. If a parse error occurs, uses an DUK_ERROR()
73583 * macro call (and hence a longjmp through current heap longjmp context).
73584 * Comments and line terminator tokens are automatically skipped.
73585 *
73586 * The input element being matched is determined by regexp_mode; if set,
73587 * parses a InputElementRegExp, otherwise a InputElementDiv. The
73588 * difference between these are handling of productions starting with a
73589 * forward slash.
73590 *
73591 * If strict_mode is set, recognizes additional future reserved words
73592 * specific to strict mode, and refuses to parse octal literals.
73593 *
73594 * The matching strategy below is to (currently) use a six character
73595 * lookup window to quickly determine which production is the -longest-
73596 * matching one, and then parse that. The top-level if-else clauses
73597 * match the first character, and the code blocks for each clause
73598 * handle -all- alternatives for that first character. Ecmascript
73599 * specification uses the "longest match wins" semantics, so the order
73600 * of the if-clauses matters.
73601 *
73602 * Misc notes:
73603 *
73604 * * Ecmascript numeric literals do not accept a sign character.
73605 * Consequently e.g. "-1.0" is parsed as two tokens: a negative
73606 * sign and a positive numeric literal. The compiler performs
73607 * the negation during compilation, so this has no adverse impact.
73608 *
73609 * * There is no token for "undefined": it is just a value available
73610 * from the global object (or simply established by doing a reference
73611 * to an undefined value).
73612 *
73613 * * Some contexts want Identifier tokens, which are IdentifierNames
73614 * excluding reserved words, while some contexts want IdentifierNames
73615 * directly. In the latter case e.g. "while" is interpreted as an
73616 * identifier name, not a DUK_TOK_WHILE token. The solution here is
73617 * to provide both token types: DUK_TOK_WHILE goes to 't' while
73618 * DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
73619 * the identifier / keyword name.
73620 *
73621 * * Directive prologue needs to identify string literals such as
73622 * "use strict" and 'use strict', which are sensitive to line
73623 * continuations and escape sequences. For instance, "use\u0020strict"
73624 * is a valid directive but is distinct from "use strict". The solution
73625 * here is to decode escapes while tokenizing, but to keep track of the
73626 * number of escapes. Directive detection can then check that the
73627 * number of escapes is zero.
73628 *
73629 * * Multi-line comments with one or more internal LineTerminator are
73630 * treated like a line terminator to comply with automatic semicolon
73631 * insertion.
73632 */
73633
73636 duk_token *out_token,
73637 duk_bool_t strict_mode,
73638 duk_bool_t regexp_mode) {
73639 duk_codepoint_t x; /* temporary, must be signed and 32-bit to hold Unicode code points */
73640 duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
73641 * init is unnecessary but suppresses "may be used uninitialized" warnings.
73642 */
73643 duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */
73644
73645 if (++lex_ctx->token_count >= lex_ctx->token_limit) {
73646 DUK_ERROR_RANGE(lex_ctx->thr, "token limit");
73647 return; /* unreachable */
73648 }
73649
73650 out_token->t = DUK_TOK_EOF;
73651 out_token->t_nores = -1; /* marker: copy t if not changed */
73652#if 0 /* not necessary to init, disabled for faster parsing */
73653 out_token->num = DUK_DOUBLE_NAN;
73654 out_token->str1 = NULL;
73655 out_token->str2 = NULL;
73656#endif
73657 out_token->num_escapes = 0;
73658 /* out_token->lineterm set by caller */
73659
73660 /* This would be nice, but parsing is faster without resetting the
73661 * value slots. The only side effect is that references to temporary
73662 * string values may linger until lexing is finished; they're then
73663 * freed normally.
73664 */
73665#if 0
73666 duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
73667 duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
73668#endif
73669
73670 /* 'advtok' indicates how much to advance and which token id to assign
73671 * at the end. This shared functionality minimizes code size. All
73672 * code paths are required to set 'advtok' to some value, so no default
73673 * init value is used. Code paths calling DUK_ERROR() never return so
73674 * they don't need to set advtok.
73675 */
73676
73677 /*
73678 * Matching order:
73679 *
73680 * Punctuator first chars, also covers comments, regexps
73681 * LineTerminator
73682 * Identifier or reserved word, also covers null/true/false literals
73683 * NumericLiteral
73684 * StringLiteral
73685 * EOF
73686 *
73687 * The order does not matter as long as the longest match is
73688 * always correctly identified. There are order dependencies
73689 * in the clauses, so it's not trivial to convert to a switch.
73690 */
73691
73692 restart_lineupdate:
73693 out_token->start_line = lex_ctx->window[0].line;
73694
73695 restart:
73696 out_token->start_offset = lex_ctx->window[0].offset;
73697
73698 x = DUK__L0();
73699
73700 switch (x) {
73701 case DUK_ASC_SPACE:
73702 case DUK_ASC_HT: /* fast paths for space and tab */
73703 DUK__ADVANCECHARS(lex_ctx, 1);
73704 goto restart;
73705 case DUK_ASC_LF: /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
73706 DUK__ADVANCECHARS(lex_ctx, 1);
73707 got_lineterm = 1;
73708 goto restart_lineupdate;
73709 case DUK_ASC_SLASH: /* '/' */
73710 if (DUK__L1() == '/') {
73711 /*
73712 * E5 Section 7.4, allow SourceCharacter (which is any 16-bit
73713 * code point).
73714 */
73715
73716 /* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but it unnecessary */
73717 for (;;) {
73718 x = DUK__L0();
73719 if (x < 0 || duk_unicode_is_line_terminator(x)) {
73720 break;
73721 }
73722 DUK__ADVANCECHARS(lex_ctx, 1);
73723 }
73724 goto restart; /* line terminator will be handled on next round */
73725 } else if (DUK__L1() == '*') {
73726 /*
73727 * E5 Section 7.4. If the multi-line comment contains a newline,
73728 * it is treated like a single line terminator for automatic
73729 * semicolon insertion.
73730 */
73731
73732 duk_bool_t last_asterisk = 0;
73733 DUK__ADVANCECHARS(lex_ctx, 2);
73734 for (;;) {
73735 x = DUK__L0();
73736 if (x < 0) {
73737 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof in multiline comment");
73738 }
73739 DUK__ADVANCECHARS(lex_ctx, 1);
73740 if (last_asterisk && x == '/') {
73741 break;
73742 }
73744 got_lineterm = 1;
73745 }
73746 last_asterisk = (x == '*');
73747 }
73748 goto restart_lineupdate;
73749 } else if (regexp_mode) {
73750#if defined(DUK_USE_REGEXP_SUPPORT)
73751 /*
73752 * "/" followed by something in regexp mode. See E5 Section 7.8.5.
73753 *
73754 * RegExp parsing is a bit complex. First, the regexp body is delimited
73755 * by forward slashes, but the body may also contain forward slashes as
73756 * part of an escape sequence or inside a character class (delimited by
73757 * square brackets). A mini state machine is used to implement these.
73758 *
73759 * Further, an early (parse time) error must be thrown if the regexp
73760 * would cause a run-time error when used in the expression new RegExp(...).
73761 * Parsing here simply extracts the (candidate) regexp, and also accepts
73762 * invalid regular expressions (which are delimited properly). The caller
73763 * (compiler) must perform final validation and regexp compilation.
73764 *
73765 * RegExp first char may not be '/' (single line comment) or '*' (multi-
73766 * line comment). These have already been checked above, so there is no
73767 * need below for special handling of the first regexp character as in
73768 * the E5 productions.
73769 *
73770 * About unicode escapes within regexp literals:
73771 *
73772 * E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
73773 * However, Section 6 states that regexps accept the escapes,
73774 * see paragraph starting with "In string literals...".
73775 * The regexp grammar, which sees the decoded regexp literal
73776 * (after lexical parsing) DOES have a \uHHHH unicode escape.
73777 * So, for instance:
73778 *
73779 * /\u1234/
73780 *
73781 * should first be parsed by the lexical grammar as:
73782 *
73783 * '\' 'u' RegularExpressionBackslashSequence
73784 * '1' RegularExpressionNonTerminator
73785 * '2' RegularExpressionNonTerminator
73786 * '3' RegularExpressionNonTerminator
73787 * '4' RegularExpressionNonTerminator
73788 *
73789 * and the escape itself is then parsed by the regexp engine.
73790 * This is the current implementation.
73791 *
73792 * Minor spec inconsistency:
73793 *
73794 * E5 Section 7.8.5 RegularExpressionBackslashSequence is:
73795 *
73796 * \ RegularExpressionNonTerminator
73797 *
73798 * while Section A.1 RegularExpressionBackslashSequence is:
73799 *
73800 * \ NonTerminator
73801 *
73802 * The latter is not normative and a typo.
73803 *
73804 */
73805
73806 /* first, parse regexp body roughly */
73807
73808 duk_small_int_t state = 0; /* 0=base, 1=esc, 2=class, 3=class+esc */
73809
73810 DUK__INITBUFFER(lex_ctx);
73811 for (;;) {
73812 DUK__ADVANCECHARS(lex_ctx, 1); /* skip opening slash on first loop */
73813 x = DUK__L0();
73814 if (x < 0 || duk_unicode_is_line_terminator(x)) {
73815 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in regexp");
73816 }
73817 x = DUK__L0(); /* re-read to avoid spill / fetch */
73818 if (state == 0) {
73819 if (x == '/') {
73820 DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing slash */
73821 break;
73822 } else if (x == '\\') {
73823 state = 1;
73824 } else if (x == '[') {
73825 state = 2;
73826 }
73827 } else if (state == 1) {
73828 state = 0;
73829 } else if (state == 2) {
73830 if (x == ']') {
73831 state = 0;
73832 } else if (x == '\\') {
73833 state = 3;
73834 }
73835 } else { /* state == 3 */
73836 state = 2;
73837 }
73838 DUK__APPENDBUFFER(lex_ctx, x);
73839 }
73840 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
73841 out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
73842
73843 /* second, parse flags */
73844
73845 DUK__INITBUFFER(lex_ctx);
73846 for (;;) {
73847 x = DUK__L0();
73849 break;
73850 }
73851 x = DUK__L0(); /* re-read to avoid spill / fetch */
73852 DUK__APPENDBUFFER(lex_ctx, x);
73853 DUK__ADVANCECHARS(lex_ctx, 1);
73854 }
73855 duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
73856 out_token->str2 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
73857
73858 DUK__INITBUFFER(lex_ctx); /* free some memory */
73859
73860 /* validation of the regexp is caller's responsibility */
73861
73862 advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
73863#else
73864 DUK_ERROR_SYNTAX(lex_ctx->thr, "regexp support disabled");
73865#endif
73866 } else if (DUK__L1() == '=') {
73867 /* "/=" and not in regexp mode */
73868 advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
73869 } else {
73870 /* "/" and not in regexp mode */
73871 advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
73872 }
73873 break;
73874 case DUK_ASC_LCURLY: /* '{' */
73875 advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
73876 break;
73877 case DUK_ASC_RCURLY: /* '}' */
73878 advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
73879 break;
73880 case DUK_ASC_LPAREN: /* '(' */
73881 advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
73882 break;
73883 case DUK_ASC_RPAREN: /* ')' */
73884 advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
73885 break;
73886 case DUK_ASC_LBRACKET: /* '[' */
73887 advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
73888 break;
73889 case DUK_ASC_RBRACKET: /* ']' */
73890 advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
73891 break;
73892 case DUK_ASC_PERIOD: /* '.' */
73893 if (DUK__ISDIGIT(DUK__L1())) {
73894 /* Period followed by a digit can only start DecimalLiteral
73895 * (handled in slow path). We could jump straight into the
73896 * DecimalLiteral handling but should avoid goto to inside
73897 * a block.
73898 */
73899 goto slow_path;
73900 }
73901 advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
73902 break;
73903 case DUK_ASC_SEMICOLON: /* ';' */
73904 advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
73905 break;
73906 case DUK_ASC_COMMA: /* ',' */
73907 advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
73908 break;
73909 case DUK_ASC_LANGLE: /* '<' */
73910 if (DUK__L1() == '<' && DUK__L2() == '=') {
73911 advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
73912 } else if (DUK__L1() == '=') {
73913 advtok = DUK__ADVTOK(2, DUK_TOK_LE);
73914 } else if (DUK__L1() == '<') {
73915 advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
73916 } else {
73917 advtok = DUK__ADVTOK(1, DUK_TOK_LT);
73918 }
73919 break;
73920 case DUK_ASC_RANGLE: /* '>' */
73921 if (DUK__L1() == '>' && DUK__L2() == '>' && DUK__L3() == '=') {
73922 advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
73923 } else if (DUK__L1() == '>' && DUK__L2() == '>') {
73924 advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
73925 } else if (DUK__L1() == '>' && DUK__L2() == '=') {
73926 advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
73927 } else if (DUK__L1() == '=') {
73928 advtok = DUK__ADVTOK(2, DUK_TOK_GE);
73929 } else if (DUK__L1() == '>') {
73930 advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
73931 } else {
73932 advtok = DUK__ADVTOK(1, DUK_TOK_GT);
73933 }
73934 break;
73935 case DUK_ASC_EQUALS: /* '=' */
73936 if (DUK__L1() == '=' && DUK__L2() == '=') {
73937 advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
73938 } else if (DUK__L1() == '=') {
73939 advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
73940 } else {
73941 advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
73942 }
73943 break;
73944 case DUK_ASC_EXCLAMATION: /* '!' */
73945 if (DUK__L1() == '=' && DUK__L2() == '=') {
73946 advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
73947 } else if (DUK__L1() == '=') {
73948 advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
73949 } else {
73950 advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
73951 }
73952 break;
73953 case DUK_ASC_PLUS: /* '+' */
73954 if (DUK__L1() == '+') {
73955 advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
73956 } else if (DUK__L1() == '=') {
73957 advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
73958 } else {
73959 advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
73960 }
73961 break;
73962 case DUK_ASC_MINUS: /* '-' */
73963 if (DUK__L1() == '-') {
73964 advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
73965 } else if (DUK__L1() == '=') {
73966 advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
73967 } else {
73968 advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
73969 }
73970 break;
73971 case DUK_ASC_STAR: /* '*' */
73972 if (DUK__L1() == '=') {
73973 advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
73974 } else {
73975 advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
73976 }
73977 break;
73978 case DUK_ASC_PERCENT: /* '%' */
73979 if (DUK__L1() == '=') {
73980 advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
73981 } else {
73982 advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
73983 }
73984 break;
73985 case DUK_ASC_AMP: /* '&' */
73986 if (DUK__L1() == '&') {
73987 advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
73988 } else if (DUK__L1() == '=') {
73989 advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
73990 } else {
73991 advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
73992 }
73993 break;
73994 case DUK_ASC_PIPE: /* '|' */
73995 if (DUK__L1() == '|') {
73996 advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
73997 } else if (DUK__L1() == '=') {
73998 advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
73999 } else {
74000 advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
74001 }
74002 break;
74003 case DUK_ASC_CARET: /* '^' */
74004 if (DUK__L1() == '=') {
74005 advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
74006 } else {
74007 advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
74008 }
74009 break;
74010 case DUK_ASC_TILDE: /* '~' */
74011 advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
74012 break;
74013 case DUK_ASC_QUESTION: /* '?' */
74014 advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
74015 break;
74016 case DUK_ASC_COLON: /* ':' */
74017 advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
74018 break;
74019 case DUK_ASC_DOUBLEQUOTE: /* '"' */
74020 case DUK_ASC_SINGLEQUOTE: { /* '\'' */
74021 duk_small_int_t quote = x; /* Note: duk_uint8_t type yields larger code */
74022 duk_small_int_t adv;
74023
74024 DUK__INITBUFFER(lex_ctx);
74025 for (;;) {
74026 DUK__ADVANCECHARS(lex_ctx, 1); /* eat opening quote on first loop */
74027 x = DUK__L0();
74028 if (x < 0 || duk_unicode_is_line_terminator(x)) {
74029 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in string literal");
74030 }
74031 if (x == quote) {
74032 DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing quote */
74033 break;
74034 }
74035 if (x == '\\') {
74036 /* DUK__L0 -> '\' char
74037 * DUK__L1 ... DUK__L5 -> more lookup
74038 */
74039
74040 x = DUK__L1();
74041
74042 /* How much to advance before next loop; note that next loop
74043 * will advance by 1 anyway, so -1 from the total escape
74044 * length (e.g. len('\uXXXX') - 1 = 6 - 1). As a default,
74045 * 1 is good.
74046 */
74047 adv = 2 - 1; /* note: long live range */
74048
74049 if (x < 0) {
74050 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in string literal");
74051 }
74053 /* line continuation */
74054 if (x == 0x000d && DUK__L2() == 0x000a) {
74055 /* CR LF again a special case */
74056 adv = 3 - 1;
74057 }
74058 } else if (x == '\'') {
74059 DUK__APPENDBUFFER(lex_ctx, 0x0027);
74060 } else if (x == '"') {
74061 DUK__APPENDBUFFER(lex_ctx, 0x0022);
74062 } else if (x == '\\') {
74063 DUK__APPENDBUFFER(lex_ctx, 0x005c);
74064 } else if (x == 'b') {
74065 DUK__APPENDBUFFER(lex_ctx, 0x0008);
74066 } else if (x == 'f') {
74067 DUK__APPENDBUFFER(lex_ctx, 0x000c);
74068 } else if (x == 'n') {
74069 DUK__APPENDBUFFER(lex_ctx, 0x000a);
74070 } else if (x == 'r') {
74071 DUK__APPENDBUFFER(lex_ctx, 0x000d);
74072 } else if (x == 't') {
74073 DUK__APPENDBUFFER(lex_ctx, 0x0009);
74074 } else if (x == 'v') {
74075 DUK__APPENDBUFFER(lex_ctx, 0x000b);
74076 } else if (x == 'x') {
74077 adv = 4 - 1;
74079 } else if (x == 'u') {
74080 adv = 6 - 1;
74082 } else if (DUK__ISDIGIT(x)) {
74083 duk_codepoint_t ch = 0; /* initialized to avoid warnings of unused var */
74084
74085 /*
74086 * Octal escape or zero escape:
74087 * \0 (lookahead not DecimalDigit)
74088 * \1 ... \7 (lookahead not DecimalDigit)
74089 * \ZeroToThree OctalDigit (lookahead not DecimalDigit)
74090 * \FourToSeven OctalDigit (no lookahead restrictions)
74091 * \ZeroToThree OctalDigit OctalDigit (no lookahead restrictions)
74092 *
74093 * Zero escape is part of the standard syntax. Octal escapes are
74094 * defined in E5 Section B.1.2, and are only allowed in non-strict mode.
74095 * Any other productions starting with a decimal digit are invalid.
74096 */
74097
74098 if (x == '0' && !DUK__ISDIGIT(DUK__L2())) {
74099 /* Zero escape (also allowed in non-strict mode) */
74100 ch = 0;
74101 /* adv = 2 - 1 default OK */
74102#if defined(DUK_USE_OCTAL_SUPPORT)
74103 } else if (strict_mode) {
74104 /* No other escape beginning with a digit in strict mode */
74105 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid escape in string literal");
74106 } else if (DUK__ISDIGIT03(x) && DUK__ISOCTDIGIT(DUK__L2()) && DUK__ISOCTDIGIT(DUK__L3())) {
74107 /* Three digit octal escape, digits validated. */
74108 adv = 4 - 1;
74109 ch = (duk__hexval(lex_ctx, x) << 6) +
74110 (duk__hexval(lex_ctx, DUK__L2()) << 3) +
74111 duk__hexval(lex_ctx, DUK__L3());
74112 } else if (((DUK__ISDIGIT03(x) && !DUK__ISDIGIT(DUK__L3())) || DUK__ISDIGIT47(x)) &&
74114 /* Two digit octal escape, digits validated.
74115 *
74116 * The if-condition is a bit tricky. We could catch e.g.
74117 * '\039' in the three-digit escape and fail it there (by
74118 * validating the digits), but we want to avoid extra
74119 * additional validation code.
74120 */
74121 adv = 3 - 1;
74122 ch = (duk__hexval(lex_ctx, x) << 3) +
74123 duk__hexval(lex_ctx, DUK__L2());
74124 } else if (DUK__ISDIGIT(x) && !DUK__ISDIGIT(DUK__L2())) {
74125 /* One digit octal escape, digit validated. */
74126 /* adv = 2 default OK */
74127 ch = duk__hexval(lex_ctx, x);
74128#else
74129 /* fall through to error */
74130#endif
74131 } else {
74132 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid escape in string literal");
74133 }
74134
74135 DUK__APPENDBUFFER(lex_ctx, ch);
74136 } else {
74137 /* escaped NonEscapeCharacter */
74138 DUK__APPENDBUFFER(lex_ctx, x);
74139 }
74140 DUK__ADVANCECHARS(lex_ctx, adv);
74141
74142 /* Track number of escapes; count not really needed but directive
74143 * prologues need to detect whether there were any escapes or line
74144 * continuations or not.
74145 */
74146 out_token->num_escapes++;
74147 } else {
74148 /* part of string */
74149 DUK__APPENDBUFFER(lex_ctx, x);
74150 }
74151 }
74152
74153 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74154 out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74155
74156 DUK__INITBUFFER(lex_ctx); /* free some memory */
74157
74158 advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
74159 break;
74160 }
74161 default:
74162 goto slow_path;
74163 } /* switch */
74164
74165 goto skip_slow_path;
74166
74167 slow_path:
74169 if (x == 0x000d && DUK__L1() == 0x000a) {
74170 /*
74171 * E5 Section 7.3: CR LF is detected as a single line terminator for
74172 * line numbers. Here we also detect it as a single line terminator
74173 * token.
74174 */
74175 DUK__ADVANCECHARS(lex_ctx, 2);
74176 } else {
74177 DUK__ADVANCECHARS(lex_ctx, 1);
74178 }
74179 got_lineterm = 1;
74180 goto restart_lineupdate;
74181 } else if (duk_unicode_is_identifier_start(x) || x == '\\') {
74182 /*
74183 * Parse an identifier and then check whether it is:
74184 * - reserved word (keyword or other reserved word)
74185 * - "null" (NullLiteral)
74186 * - "true" (BooleanLiteral)
74187 * - "false" (BooleanLiteral)
74188 * - anything else => identifier
74189 *
74190 * This does not follow the E5 productions cleanly, but is
74191 * useful and compact.
74192 *
74193 * Note that identifiers may contain Unicode escapes,
74194 * see E5 Sections 6 and 7.6. They must be decoded first,
74195 * and the result checked against allowed characters.
74196 * The above if-clause accepts an identifier start and an
74197 * '\' character -- no other token can begin with a '\'.
74198 *
74199 * Note that "get" and "set" are not reserved words in E5
74200 * specification so they are recognized as plain identifiers
74201 * (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
74202 * used now). The compiler needs to work around this.
74203 *
74204 * Strictly speaking, following Ecmascript longest match
74205 * specification, an invalid escape for the first character
74206 * should cause a syntax error. However, an invalid escape
74207 * for IdentifierParts should just terminate the identifier
74208 * early (longest match), and let the next tokenization
74209 * fail. For instance Rhino croaks with 'foo\z' when
74210 * parsing the identifier. This has little practical impact.
74211 */
74212
74213 duk_small_int_t i, i_end;
74214 duk_bool_t first = 1;
74215 duk_hstring *str;
74216
74217 DUK__INITBUFFER(lex_ctx);
74218 for (;;) {
74219 /* re-lookup first char on first loop */
74220 if (DUK__L0() == '\\') {
74221 duk_codepoint_t ch;
74222 if (DUK__L1() != 'u') {
74223 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid unicode escape in identifier");
74224 }
74225
74226 ch = duk__decode_uniesc_from_window(lex_ctx, 2);
74227
74228 /* IdentifierStart is stricter than IdentifierPart, so if the first
74229 * character is escaped, must have a stricter check here.
74230 */
74232 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid unicode escape in identifier");
74233 }
74234 DUK__APPENDBUFFER(lex_ctx, ch);
74235 DUK__ADVANCECHARS(lex_ctx, 6);
74236
74237 /* Track number of escapes: necessary for proper keyword
74238 * detection.
74239 */
74240 out_token->num_escapes++;
74241 } else {
74242 /* Note: first character is checked against this. But because
74243 * IdentifierPart includes all IdentifierStart characters, and
74244 * the first character (if unescaped) has already been checked
74245 * in the if condition, this is OK.
74246 */
74248 break;
74249 }
74250 DUK__APPENDBUFFER(lex_ctx, DUK__L0());
74251 DUK__ADVANCECHARS(lex_ctx, 1);
74252 }
74253 first = 0;
74254 }
74255
74256 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74257 out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74258 str = out_token->str1;
74259 DUK_ASSERT(str != NULL);
74260 out_token->t_nores = DUK_TOK_IDENTIFIER;
74261
74262 DUK__INITBUFFER(lex_ctx); /* free some memory */
74263
74264 /*
74265 * Interned identifier is compared against reserved words, which are
74266 * currently interned into the heap context. See genbuiltins.py.
74267 *
74268 * Note that an escape in the identifier disables recognition of
74269 * keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
74270 * identifier named "if"). This is not necessarily compliant,
74271 * see test-dec-escaped-char-in-keyword.js.
74272 *
74273 * Note: "get" and "set" are awkward. They are not officially
74274 * ReservedWords (and indeed e.g. "var set = 1;" is valid), and
74275 * must come out as DUK_TOK_IDENTIFIER. The compiler needs to
74276 * work around this a bit.
74277 */
74278
74279 /* XXX: optimize by adding the token numbers directly into the
74280 * always interned duk_hstring objects (there should be enough
74281 * flag bits free for that)?
74282 */
74283
74285
74286 advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
74287 if (out_token->num_escapes == 0) {
74288 for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
74289 DUK_ASSERT(i >= 0 && i < DUK_HEAP_NUM_STRINGS);
74290 if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
74291 advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
74292 break;
74293 }
74294 }
74295 }
74296 } else if (DUK__ISDIGIT(x) || (x == '.')) {
74297 /* Note: decimal number may start with a period, but must be followed by a digit */
74298
74299 /*
74300 * DecimalLiteral, HexIntegerLiteral, OctalIntegerLiteral
74301 * "pre-parsing", followed by an actual, accurate parser step.
74302 *
74303 * Note: the leading sign character ('+' or '-') is -not- part of
74304 * the production in E5 grammar, and that the a DecimalLiteral
74305 * starting with a '0' must be followed by a non-digit. Leading
74306 * zeroes are syntax errors and must be checked for.
74307 *
74308 * XXX: the two step parsing process is quite awkward, it would
74309 * be more straightforward to allow numconv to parse the longest
74310 * valid prefix (it already does that, it only needs to indicate
74311 * where the input ended). However, the lexer decodes characters
74312 * using a lookup window, so this is not a trivial change.
74313 */
74314
74315 /* XXX: because of the final check below (that the literal is not
74316 * followed by a digit), this could maybe be simplified, if we bail
74317 * out early from a leading zero (and if there are no periods etc).
74318 * Maybe too complex.
74319 */
74320
74321 duk_double_t val;
74322 duk_bool_t int_only = 0;
74323 duk_bool_t allow_hex = 0;
74324 duk_small_int_t state; /* 0=before period/exp,
74325 * 1=after period, before exp
74326 * 2=after exp, allow '+' or '-'
74327 * 3=after exp and exp sign
74328 */
74329 duk_small_uint_t s2n_flags;
74331
74332 DUK__INITBUFFER(lex_ctx);
74333 y = DUK__L1();
74334 if (x == '0' && (y == 'x' || y == 'X')) {
74335 DUK__APPENDBUFFER(lex_ctx, x);
74336 DUK__APPENDBUFFER(lex_ctx, y);
74337 DUK__ADVANCECHARS(lex_ctx, 2);
74338 int_only = 1;
74339 allow_hex = 1;
74340#if defined(DUK_USE_OCTAL_SUPPORT)
74341 } else if (!strict_mode && x == '0' && DUK__ISDIGIT(y)) {
74342 /* Note: if DecimalLiteral starts with a '0', it can only be
74343 * followed by a period or an exponent indicator which starts
74344 * with 'e' or 'E'. Hence the if-check above ensures that
74345 * OctalIntegerLiteral is the only valid NumericLiteral
74346 * alternative at this point (even if y is, say, '9').
74347 */
74348
74349 DUK__APPENDBUFFER(lex_ctx, x);
74350 DUK__ADVANCECHARS(lex_ctx, 1);
74351 int_only = 1;
74352#endif
74353 }
74354
74355 state = 0;
74356 for (;;) {
74357 x = DUK__L0(); /* re-lookup curr char on first round */
74358 if (DUK__ISDIGIT(x)) {
74359 /* Note: intentionally allow leading zeroes here, as the
74360 * actual parser will check for them.
74361 */
74362 if (state == 2) {
74363 state = 3;
74364 }
74365 } else if (allow_hex && DUK__ISHEXDIGIT(x)) {
74366 /* Note: 'e' and 'E' are also accepted here. */
74367 ;
74368 } else if (x == '.') {
74369 if (state >= 1 || int_only) {
74370 break;
74371 } else {
74372 state = 1;
74373 }
74374 } else if (x == 'e' || x == 'E') {
74375 if (state >= 2 || int_only) {
74376 break;
74377 } else {
74378 state = 2;
74379 }
74380 } else if (x == '-' || x == '+') {
74381 if (state != 2) {
74382 break;
74383 } else {
74384 state = 3;
74385 }
74386 } else {
74387 break;
74388 }
74389 DUK__APPENDBUFFER(lex_ctx, x);
74390 DUK__ADVANCECHARS(lex_ctx, 1);
74391 }
74392
74393 /* XXX: better coercion */
74394 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74395
74396 s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
74400#if defined(DUK_USE_OCTAL_SUPPORT)
74401 (strict_mode ? 0 : DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) |
74402#endif
74404
74405 duk_dup((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74406 duk_numconv_parse((duk_context *) lex_ctx->thr, 10 /*radix*/, s2n_flags);
74407 val = duk_to_number((duk_context *) lex_ctx->thr, -1);
74408 if (DUK_ISNAN(val)) {
74409 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid numeric literal");
74410 }
74411 duk_replace((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx); /* could also just pop? */
74412
74413 DUK__INITBUFFER(lex_ctx); /* free some memory */
74414
74415 /* Section 7.8.3 (note): NumericLiteral must be followed by something other than
74416 * IdentifierStart or DecimalDigit.
74417 */
74418
74420 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid numeric literal");
74421 }
74422
74423 out_token->num = val;
74424 advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
74425 } else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
74426 DUK__ADVANCECHARS(lex_ctx, 1);
74427 goto restart;
74428 } else if (x < 0) {
74429 advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
74430 } else {
74431 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid token");
74432 }
74433 skip_slow_path:
74434
74435 /*
74436 * Shared exit path
74437 */
74438
74439 DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
74440 out_token->t = advtok & 0xff;
74441 if (out_token->t_nores < 0) {
74442 out_token->t_nores = out_token->t;
74443 }
74444 out_token->lineterm = got_lineterm;
74445
74446 /* Automatic semicolon insertion is allowed if a token is preceded
74447 * by line terminator(s), or terminates a statement list (right curly
74448 * or EOF).
74449 */
74450 if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
74451 out_token->allow_auto_semi = 1;
74452 } else {
74453 out_token->allow_auto_semi = 0;
74454 }
74455}
74456
74457#if defined(DUK_USE_REGEXP_SUPPORT)
74458
74459/*
74460 * Parse a RegExp token. The grammar is described in E5 Section 15.10.
74461 * Terminal constructions (such as quantifiers) are parsed directly here.
74462 *
74463 * 0xffffffffU is used as a marker for "infinity" in quantifiers. Further,
74464 * DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
74465 * will be accepted for a quantifier.
74466 */
74467
74469 duk_small_int_t advtok = 0; /* init is unnecessary but suppresses "may be used uninitialized" warnings */
74470 duk_codepoint_t x, y;
74471
74472 if (++lex_ctx->token_count >= lex_ctx->token_limit) {
74473 DUK_ERROR_RANGE(lex_ctx->thr, "token limit");
74474 return; /* unreachable */
74475 }
74476
74477 DUK_MEMZERO(out_token, sizeof(*out_token));
74478
74479 x = DUK__L0();
74480 y = DUK__L1();
74481
74482 DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
74483
74484 switch (x) {
74485 case '|': {
74487 break;
74488 }
74489 case '^': {
74491 break;
74492 }
74493 case '$': {
74494 advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
74495 break;
74496 }
74497 case '?': {
74498 out_token->qmin = 0;
74499 out_token->qmax = 1;
74500 if (y == '?') {
74501 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74502 out_token->greedy = 0;
74503 } else {
74504 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74505 out_token->greedy = 1;
74506 }
74507 break;
74508 }
74509 case '*': {
74510 out_token->qmin = 0;
74511 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74512 if (y == '?') {
74513 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74514 out_token->greedy = 0;
74515 } else {
74516 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74517 out_token->greedy = 1;
74518 }
74519 break;
74520 }
74521 case '+': {
74522 out_token->qmin = 1;
74523 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74524 if (y == '?') {
74525 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74526 out_token->greedy = 0;
74527 } else {
74528 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74529 out_token->greedy = 1;
74530 }
74531 break;
74532 }
74533 case '{': {
74534 /* Production allows 'DecimalDigits', including leading zeroes */
74535 duk_uint_fast32_t val1 = 0;
74537 duk_small_int_t digits = 0;
74538#if defined(DUK_USE_ES6_REGEXP_BRACES)
74539 duk_lexer_point lex_pt;
74540#endif
74541
74542#if defined(DUK_USE_ES6_REGEXP_BRACES)
74543 /* Store lexer position, restoring if quantifier is invalid. */
74544 DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
74545#endif
74546
74547 for (;;) {
74548 DUK__ADVANCECHARS(lex_ctx, 1); /* eat '{' on entry */
74549 x = DUK__L0();
74550 if (DUK__ISDIGIT(x)) {
74551 digits++;
74552 val1 = val1 * 10 + (duk_uint_fast32_t) duk__hexval(lex_ctx, x);
74553 } else if (x == ',') {
74554 if (digits > DUK__MAX_RE_QUANT_DIGITS) {
74555 goto invalid_quantifier;
74556 }
74557 if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
74558 goto invalid_quantifier;
74559 }
74560 if (DUK__L1() == '}') {
74561 /* form: { DecimalDigits , }, val1 = min count */
74562 if (digits == 0) {
74563 goto invalid_quantifier;
74564 }
74565 out_token->qmin = val1;
74566 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74567 DUK__ADVANCECHARS(lex_ctx, 2);
74568 break;
74569 }
74570 val2 = val1;
74571 val1 = 0;
74572 digits = 0; /* not strictly necessary because of lookahead '}' above */
74573 } else if (x == '}') {
74574 if (digits > DUK__MAX_RE_QUANT_DIGITS) {
74575 goto invalid_quantifier;
74576 }
74577 if (digits == 0) {
74578 goto invalid_quantifier;
74579 }
74580 if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
74581 /* val2 = min count, val1 = max count */
74582 out_token->qmin = val2;
74583 out_token->qmax = val1;
74584 } else {
74585 /* val1 = count */
74586 out_token->qmin = val1;
74587 out_token->qmax = val1;
74588 }
74589 DUK__ADVANCECHARS(lex_ctx, 1);
74590 break;
74591 } else {
74592 goto invalid_quantifier;
74593 }
74594 }
74595 if (DUK__L0() == '?') {
74596 out_token->greedy = 0;
74597 DUK__ADVANCECHARS(lex_ctx, 1);
74598 } else {
74599 out_token->greedy = 1;
74600 }
74601 advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
74602 break;
74603 invalid_quantifier:
74604#if defined(DUK_USE_ES6_REGEXP_BRACES)
74605 /* Failed to match the quantifier, restore lexer and parse
74606 * opening brace as a literal.
74607 */
74608 DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
74609 advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
74610 out_token->num = '{';
74611#else
74612 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp quantifier");
74613#endif
74614 break;
74615 }
74616 case '.': {
74618 break;
74619 }
74620 case '\\': {
74621 /* The E5.1 specification does not seem to allow IdentifierPart characters
74622 * to be used as identity escapes. Unfortunately this includes '$', which
74623 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
74624 * Many other implementations (including V8 and Rhino, for instance) do
74625 * accept '\$' as a valid identity escape, which is quite pragmatic.
74626 * See: test-regexp-identity-escape-dollar.js.
74627 */
74628
74629 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR); /* default: char escape (two chars) */
74630 if (y == 'b') {
74632 } else if (y == 'B') {
74634 } else if (y == 'f') {
74635 out_token->num = 0x000c;
74636 } else if (y == 'n') {
74637 out_token->num = 0x000a;
74638 } else if (y == 't') {
74639 out_token->num = 0x0009;
74640 } else if (y == 'r') {
74641 out_token->num = 0x000d;
74642 } else if (y == 'v') {
74643 out_token->num = 0x000b;
74644 } else if (y == 'c') {
74645 x = DUK__L2();
74646 if ((x >= 'a' && x <= 'z') ||
74647 (x >= 'A' && x <= 'Z')) {
74648 out_token->num = (x % 32);
74649 advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
74650 } else {
74651 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74652 }
74653 } else if (y == 'x') {
74654 out_token->num = duk__decode_hexesc_from_window(lex_ctx, 2);
74655 advtok = DUK__ADVTOK(4, DUK_RETOK_ATOM_CHAR);
74656 } else if (y == 'u') {
74657 out_token->num = duk__decode_uniesc_from_window(lex_ctx, 2);
74658 advtok = DUK__ADVTOK(6, DUK_RETOK_ATOM_CHAR);
74659 } else if (y == 'd') {
74660 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
74661 } else if (y == 'D') {
74663 } else if (y == 's') {
74664 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
74665 } else if (y == 'S') {
74667 } else if (y == 'w') {
74669 } else if (y == 'W') {
74671 } else if (DUK__ISDIGIT(y)) {
74672 /* E5 Section 15.10.2.11 */
74673 if (y == '0') {
74674 if (DUK__ISDIGIT(DUK__L2())) {
74675 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74676 }
74677 out_token->num = 0x0000;
74678 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
74679 } else {
74680 /* XXX: shared parsing? */
74681 duk_uint_fast32_t val = 0;
74683 for (i = 0; ; i++) {
74684 if (i >= DUK__MAX_RE_DECESC_DIGITS) {
74685 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74686 }
74687 DUK__ADVANCECHARS(lex_ctx, 1); /* eat backslash on entry */
74688 x = DUK__L0();
74689 if (!DUK__ISDIGIT(x)) {
74690 break;
74691 }
74692 val = val * 10 + (duk_uint_fast32_t) duk__hexval(lex_ctx, x);
74693 }
74694 /* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
74696 out_token->num = val;
74697 }
74698 } else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
74700 y == '$' ||
74701#endif
74702 y == DUK_UNICODE_CP_ZWNJ ||
74703 y == DUK_UNICODE_CP_ZWJ) {
74704 /* IdentityEscape, with dollar added as a valid additional
74705 * non-standard escape (see test-regexp-identity-escape-dollar.js).
74706 * Careful not to match end-of-buffer (<0) here.
74707 */
74708 out_token->num = y;
74709 } else {
74710 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74711 }
74712 break;
74713 }
74714 case '(': {
74715 /* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
74716
74717 if (y == '?') {
74718 if (DUK__L2() == '=') {
74719 /* (?= */
74721 } else if (DUK__L2() == '!') {
74722 /* (?! */
74724 } else if (DUK__L2() == ':') {
74725 /* (?: */
74727 }
74728 } else {
74729 /* ( */
74731 }
74732 break;
74733 }
74734 case ')': {
74736 break;
74737 }
74738 case '[': {
74739 /*
74740 * To avoid creating a heavy intermediate value for the list of ranges,
74741 * only the start token ('[' or '[^') is parsed here. The regexp
74742 * compiler parses the ranges itself.
74743 */
74745 if (y == '^') {
74747 }
74748 break;
74749 }
74750#if !defined(DUK_USE_ES6_REGEXP_BRACES)
74751 case '}':
74752#endif
74753 case ']': {
74754 /* Although these could be parsed as PatternCharacters unambiguously (here),
74755 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
74756 */
74757 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp character");
74758 break;
74759 }
74760 case -1: {
74761 /* EOF */
74762 advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
74763 break;
74764 }
74765 default: {
74766 /* PatternCharacter, all excluded characters are matched by cases above */
74767 advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
74768 out_token->num = x;
74769 break;
74770 }
74771 }
74772
74773 /*
74774 * Shared exit path
74775 */
74776
74777 DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
74778 out_token->t = advtok & 0xff;
74779}
74780
74781/*
74782 * Special parser for character classes; calls callback for every
74783 * range parsed and returns the number of ranges present.
74784 */
74786/* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
74787 * required anyway. We could use that BUT we need to update the regexp compiler
74788 * 'nranges' too. Work this out a bit more cleanly to save space.
74789 */
74790
74791/* XXX: the handling of character range detection is a bit convoluted.
74792 * Try to simplify and make smaller.
74793 */
74794
74795/* XXX: logic for handling character ranges is now incorrect, it will accept
74796 * e.g. [\d-z] whereas it should croak from it? SMJS accepts this too, though.
74797 *
74798 * Needs a read through and a lot of additional tests.
74799 */
74800
74803 duk_re_range_callback gen_range,
74804 void *userdata,
74805 const duk_uint16_t *ranges,
74806 duk_small_int_t num) {
74807 const duk_uint16_t *ranges_end;
74808
74809 DUK_UNREF(lex_ctx);
74810
74811 ranges_end = ranges + num;
74812 while (ranges < ranges_end) {
74813 /* mark range 'direct', bypass canonicalization (see Wiki) */
74814 gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
74815 ranges += 2;
74816 }
74817}
74818
74819DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
74820 duk_codepoint_t start = -1;
74821 duk_codepoint_t ch;
74823 duk_bool_t dash = 0;
74824
74825 DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
74826
74827 for (;;) {
74828 x = DUK__L0();
74829 DUK__ADVANCECHARS(lex_ctx, 1);
74830
74831 ch = -1; /* not strictly necessary, but avoids "uninitialized variable" warnings */
74832 DUK_UNREF(ch);
74833
74834 if (x < 0) {
74835 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof in character class");
74836 } else if (x == ']') {
74837 DUK_ASSERT(!dash); /* lookup should prevent this */
74838 if (start >= 0) {
74839 gen_range(userdata, start, start, 0);
74840 }
74841 break;
74842 } else if (x == '-') {
74843 if (start >= 0 && !dash && DUK__L0() != ']') {
74844 /* '-' as a range indicator */
74845 dash = 1;
74846 continue;
74847 } else {
74848 /* '-' verbatim */
74849 ch = x;
74850 }
74851 } else if (x == '\\') {
74852 /*
74853 * The escapes are same as outside a character class, except that \b has a
74854 * different meaning, and \B and backreferences are prohibited (see E5
74855 * Section 15.10.2.19). However, it's difficult to share code because we
74856 * handle e.g. "\n" very differently: here we generate a single character
74857 * range for it.
74858 */
74859
74860 x = DUK__L0();
74861 DUK__ADVANCECHARS(lex_ctx, 1);
74862
74863 if (x == 'b') {
74864 /* Note: '\b' in char class is different than outside (assertion),
74865 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
74866 * check below.
74867 */
74868 ch = 0x0008;
74869 } else if (x == 'f') {
74870 ch = 0x000c;
74871 } else if (x == 'n') {
74872 ch = 0x000a;
74873 } else if (x == 't') {
74874 ch = 0x0009;
74875 } else if (x == 'r') {
74876 ch = 0x000d;
74877 } else if (x == 'v') {
74878 ch = 0x000b;
74879 } else if (x == 'c') {
74880 x = DUK__L0();
74881 DUK__ADVANCECHARS(lex_ctx, 1);
74882 if ((x >= 'a' && x <= 'z') ||
74883 (x >= 'A' && x <= 'Z')) {
74884 ch = (x % 32);
74885 } else {
74886 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74887 return; /* never reached, but avoids warnings of
74888 * potentially unused variables.
74889 */
74890 }
74891 } else if (x == 'x') {
74892 ch = duk__decode_hexesc_from_window(lex_ctx, 0);
74893 DUK__ADVANCECHARS(lex_ctx, 2);
74894 } else if (x == 'u') {
74895 ch = duk__decode_uniesc_from_window(lex_ctx, 0);
74896 DUK__ADVANCECHARS(lex_ctx, 4);
74897 } else if (x == 'd') {
74899 gen_range,
74900 userdata,
74902 sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
74903 ch = -1;
74904 } else if (x == 'D') {
74906 gen_range,
74907 userdata,
74909 sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
74910 ch = -1;
74911 } else if (x == 's') {
74913 gen_range,
74914 userdata,
74916 sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
74917 ch = -1;
74918 } else if (x == 'S') {
74920 gen_range,
74921 userdata,
74923 sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
74924 ch = -1;
74925 } else if (x == 'w') {
74927 gen_range,
74928 userdata,
74930 sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
74931 ch = -1;
74932 } else if (x == 'W') {
74934 gen_range,
74935 userdata,
74937 sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
74938 ch = -1;
74939 } else if (DUK__ISDIGIT(x)) {
74940 /* DecimalEscape, only \0 is allowed, no leading zeroes are allowed */
74941 if (x == '0' && !DUK__ISDIGIT(DUK__L0())) {
74942 ch = 0x0000;
74943 } else {
74944 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74945 }
74946 } else if (!duk_unicode_is_identifier_part(x)
74948 || x == '$'
74949#endif
74950 ) {
74951 /* IdentityEscape */
74952 ch = x;
74953 } else {
74954 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74955 }
74956 } else {
74957 /* character represents itself */
74958 ch = x;
74959 }
74960
74961 /* ch is a literal character here or -1 if parsed entity was
74962 * an escape such as "\s".
74963 */
74964
74965 if (ch < 0) {
74966 /* multi-character sets not allowed as part of ranges, see
74967 * E5 Section 15.10.2.15, abstract operation CharacterRange.
74968 */
74969 if (start >= 0) {
74970 if (dash) {
74971 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid range");
74972 } else {
74973 gen_range(userdata, start, start, 0);
74974 start = -1;
74975 /* dash is already 0 */
74976 }
74977 }
74978 } else {
74979 if (start >= 0) {
74980 if (dash) {
74981 if (start > ch) {
74982 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid range");
74983 }
74984 gen_range(userdata, start, ch, 0);
74985 start = -1;
74986 dash = 0;
74987 } else {
74988 gen_range(userdata, start, start, 0);
74989 start = ch;
74990 /* dash is already 0 */
74991 }
74992 } else {
74993 start = ch;
74994 }
74995 }
74996 }
74997
74998 return;
75001#endif /* DUK_USE_REGEXP_SUPPORT */
75003 * Number-to-string and string-to-number conversions.
75004 *
75005 * Slow path number-to-string and string-to-number conversion is based on
75006 * a Dragon4 variant, with fast paths for small integers. Big integer
75007 * arithmetic is needed for guaranteeing that the conversion is correct
75008 * and uses a minimum number of digits. The big number arithmetic has a
75009 * fixed maximum size and does not require dynamic allocations.
75010 *
75011 * See: doc/number-conversion.rst.
75012 */
75013
75014/* include removed: duk_internal.h */
75015
75016#define DUK__IEEE_DOUBLE_EXP_BIAS 1023
75017#define DUK__IEEE_DOUBLE_EXP_MIN (-1022) /* biased exp == 0 -> denormal, exp -1022 */
75018
75019#define DUK__DIGITCHAR(x) duk_lc_digits[(x)]
75020
75021/*
75022 * Tables generated with src/gennumdigits.py.
75023 *
75024 * duk__str2num_digits_for_radix indicates, for each radix, how many input
75025 * digits should be considered significant for string-to-number conversion.
75026 * The input is also padded to this many digits to give the Dragon4
75027 * conversion enough (apparent) precision to work with.
75029 * duk__str2num_exp_limits indicates, for each radix, the radix-specific
75030 * minimum/maximum exponent values (for a Dragon4 integer mantissa)
75031 * below and above which the number is guaranteed to underflow to zero
75032 * or overflow to Infinity. This allows parsing to keep bigint values
75033 * bounded.
75034 */
75035
75036DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
75037 69, 44, 35, 30, 27, 25, 23, 22, 20, 20, /* 2 to 11 */
75038 20, 19, 19, 18, 18, 17, 17, 17, 16, 16, /* 12 to 21 */
75039 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, /* 22 to 31 */
75040 14, 14, 14, 14, 14 /* 31 to 36 */
75041};
75042
75043typedef struct {
75044 duk_int16_t upper;
75045 duk_int16_t lower;
75047
75049 { 957, -1147 }, { 605, -725 }, { 479, -575 }, { 414, -496 },
75050 { 372, -446 }, { 342, -411 }, { 321, -384 }, { 304, -364 },
75051 { 291, -346 }, { 279, -334 }, { 268, -323 }, { 260, -312 },
75052 { 252, -304 }, { 247, -296 }, { 240, -289 }, { 236, -283 },
75053 { 231, -278 }, { 227, -273 }, { 223, -267 }, { 220, -263 },
75054 { 216, -260 }, { 213, -256 }, { 210, -253 }, { 208, -249 },
75055 { 205, -246 }, { 203, -244 }, { 201, -241 }, { 198, -239 },
75056 { 196, -237 }, { 195, -234 }, { 193, -232 }, { 191, -230 },
75057 { 190, -228 }, { 188, -226 }, { 187, -225 },
75059
75060/*
75061 * Limited functionality bigint implementation.
75062 *
75063 * Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
75064 * with the caller responsible for ensuring this is never exceeded. No memory
75065 * allocation (except stack) is needed for bigint computation. Operations
75066 * have been tailored for number conversion needs.
75068 * Argument order is "assignment order", i.e. target first, then arguments:
75069 * x <- y * z --> duk__bi_mul(x, y, z);
75070 */
75071
75072/* This upper value has been experimentally determined; debug build will check
75073 * bigint size with assertions.
75074 */
75075#define DUK__BI_MAX_PARTS 37 /* 37x32 = 1184 bits */
75076
75077#ifdef DUK_USE_DDDPRINT
75078#define DUK__BI_PRINT(name,x) duk__bi_print((name),(x))
75079#else
75080#define DUK__BI_PRINT(name,x)
75081#endif
75082
75083/* Current size is about 152 bytes. */
75084typedef struct {
75086 duk_uint32_t v[DUK__BI_MAX_PARTS]; /* low to high */
75087} duk__bigint;
75088
75089#ifdef DUK_USE_DDDPRINT
75090DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
75091 /* Overestimate required size; debug code so not critical to be tight. */
75092 char buf[DUK__BI_MAX_PARTS * 9 + 64];
75093 char *p = buf;
75095
75096 /* No NUL term checks in this debug code. */
75097 p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
75098 if (x->n == 0) {
75099 p += DUK_SPRINTF(p, " 0");
75101 for (i = x->n - 1; i >= 0; i--) {
75102 p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
75103 }
75104
75105 DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
75106}
75107#endif
75108
75109#ifdef DUK_USE_ASSERTIONS
75110DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
75111 return (duk_small_int_t)
75112 ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
75113 ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
75114}
75115#endif
75116
75119
75120 for (i = x->n - 1; i >= 0; i--) {
75121 if (x->v[i] != 0) {
75122 break;
75123 }
75124 }
75125
75126 /* Note: if 'x' is zero, x->n becomes 0 here */
75127 x->n = i + 1;
75128 DUK_ASSERT(duk__bi_is_valid(x));
75129}
75130
75131/* x <- y */
75134
75135 n = y->n;
75136 x->n = n;
75137 if (n == 0) {
75138 return;
75139 }
75140 DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
75141}
75142
75143DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
75144 if (v == 0U) {
75145 x->n = 0;
75146 } else {
75147 x->n = 1;
75148 x->v[0] = v;
75149 }
75150 DUK_ASSERT(duk__bi_is_valid(x));
75151}
75152
75153/* Return value: <0 <=> x < y
75154 * 0 <=> x == y
75155 * >0 <=> x > y
75156 */
75158 duk_small_int_t i, nx, ny;
75159 duk_uint32_t tx, ty;
75160
75161 DUK_ASSERT(duk__bi_is_valid(x));
75162 DUK_ASSERT(duk__bi_is_valid(y));
75163
75164 nx = x->n;
75165 ny = y->n;
75166 if (nx > ny) {
75167 goto ret_gt;
75168 }
75169 if (nx < ny) {
75170 goto ret_lt;
75171 }
75172 for (i = nx - 1; i >= 0; i--) {
75173 tx = x->v[i];
75174 ty = y->v[i];
75175
75176 if (tx > ty) {
75177 goto ret_gt;
75178 }
75179 if (tx < ty) {
75180 goto ret_lt;
75181 }
75182 }
75183
75184 return 0;
75185
75186 ret_gt:
75187 return 1;
75188
75189 ret_lt:
75190 return -1;
75191}
75192
75193/* x <- y + z */
75194#ifdef DUK_USE_64BIT_OPS
75196 duk_uint64_t tmp;
75197 duk_small_int_t i, ny, nz;
75198
75199 DUK_ASSERT(duk__bi_is_valid(y));
75200 DUK_ASSERT(duk__bi_is_valid(z));
75201
75202 if (z->n > y->n) {
75203 duk__bigint *t;
75204 t = y; y = z; z = t;
75205 }
75206 DUK_ASSERT(y->n >= z->n);
75207
75208 ny = y->n; nz = z->n;
75209 tmp = 0U;
75210 for (i = 0; i < ny; i++) {
75212 tmp += y->v[i];
75213 if (i < nz) {
75214 tmp += z->v[i];
75215 }
75216 x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
75217 tmp = tmp >> 32;
75218 }
75219 if (tmp != 0U) {
75221 x->v[i++] = (duk_uint32_t) tmp;
75222 }
75223 x->n = i;
75225
75226 /* no need to normalize */
75227 DUK_ASSERT(duk__bi_is_valid(x));
75228}
75229#else /* DUK_USE_64BIT_OPS */
75231 duk_uint32_t carry, tmp1, tmp2;
75232 duk_small_int_t i, ny, nz;
75233
75234 DUK_ASSERT(duk__bi_is_valid(y));
75235 DUK_ASSERT(duk__bi_is_valid(z));
75236
75237 if (z->n > y->n) {
75238 duk__bigint *t;
75239 t = y; y = z; z = t;
75240 }
75241 DUK_ASSERT(y->n >= z->n);
75242
75243 ny = y->n; nz = z->n;
75244 carry = 0U;
75245 for (i = 0; i < ny; i++) {
75246 /* Carry is detected based on wrapping which relies on exact 32-bit
75247 * types.
75248 */
75250 tmp1 = y->v[i];
75251 tmp2 = tmp1;
75252 if (i < nz) {
75253 tmp2 += z->v[i];
75254 }
75255
75256 /* Careful with carry condition:
75257 * - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
75258 * - If carry added: 0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
75259 */
75260 if (carry) {
75261 tmp2++;
75262 carry = (tmp2 <= tmp1 ? 1U : 0U);
75263 } else {
75264 carry = (tmp2 < tmp1 ? 1U : 0U);
75265 }
75267 x->v[i] = tmp2;
75268 }
75269 if (carry) {
75271 DUK_ASSERT(carry == 1U);
75272 x->v[i++] = carry;
75273 }
75274 x->n = i;
75276
75277 /* no need to normalize */
75278 DUK_ASSERT(duk__bi_is_valid(x));
75279}
75280#endif /* DUK_USE_64BIT_OPS */
75281
75282/* x <- y + z */
75283DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75284 duk__bigint tmp;
75285
75286 DUK_ASSERT(duk__bi_is_valid(y));
75287
75288 /* XXX: this could be optimized; there is only one call site now though */
75289 duk__bi_set_small(&tmp, z);
75290 duk__bi_add(x, y, &tmp);
75291
75292 DUK_ASSERT(duk__bi_is_valid(x));
75293}
75294
75295#if 0 /* unused */
75296/* x <- x + y, use t as temp */
75297DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
75298 duk__bi_add(t, x, y);
75299 duk__bi_copy(x, t);
75300}
75301#endif
75302
75303/* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
75304#ifdef DUK_USE_64BIT_OPS
75306 duk_small_int_t i, ny, nz;
75307 duk_uint32_t ty, tz;
75308 duk_int64_t tmp;
75309
75310 DUK_ASSERT(duk__bi_is_valid(y));
75311 DUK_ASSERT(duk__bi_is_valid(z));
75312 DUK_ASSERT(duk__bi_compare(y, z) >= 0);
75313 DUK_ASSERT(y->n >= z->n);
75314
75315 ny = y->n; nz = z->n;
75316 tmp = 0;
75317 for (i = 0; i < ny; i++) {
75318 ty = y->v[i];
75319 if (i < nz) {
75320 tz = z->v[i];
75321 } else {
75322 tz = 0;
75323 }
75324 tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
75325 x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
75326 tmp = tmp >> 32; /* 0 or -1 */
75327 }
75328 DUK_ASSERT(tmp == 0);
75329
75330 x->n = i;
75331 duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
75332 DUK_ASSERT(duk__bi_is_valid(x));
75333}
75334#else
75336 duk_small_int_t i, ny, nz;
75337 duk_uint32_t tmp1, tmp2, borrow;
75338
75339 DUK_ASSERT(duk__bi_is_valid(y));
75340 DUK_ASSERT(duk__bi_is_valid(z));
75341 DUK_ASSERT(duk__bi_compare(y, z) >= 0);
75342 DUK_ASSERT(y->n >= z->n);
75343
75344 ny = y->n; nz = z->n;
75345 borrow = 0U;
75346 for (i = 0; i < ny; i++) {
75347 /* Borrow is detected based on wrapping which relies on exact 32-bit
75348 * types.
75349 */
75350 tmp1 = y->v[i];
75351 tmp2 = tmp1;
75352 if (i < nz) {
75353 tmp2 -= z->v[i];
75354 }
75355
75356 /* Careful with borrow condition:
75357 * - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
75358 * - If borrow subtracted: 0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
75359 */
75360 if (borrow) {
75361 tmp2--;
75362 borrow = (tmp2 >= tmp1 ? 1U : 0U);
75363 } else {
75364 borrow = (tmp2 > tmp1 ? 1U : 0U);
75365 }
75366
75367 x->v[i] = tmp2;
75368 }
75369 DUK_ASSERT(borrow == 0U);
75370
75371 x->n = i;
75372 duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
75373 DUK_ASSERT(duk__bi_is_valid(x));
75374}
75375#endif
75377#if 0 /* unused */
75378/* x <- y - z */
75379DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75380 duk__bigint tmp;
75381
75382 DUK_ASSERT(duk__bi_is_valid(y));
75383
75384 /* XXX: this could be optimized */
75385 duk__bi_set_small(&tmp, z);
75386 duk__bi_sub(x, y, &tmp);
75387
75388 DUK_ASSERT(duk__bi_is_valid(x));
75389}
75390#endif
75391
75392/* x <- x - y, use t as temp */
75394 duk__bi_sub(t, x, y);
75395 duk__bi_copy(x, t);
75396}
75397
75398/* x <- y * z */
75400 duk_small_int_t i, j, nx, nz;
75401
75402 DUK_ASSERT(duk__bi_is_valid(y));
75403 DUK_ASSERT(duk__bi_is_valid(z));
75404
75405 nx = y->n + z->n; /* max possible */
75407
75408 if (nx == 0) {
75409 /* Both inputs are zero; cases where only one is zero can go
75410 * through main algorithm.
75411 */
75412 x->n = 0;
75413 return;
75414 }
75415
75416 DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * nx));
75417 x->n = nx;
75418
75419 nz = z->n;
75420 for (i = 0; i < y->n; i++) {
75421#ifdef DUK_USE_64BIT_OPS
75422 duk_uint64_t tmp = 0U;
75423 for (j = 0; j < nz; j++) {
75424 tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
75425 x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
75426 tmp = tmp >> 32;
75427 }
75428 if (tmp > 0) {
75429 DUK_ASSERT(i + j < nx);
75431 DUK_ASSERT(x->v[i+j] == 0U);
75432 x->v[i+j] = (duk_uint32_t) tmp;
75433 }
75434#else
75435 /*
75436 * Multiply + add + carry for 32-bit components using only 16x16->32
75437 * multiplies and carry detection based on unsigned overflow.
75438 *
75439 * 1st mult, 32-bit: (A*2^16 + B)
75440 * 2nd mult, 32-bit: (C*2^16 + D)
75441 * 3rd add, 32-bit: E
75442 * 4th add, 32-bit: F
75443 *
75444 * (AC*2^16 + B) * (C*2^16 + D) + E + F
75445 * = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
75446 * = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
75447 * = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
75448 */
75449 duk_uint32_t a, b, c, d, e, f;
75450 duk_uint32_t r, s, t;
75451
75452 a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
75453
75454 f = 0;
75455 for (j = 0; j < nz; j++) {
75456 c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
75457 e = x->v[i+j];
75458
75459 /* build result as: (r << 32) + s: start with (BD + E + F) */
75460 r = 0;
75461 s = b * d;
75462
75463 /* add E */
75464 t = s + e;
75465 if (t < s) { r++; } /* carry */
75466 s = t;
75467
75468 /* add F */
75469 t = s + f;
75470 if (t < s) { r++; } /* carry */
75471 s = t;
75472
75473 /* add BC*2^16 */
75474 t = b * c;
75475 r += (t >> 16);
75476 t = s + ((t & 0xffffUL) << 16);
75477 if (t < s) { r++; } /* carry */
75478 s = t;
75479
75480 /* add AD*2^16 */
75481 t = a * d;
75482 r += (t >> 16);
75483 t = s + ((t & 0xffffUL) << 16);
75484 if (t < s) { r++; } /* carry */
75485 s = t;
75486
75487 /* add AC*2^32 */
75488 t = a * c;
75489 r += t;
75490
75491 DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
75492 (unsigned long) y->v[i], (unsigned long) z->v[j],
75493 (unsigned long) x->v[i+j], (unsigned long) r,
75494 (unsigned long) s));
75495
75496 x->v[i+j] = s;
75497 f = r;
75498 }
75499 if (f > 0U) {
75500 DUK_ASSERT(i + j < nx);
75502 DUK_ASSERT(x->v[i+j] == 0U);
75503 x->v[i+j] = (duk_uint32_t) f;
75504 }
75505#endif /* DUK_USE_64BIT_OPS */
75506 }
75507
75509 DUK_ASSERT(duk__bi_is_valid(x));
75510}
75511
75512/* x <- y * z */
75513DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75514 duk__bigint tmp;
75516 DUK_ASSERT(duk__bi_is_valid(y));
75517
75518 /* XXX: this could be optimized */
75519 duk__bi_set_small(&tmp, z);
75520 duk__bi_mul(x, y, &tmp);
75521
75522 DUK_ASSERT(duk__bi_is_valid(x));
75523}
75524
75525/* x <- x * y, use t as temp */
75527 duk__bi_mul(t, x, y);
75528 duk__bi_copy(x, t);
75529}
75530
75531/* x <- x * y, use t as temp */
75532DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
75533 duk__bi_mul_small(t, x, y);
75534 duk__bi_copy(x, t);
75535}
75538 DUK_ASSERT(duk__bi_is_valid(x));
75539 return (x->n == 0) || ((x->v[0] & 0x01) == 0);
75540}
75541
75543 DUK_ASSERT(duk__bi_is_valid(x));
75544 return (x->n == 0); /* this is the case for normalized numbers */
75545}
75546
75547/* Bigint is 2^52. Used to detect normalized IEEE double mantissa values
75548 * which are at the lowest edge (next floating point value downwards has
75549 * a different exponent). The lowest mantissa has the form:
75550 *
75551 * 1000........000 (52 zeroes; only "hidden bit" is set)
75552 */
75554 DUK_ASSERT(duk__bi_is_valid(x));
75556 (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
75557}
75558
75559/* x <- (1<<y) */
75561 duk_small_int_t n, r;
75562
75563 n = (y / 32) + 1;
75564 DUK_ASSERT(n > 0);
75565 r = y % 32;
75566 DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * n);
75567 x->n = n;
75568 x->v[n - 1] = (((duk_uint32_t) 1) << r);
75569}
75570
75571/* x <- b^y; use t1 and t2 as temps */
75573 /* Fast path the binary case */
75574
75575 DUK_ASSERT(x != t1 && x != t2 && t1 != t2); /* distinct bignums, easy mistake to make */
75576 DUK_ASSERT(b >= 0);
75577 DUK_ASSERT(y >= 0);
75578
75579 if (b == 2) {
75580 duk__bi_twoexp(x, y);
75581 return;
75582 }
75583
75584 /* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
75585
75586 DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
75587
75588 duk__bi_set_small(x, 1);
75589 duk__bi_set_small(t1, b);
75590 for (;;) {
75591 /* Loop structure ensures that we don't compute t1^2 unnecessarily
75592 * on the final round, as that might create a bignum exceeding the
75593 * current DUK__BI_MAX_PARTS limit.
75594 */
75595 if (y & 0x01) {
75596 duk__bi_mul_copy(x, t1, t2);
75597 }
75598 y = y >> 1;
75599 if (y == 0) {
75600 break;
75601 }
75602 duk__bi_mul_copy(t1, t1, t2);
75603 }
75604
75605 DUK__BI_PRINT("exp_small result", x);
75606}
75607
75608/*
75609 * A Dragon4 number-to-string variant, based on:
75610 *
75611 * Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
75612 * Accurately"
75614 * Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
75615 * Quickly and Accurately"
75617 * The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
75618 * i.e. the base implementation without logarithm estimation speedups
75619 * (these would increase code footprint considerably). Fixed-format output
75620 * does not follow the suggestions in the paper; instead, we generate an
75621 * extra digit and round-with-carry.
75623 * The same algorithm is used for number parsing (with b=10 and B=2)
75624 * by generating one extra digit and doing rounding manually.
75625 *
75626 * See doc/number-conversion.rst for limitations.
75627 */
75629/* Maximum number of digits generated. */
75630#define DUK__MAX_OUTPUT_DIGITS 1040 /* (Number.MAX_VALUE).toString(2).length == 1024, + spare */
75632/* Maximum number of characters in formatted value. */
75633#define DUK__MAX_FORMATTED_LENGTH 1040 /* (-Number.MAX_VALUE).toString(2).length == 1025, + spare */
75635/* Number and (minimum) size of bigints in the nc_ctx structure. */
75636#define DUK__NUMCONV_CTX_NUM_BIGINTS 7
75637#define DUK__NUMCONV_CTX_BIGINTS_SIZE (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
75639typedef struct {
75640 /* Currently about 7*152 = 1064 bytes. The space for these
75641 * duk__bigints is used also as a temporary buffer for generating
75642 * the final string. This is a bit awkard; a union would be
75643 * more correct.
75645 duk__bigint f, r, s, mp, mm, t1, t2;
75646
75647 duk_small_int_t is_s2n; /* if 1, doing a string-to-number; else doing a number-to-string */
75648 duk_small_int_t is_fixed; /* if 1, doing a fixed format output (not free format) */
75649 duk_small_int_t req_digits; /* requested number of output digits; 0 = free-format */
75650 duk_small_int_t abs_pos; /* digit position is absolute, not relative */
75651 duk_small_int_t e; /* exponent for 'f' */
75652 duk_small_int_t b; /* input radix */
75653 duk_small_int_t B; /* output radix */
75654 duk_small_int_t k; /* see algorithm */
75655 duk_small_int_t low_ok; /* see algorithm */
75656 duk_small_int_t high_ok; /* see algorithm */
75657 duk_small_int_t unequal_gaps; /* m+ != m- (very rarely) */
75658
75659 /* Buffer used for generated digits, values are in the range [0,B-1]. */
75660 duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
75661 duk_small_int_t count; /* digit count */
75663
75664/* Note: computes with 'idx' in assertions, so caller beware.
75665 * 'idx' is preincremented, i.e. '1' on first call, because it
75666 * is more convenient for the caller.
75667 */
75668#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x) do { \
75669 DUK_ASSERT((preinc_idx) - 1 >= 0); \
75670 DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
75671 ((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
75672 } while (0)
75673
75674DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
75675 duk_uint8_t *p;
75676 duk_size_t len;
75677 duk_small_int_t dig;
75679
75680 DUK_ASSERT(radix >= 2 && radix <= 36);
75681
75682 /* A 32-bit unsigned integer formats to at most 32 digits (the
75683 * worst case happens with radix == 2). Output the digits backwards,
75684 * and use a memmove() to get them in the right place.
75685 */
75686
75687 p = buf + 32;
75688 for (;;) {
75689 t = x / radix;
75690 dig = x - t * radix;
75691 x = t;
75692
75693 DUK_ASSERT(dig >= 0 && dig < 36);
75694 *(--p) = DUK__DIGITCHAR(dig);
75695
75696 if (x == 0) {
75697 break;
75698 }
75699 }
75700 len = (duk_size_t) ((buf + 32) - p);
75701
75702 DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);
75703
75704 return len;
75705}
75706
75708 duk_small_int_t lowest_mantissa;
75709
75710#if 1
75711 /* Assume IEEE round-to-even, so that shorter encoding can be used
75712 * when round-to-even would produce correct result. By removing
75713 * this check (and having low_ok == high_ok == 0) the results would
75714 * still be accurate but in some cases longer than necessary.
75715 */
75716 if (duk__bi_is_even(&nc_ctx->f)) {
75717 DUK_DDD(DUK_DDDPRINT("f is even"));
75718 nc_ctx->low_ok = 1;
75719 nc_ctx->high_ok = 1;
75720 } else {
75721 DUK_DDD(DUK_DDDPRINT("f is odd"));
75722 nc_ctx->low_ok = 0;
75723 nc_ctx->high_ok = 0;
75724 }
75725#else
75726 /* Note: not honoring round-to-even should work but now generates incorrect
75727 * results. For instance, 1e23 serializes to "a000...", i.e. the first digit
75728 * equals the radix (10). Scaling stops one step too early in this case.
75729 * Don't know why this is the case, but since this code path is unused, it
75730 * doesn't matter.
75731 */
75732 nc_ctx->low_ok = 0;
75733 nc_ctx->high_ok = 0;
75734#endif
75735
75736 /* For string-to-number, pretend we never have the lowest mantissa as there
75737 * is no natural "precision" for inputs. Having lowest_mantissa == 0, we'll
75738 * fall into the base cases for both e >= 0 and e < 0.
75739 */
75740 if (nc_ctx->is_s2n) {
75741 lowest_mantissa = 0;
75742 } else {
75743 lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
75744 }
75745
75746 nc_ctx->unequal_gaps = 0;
75747 if (nc_ctx->e >= 0) {
75748 /* exponent non-negative (and thus not minimum exponent) */
75749
75750 if (lowest_mantissa) {
75751 /* (>= e 0) AND (= f (expt b (- p 1)))
75752 *
75753 * be <- (expt b e) == b^e
75754 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
75755 * r <- (* f be1 2) == 2 * f * b^(e+1) [if b==2 -> f * b^(e+2)]
75756 * s <- (* b 2) [if b==2 -> 4]
75757 * m+ <- be1 == b^(e+1)
75758 * m- <- be == b^e
75759 * k <- 0
75760 * B <- B
75761 * low_ok <- round
75762 * high_ok <- round
75763 */
75764
75765 DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
75766 "lowest mantissa value for this exponent -> "
75767 "unequal gaps"));
75768
75769 duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
75770 duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, nc_ctx->b); /* mp <- b^(e+1) */
75771 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
75772 duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^(e+1) */
75773 duk__bi_set_small(&nc_ctx->s, nc_ctx->b * 2); /* s <- 2 * b */
75774 nc_ctx->unequal_gaps = 1;
75775 } else {
75776 /* (>= e 0) AND (not (= f (expt b (- p 1))))
75777 *
75778 * be <- (expt b e) == b^e
75779 * r <- (* f be 2) == 2 * f * b^e [if b==2 -> f * b^(e+1)]
75780 * s <- 2
75781 * m+ <- be == b^e
75782 * m- <- be == b^e
75783 * k <- 0
75784 * B <- B
75785 * low_ok <- round
75786 * high_ok <- round
75787 */
75788
75789 DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
75790 "not lowest mantissa for this exponent -> "
75791 "equal gaps"));
75792
75793 duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
75794 duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm); /* mp <- b^e */
75795 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
75796 duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^e */
75797 duk__bi_set_small(&nc_ctx->s, 2); /* s <- 2 */
75798 }
75799 } else {
75800 /* When doing string-to-number, lowest_mantissa is always 0 so
75801 * the exponent check, while incorrect, won't matter.
75802 */
75803 if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
75804 lowest_mantissa /* lowest mantissa for this exponent*/) {
75805 /* r <- (* f b 2) [if b==2 -> (* f 4)]
75806 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2 [if b==2 -> b^(2-e)]
75807 * m+ <- b == 2
75808 * m- <- 1
75809 * k <- 0
75810 * B <- B
75811 * low_ok <- round
75812 * high_ok <- round
75813 */
75814
75815 DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
75816 "lowest mantissa for this exponent -> "
75817 "unequal gaps"));
75818
75819 duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, nc_ctx->b * 2); /* r <- (2 * b) * f */
75820 duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, 1 - nc_ctx->e, &nc_ctx->s, &nc_ctx->t2); /* NB: use 's' as temp on purpose */
75821 duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(1-e) * 2 */
75822 duk__bi_set_small(&nc_ctx->mp, 2);
75823 duk__bi_set_small(&nc_ctx->mm, 1);
75824 nc_ctx->unequal_gaps = 1;
75825 } else {
75826 /* r <- (* f 2)
75827 * s <- (* (expt b (- e)) 2) == b^(-e) * 2 [if b==2 -> b^(1-e)]
75828 * m+ <- 1
75829 * m- <- 1
75830 * k <- 0
75831 * B <- B
75832 * low_ok <- round
75833 * high_ok <- round
75834 */
75835
75836 DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
75837 "lowest mantissa for this exponent -> "
75838 "equal gaps"));
75839
75840 duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2); /* r <- 2 * f */
75841 duk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, -nc_ctx->e, &nc_ctx->s, &nc_ctx->t2); /* NB: use 's' as temp on purpose */
75842 duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(-e) * 2 */
75843 duk__bi_set_small(&nc_ctx->mp, 1);
75844 duk__bi_set_small(&nc_ctx->mm, 1);
75845 }
75846 }
75847}
75848
75850 duk_small_int_t k = 0;
75851
75852 /* This is essentially the 'scale' algorithm, with recursion removed.
75853 * Note that 'k' is either correct immediately, or will move in one
75854 * direction in the loop. There's no need to do the low/high checks
75855 * on every round (like the Scheme algorithm does).
75856 *
75857 * The scheme algorithm finds 'k' and updates 's' simultaneously,
75858 * while the logical algorithm finds 'k' with 's' having its initial
75859 * value, after which 's' is updated separately (see the Burger-Dybvig
75860 * paper, Section 3.1, steps 2 and 3).
75861 *
75862 * The case where m+ == m- (almost always) is optimized for, because
75863 * it reduces the bigint operations considerably and almost always
75864 * applies. The scale loop only needs to work with m+, so this works.
75865 */
75866
75867 /* XXX: this algorithm could be optimized quite a lot by using e.g.
75868 * a logarithm based estimator for 'k' and performing B^n multiplication
75869 * using a lookup table or using some bit-representation based exp
75870 * algorithm. Currently we just loop, with significant performance
75871 * impact for very large and very small numbers.
75872 */
75873
75874 DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
75875 (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
75876 DUK__BI_PRINT("r(init)", &nc_ctx->r);
75877 DUK__BI_PRINT("s(init)", &nc_ctx->s);
75878 DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
75879 DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
75880
75881 for (;;) {
75882 DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
75883 DUK__BI_PRINT("r", &nc_ctx->r);
75884 DUK__BI_PRINT("s", &nc_ctx->s);
75885 DUK__BI_PRINT("m+", &nc_ctx->mp);
75886 DUK__BI_PRINT("m-", &nc_ctx->mm);
75887
75888 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
75889 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
75890 DUK_DDD(DUK_DDDPRINT("k is too low"));
75891 /* r <- r
75892 * s <- (* s B)
75893 * m+ <- m+
75894 * m- <- m-
75895 * k <- (+ k 1)
75896 */
75897
75898 duk__bi_mul_small_copy(&nc_ctx->s, nc_ctx->B, &nc_ctx->t1);
75899 k++;
75900 } else {
75901 break;
75902 }
75903 }
75904
75905 /* k > 0 -> k was too low, and cannot be too high */
75906 if (k > 0) {
75907 goto skip_dec_k;
75908 }
75909
75910 for (;;) {
75911 DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
75912 DUK__BI_PRINT("r", &nc_ctx->r);
75913 DUK__BI_PRINT("s", &nc_ctx->s);
75914 DUK__BI_PRINT("m+", &nc_ctx->mp);
75915 DUK__BI_PRINT("m-", &nc_ctx->mm);
75916
75917 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
75918 duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, nc_ctx->B); /* t2 = (* (+ r m+) B) */
75919 if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
75920 DUK_DDD(DUK_DDDPRINT("k is too high"));
75921 /* r <- (* r B)
75922 * s <- s
75923 * m+ <- (* m+ B)
75924 * m- <- (* m- B)
75925 * k <- (- k 1)
75926 */
75927 duk__bi_mul_small_copy(&nc_ctx->r, nc_ctx->B, &nc_ctx->t1);
75928 duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t1);
75929 if (nc_ctx->unequal_gaps) {
75930 DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
75931 duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t1);
75932 }
75933 k--;
75934 } else {
75935 break;
75936 }
75938
75939 skip_dec_k:
75940
75941 if (!nc_ctx->unequal_gaps) {
75942 DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
75943 duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp); /* mm <- mp */
75944 }
75945 nc_ctx->k = k;
75946
75947 DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
75948 DUK__BI_PRINT("r(final)", &nc_ctx->r);
75949 DUK__BI_PRINT("s(final)", &nc_ctx->s);
75950 DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
75951 DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
75952}
75953
75955 duk_small_int_t tc1, tc2; /* terminating conditions */
75956 duk_small_int_t d; /* current digit */
75957 duk_small_int_t count = 0; /* digit count */
75958
75959 /*
75960 * Digit generation loop.
75961 *
75962 * Different termination conditions:
75963 *
75964 * 1. Free format output. Terminate when shortest accurate
75965 * representation found.
75966 *
75967 * 2. Fixed format output, with specific number of digits.
75968 * Ignore termination conditions, terminate when digits
75969 * generated. Caller requests an extra digit and rounds.
75970 *
75971 * 3. Fixed format output, with a specific absolute cut-off
75972 * position (e.g. 10 digits after decimal point). Note
75973 * that we always generate at least one digit, even if
75974 * the digit is below the cut-off point already.
75975 */
75976
75977 for (;;) {
75978 DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
75979 (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
75980 (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
75981 DUK__BI_PRINT("r", &nc_ctx->r);
75982 DUK__BI_PRINT("s", &nc_ctx->s);
75983 DUK__BI_PRINT("m+", &nc_ctx->mp);
75984 DUK__BI_PRINT("m-", &nc_ctx->mm);
75985
75986 /* (quotient-remainder (* r B) s) using a dummy subtraction loop */
75987 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, nc_ctx->B); /* t1 <- (* r B) */
75988 d = 0;
75989 for (;;) {
75990 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
75991 break;
75992 }
75993 duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2); /* t1 <- t1 - s */
75994 d++;
75995 }
75996 duk__bi_copy(&nc_ctx->r, &nc_ctx->t1); /* r <- (remainder (* r B) s) */
75997 /* d <- (quotient (* r B) s) (in range 0...B-1) */
75998 DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
75999 DUK__BI_PRINT("r(rem)", &nc_ctx->r);
76000
76001 duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
76002 duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
76003 DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
76004 DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
76005
76006 /* Terminating conditions. For fixed width output, we just ignore the
76007 * terminating conditions (and pretend that tc1 == tc2 == false). The
76008 * the current shortcut for fixed-format output is to generate a few
76009 * extra digits and use rounding (with carry) to finish the output.
76010 */
76011
76012 if (nc_ctx->is_fixed == 0) {
76013 /* free-form */
76014 tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
76015
76016 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 <- (+ r m+) */
76017 tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
76018
76019 DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
76020 } else {
76021 /* fixed-format */
76022 tc1 = 0;
76023 tc2 = 0;
76024 }
76025
76026 /* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
76027 * on purpose, which is taken into account by the macro.
76028 */
76029 count++;
76030
76031 if (tc1) {
76032 if (tc2) {
76033 /* tc1 = true, tc2 = true */
76034 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
76035 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) { /* (< (* r 2) s) */
76036 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
76037 (long) d, (long) nc_ctx->k));
76038 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76039 } else {
76040 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
76041 (long) (d + 1), (long) nc_ctx->k));
76042 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
76043 }
76044 break;
76045 } else {
76046 /* tc1 = true, tc2 = false */
76047 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
76048 (long) d, (long) nc_ctx->k));
76049 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76050 break;
76051 }
76052 } else {
76053 if (tc2) {
76054 /* tc1 = false, tc2 = true */
76055 DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
76056 (long) (d + 1), (long) nc_ctx->k));
76057 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
76058 break;
76059 } else {
76060 /* tc1 = false, tc2 = false */
76061 DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
76062 (long) d, (long) nc_ctx->k));
76063 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76064
76065 /* r <- r (updated above: r <- (remainder (* r B) s)
76066 * s <- s
76067 * m+ <- m+ (updated above: m+ <- (* m+ B)
76068 * m- <- m- (updated above: m- <- (* m- B)
76069 * B, low_ok, high_ok are fixed
76070 */
76071
76072 /* fall through and continue for-loop */
76073 }
76074 }
76075
76076 /* fixed-format termination conditions */
76077 if (nc_ctx->is_fixed) {
76078 if (nc_ctx->abs_pos) {
76079 int pos = nc_ctx->k - count + 1; /* count is already incremented, take into account */
76080 DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
76081 (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
76082 if (pos <= nc_ctx->req_digits) {
76083 DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
76084 break;
76085 }
76086 } else {
76087 DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
76088 (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
76089 if (count >= nc_ctx->req_digits) {
76090 DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
76091 break;
76092 }
76093 }
76094 }
76095 } /* for */
76096
76097 nc_ctx->count = count;
76098
76099 DUK_DDD(DUK_DDDPRINT("generate finished"));
76100
76101#ifdef DUK_USE_DDDPRINT
76102 {
76103 duk_uint8_t buf[2048];
76104 duk_small_int_t i, t;
76105 DUK_MEMZERO(buf, sizeof(buf));
76106 for (i = 0; i < nc_ctx->count; i++) {
76107 t = nc_ctx->digits[i];
76108 if (t < 0 || t > 36) {
76109 buf[i] = (duk_uint8_t) '?';
76110 } else {
76111 buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
76113 }
76114 DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
76115 (long) nc_ctx->k, (const char *) buf));
76116 }
76117#endif
76118}
76119
76120/* Round up digits to a given position. If position is out-of-bounds,
76121 * does nothing. If carry propagates over the first digit, a '1' is
76122 * prepended to digits and 'k' will be updated. Return value indicates
76123 * whether carry propagated over the first digit.
76124 *
76125 * Note that nc_ctx->count is NOT updated based on the rounding position
76126 * (it is updated only if carry overflows over the first digit and an
76127 * extra digit is prepended).
76128 */
76131 duk_uint8_t *p;
76132 duk_uint8_t roundup_limit;
76133 duk_small_int_t ret = 0;
76134
76135 /*
76136 * round_idx points to the digit which is considered for rounding; the
76137 * digit to its left is the final digit of the rounded value. If round_idx
76138 * is zero, rounding will be performed; the result will either be an empty
76139 * rounded value or if carry happens a '1' digit is generated.
76140 */
76141
76142 if (round_idx >= nc_ctx->count) {
76143 DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
76144 (long) round_idx, (long) nc_ctx->count));
76145 return 0;
76146 } else if (round_idx < 0) {
76147 DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
76148 (long) round_idx));
76149 return 0;
76150 }
76151
76152 /*
76153 * Round-up limit.
76154 *
76155 * For even values, divides evenly, e.g. 10 -> roundup_limit=5.
76156 *
76157 * For odd values, rounds up, e.g. 3 -> roundup_limit=2.
76158 * If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
76159 */
76160 roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
76161
76162 p = &nc_ctx->digits[round_idx];
76163 if (*p >= roundup_limit) {
76164 DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
76165 /* carry */
76166 for (;;) {
76167 *p = 0;
76168 if (p == &nc_ctx->digits[0]) {
76169 DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
76170 DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
76171 (const void *) (&nc_ctx->digits[0]),
76172 (size_t) (sizeof(char) * nc_ctx->count));
76173 nc_ctx->digits[0] = 1; /* don't increase 'count' */
76174 nc_ctx->k++; /* position of highest digit changed */
76175 nc_ctx->count++; /* number of digits changed */
76176 ret = 1;
76177 break;
76178 }
76179
76180 DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
76181 (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
76182 p--;
76183 t = *p;
76184 DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
76185 if (++t < nc_ctx->B) {
76186 DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
76187 *p = (duk_uint8_t) t;
76188 break;
76189 }
76190
76191 DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
76192 }
76193 }
76194
76195 return ret;
76196}
76197
76198#define DUK__NO_EXP (65536) /* arbitrary marker, outside valid exp range */
76199
76201 duk_context *ctx,
76202 duk_small_int_t radix,
76203 duk_small_int_t digits,
76204 duk_small_uint_t flags,
76205 duk_small_int_t neg) {
76207 duk_small_int_t pos, pos_end;
76208 duk_small_int_t expt;
76209 duk_small_int_t dig;
76210 duk_uint8_t *q;
76211 duk_uint8_t *buf;
76212
76213 /*
76214 * The string conversion here incorporates all the necessary Ecmascript
76215 * semantics without attempting to be generic. nc_ctx->digits contains
76216 * nc_ctx->count digits (>= 1), with the topmost digit's 'position'
76217 * indicated by nc_ctx->k as follows:
76218 *
76219 * digits="123" count=3 k=0 --> 0.123
76220 * digits="123" count=3 k=1 --> 1.23
76221 * digits="123" count=3 k=5 --> 12300
76222 * digits="123" count=3 k=-1 --> 0.0123
76223 *
76224 * Note that the identifier names used for format selection are different
76225 * in Burger-Dybvig paper and Ecmascript specification (quite confusingly
76226 * so, because e.g. 'k' has a totally different meaning in each). See
76227 * documentation for discussion.
76228 *
76229 * Ecmascript doesn't specify any specific behavior for format selection
76230 * (e.g. when to use exponent notation) for non-base-10 numbers.
76231 *
76232 * The bigint space in the context is reused for string output, as there
76233 * is more than enough space for that (>1kB at the moment), and we avoid
76234 * allocating even more stack.
76235 */
76236
76238 DUK_ASSERT(nc_ctx->count >= 1);
76239
76240 k = nc_ctx->k;
76241 buf = (duk_uint8_t *) &nc_ctx->f; /* XXX: union would be more correct */
76242 q = buf;
76243
76244 /* Exponent handling: if exponent format is used, record exponent value and
76245 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
76246 *
76247 * toFixed() prevents exponent use; otherwise apply a set of criteria to
76248 * match the other API calls (toString(), toPrecision, etc).
76249 */
76250
76251 expt = DUK__NO_EXP;
76252 if (!nc_ctx->abs_pos /* toFixed() */) {
76253 if ((flags & DUK_N2S_FLAG_FORCE_EXP) || /* exponential notation forced */
76254 ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) && /* fixed precision and zero padding would be required */
76255 (k - digits >= 1)) || /* (e.g. k=3, digits=2 -> "12X") */
76256 ((k > 21 || k <= -6) && (radix == 10))) { /* toString() conditions */
76257 DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
76258 (long) k, (long) (k - 1)));
76259 expt = k - 1; /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
76260 k = 1; /* generate mantissa with a single leading whole number digit */
76261 }
76262 }
76263
76264 if (neg) {
76265 *q++ = '-';
76266 }
76267
76268 /* Start position (inclusive) and end position (exclusive) */
76269 pos = (k >= 1 ? k : 1);
76270 if (nc_ctx->is_fixed) {
76271 if (nc_ctx->abs_pos) {
76272 /* toFixed() */
76273 pos_end = -digits;
76274 } else {
76275 pos_end = k - digits;
76276 }
76277 } else {
76278 pos_end = k - nc_ctx->count;
76279 }
76280 if (pos_end > 0) {
76281 pos_end = 0;
76282 }
76283
76284 DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
76285 "digits=%ld, abs_pos=%ld",
76286 (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
76287 (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
76288
76289 /* Digit generation */
76290 while (pos > pos_end) {
76291 DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
76292 (long) pos, (long) pos_end));
76293 if (pos == 0) {
76294 *q++ = (duk_uint8_t) '.';
76295 }
76296 if (pos > k) {
76297 *q++ = (duk_uint8_t) '0';
76298 } else if (pos <= k - nc_ctx->count) {
76299 *q++ = (duk_uint8_t) '0';
76300 } else {
76301 dig = nc_ctx->digits[k - pos];
76302 DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
76303 *q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
76304 }
76305
76306 pos--;
76307 }
76308 DUK_ASSERT(pos <= 1);
76309
76310 /* Exponent */
76311 if (expt != DUK__NO_EXP) {
76312 /*
76313 * Exponent notation for non-base-10 numbers isn't specified in Ecmascript
76314 * specification, as it never explicitly turns up: non-decimal numbers can
76315 * only be formatted with Number.prototype.toString([radix]) and for that,
76316 * behavior is not explicitly specified.
76317 *
76318 * Logical choices include formatting the exponent as decimal (e.g. binary
76319 * 100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
76320 * The Dragon4 algorithm (in the original paper) prints the exponent value
76321 * in the target radix B. However, for radix values 15 and above, the
76322 * exponent separator 'e' is no longer easily parseable. Consider, for
76323 * instance, the number "1.faecee+1c".
76324 */
76325
76326 duk_size_t len;
76327 char expt_sign;
76328
76329 *q++ = 'e';
76330 if (expt >= 0) {
76331 expt_sign = '+';
76332 } else {
76333 expt_sign = '-';
76334 expt = -expt;
76335 }
76336 *q++ = (duk_uint8_t) expt_sign;
76337 len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
76338 q += len;
76339 }
76340
76341 duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
76342}
76343
76344/*
76345 * Conversion helpers
76346 */
76347
76350 duk_uint32_t tmp;
76351 duk_small_int_t expt;
76352
76353 /*
76354 * seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
76355 * A B C D E F G H
76356 *
76357 * s sign bit
76358 * eee... exponent field
76359 * fff... fraction
76360 *
76361 * ieee value = 1.ffff... * 2^(e - 1023) (normal)
76362 * = 0.ffff... * 2^(-1022) (denormal)
76363 *
76364 * algorithm v = f * b^e
76365 */
76366
76368
76369 nc_ctx->f.n = 2;
76370
76371 tmp = DUK_DBLUNION_GET_LOW32(&u);
76372 nc_ctx->f.v[0] = tmp;
76373 tmp = DUK_DBLUNION_GET_HIGH32(&u);
76374 nc_ctx->f.v[1] = tmp & 0x000fffffUL;
76375 expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
76377 if (expt == 0) {
76378 /* denormal */
76379 expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
76380 duk__bi_normalize(&nc_ctx->f);
76381 } else {
76382 /* normal: implicit leading 1-bit */
76383 nc_ctx->f.v[1] |= 0x00100000UL;
76384 expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
76385 DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f)); /* true, because v[1] has at least one bit set */
76386 }
76387
76388 DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
76389
76390 nc_ctx->e = expt;
76391}
76392
76395 duk_small_int_t expt;
76397 duk_small_int_t bitstart;
76398 duk_small_int_t bitround;
76399 duk_small_int_t bitidx;
76400 duk_small_int_t skip_round;
76401 duk_uint32_t t, v;
76402
76403 DUK_ASSERT(nc_ctx->count == 53 + 1);
76404
76405 /* Sometimes this assert is not true right now; it will be true after
76406 * rounding. See: test-bug-numconv-mantissa-assert.js.
76407 */
76408 DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1); /* zero handled by caller */
76409
76410 /* Should not be required because the code below always sets both high
76411 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
76412 * (perhaps because the low part is set (seemingly) conditionally in a
76413 * loop), so this is here to avoid the bogus warning.
76414 */
76415 DUK_MEMZERO((void *) &u, sizeof(u));
76416
76417 /*
76418 * Figure out how generated digits match up with the mantissa,
76419 * and then perform rounding. If mantissa overflows, need to
76420 * recompute the exponent (it is bumped and may overflow to
76421 * infinity).
76422 *
76423 * For normal numbers the leading '1' is hidden and ignored,
76424 * and the last bit is used for rounding:
76425 *
76426 * rounding pt
76427 * <--------52------->|
76428 * 1 x x x x ... x x x x|y ==> x x x x ... x x x x
76429 *
76430 * For denormals, the leading '1' is included in the number,
76431 * and the rounding point is different:
76432 *
76433 * rounding pt
76434 * <--52 or less--->|
76435 * 1 x x x x ... x x|x x y ==> 0 0 ... 1 x x ... x x
76436 *
76437 * The largest denormals will have a mantissa beginning with
76438 * a '1' (the explicit leading bit); smaller denormals will
76439 * have leading zero bits.
76440 *
76441 * If the exponent would become too high, the result becomes
76442 * Infinity. If the exponent is so small that the entire
76443 * mantissa becomes zero, the result becomes zero.
76444 *
76445 * Note: the Dragon4 'k' is off-by-one with respect to the IEEE
76446 * exponent. For instance, k==0 indicates that the leading '1'
76447 * digit is at the first binary fraction position (0.1xxx...);
76448 * the corresponding IEEE exponent would be -1.
76449 */
76450
76451 skip_round = 0;
76452
76453 recheck_exp:
76454
76455 expt = nc_ctx->k - 1; /* IEEE exp without bias */
76456 if (expt > 1023) {
76457 /* Infinity */
76458 bitstart = -255; /* needed for inf: causes mantissa to become zero,
76459 * and rounding to be skipped.
76460 */
76461 expt = 2047;
76462 } else if (expt >= -1022) {
76463 /* normal */
76464 bitstart = 1; /* skip leading digit */
76466 DUK_ASSERT(expt >= 1 && expt <= 2046);
76467 } else {
76468 /* denormal or zero */
76469 bitstart = 1023 + expt; /* expt==-1023 -> bitstart=0 (leading 1);
76470 * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
76471 */
76472 expt = 0;
76473 }
76474 bitround = bitstart + 52;
76475
76476 DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
76477 (long) expt, (long) bitstart, (long) bitround));
76478
76479 if (!skip_round) {
76480 if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
76481 /* Corner case: see test-numconv-parse-mant-carry.js. We could
76482 * just bump the exponent and update bitstart, but it's more robust
76483 * to recompute (but avoid rounding twice).
76484 */
76485 DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
76486 skip_round = 1;
76487 goto recheck_exp;
76488 }
76489 }
76490
76491 /*
76492 * Create mantissa
76493 */
76494
76495 t = 0;
76496 for (i = 0; i < 52; i++) {
76497 bitidx = bitstart + 52 - 1 - i;
76498 if (bitidx >= nc_ctx->count) {
76499 v = 0;
76500 } else if (bitidx < 0) {
76501 v = 0;
76502 } else {
76503 v = nc_ctx->digits[bitidx];
76504 }
76505 DUK_ASSERT(v == 0 || v == 1);
76506 t += v << (i % 32);
76507 if (i == 31) {
76508 /* low 32 bits is complete */
76510 t = 0;
76511 }
76512 }
76513 /* t has high mantissa */
76514
76515 DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
76516 (unsigned long) t,
76517 (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
76518
76519 DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
76520 t += expt << 20;
76521#if 0 /* caller handles sign change */
76522 if (negative) {
76523 t |= 0x80000000U;
76524 }
76525#endif
76527
76528 DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
76529 (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
76530 (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
76531
76532 *x = DUK_DBLUNION_GET_DOUBLE(&u);
76533}
76534
76535/*
76536 * Exposed number-to-string API
76537 *
76538 * Input: [ number ]
76539 * Output: [ string ]
76540 */
76541
76543 duk_double_t x;
76545 duk_small_int_t neg;
76546 duk_uint32_t uval;
76547 duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
76548 duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
76549
76550 x = (duk_double_t) duk_require_number(ctx, -1);
76551 duk_pop(ctx);
76552
76553 /*
76554 * Handle special cases (NaN, infinity, zero).
76555 */
76556
76558 if (DUK_SIGNBIT((double) x)) {
76559 x = -x;
76560 neg = 1;
76561 } else {
76562 neg = 0;
76563 }
76564
76565 /* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
76566 DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
76567
76568 if (c == DUK_FP_NAN) {
76570 return;
76571 } else if (c == DUK_FP_INFINITE) {
76572 if (neg) {
76573 /* -Infinity */
76575 } else {
76576 /* Infinity */
76578 }
76579 return;
76580 } else if (c == DUK_FP_ZERO) {
76581 /* We can't shortcut zero here if it goes through special formatting
76582 * (such as forced exponential notation).
76583 */
76584 ;
76585 }
76586
76587 /*
76588 * Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
76589 * specially, as they're very likely for embedded programs. This
76590 * is now done for all radix values. We must be careful not to use
76591 * the fast path when special formatting (e.g. forced exponential)
76592 * is in force.
76593 *
76594 * XXX: could save space by supporting radix 10 only and using
76595 * sprintf "%lu" for the fast path and for exponent formatting.
76596 */
76597
76598 uval = (unsigned int) x;
76599 if (((double) uval) == x && /* integer number in range */
76600 flags == 0) { /* no special formatting */
76601 /* use bigint area as a temp */
76602 duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
76603 duk_uint8_t *p = buf;
76604
76605 DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1); /* max size: radix=2 + sign */
76606 if (neg && uval != 0) {
76607 /* no negative sign for zero */
76608 *p++ = (duk_uint8_t) '-';
76609 }
76610 p += duk__dragon4_format_uint32(p, uval, radix);
76611 duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (p - buf));
76612 return;
76613 }
76614
76615 /*
76616 * Dragon4 setup.
76617 *
76618 * Convert double from IEEE representation for conversion;
76619 * normal finite values have an implicit leading 1-bit. The
76620 * slow path algorithm doesn't handle zero, so zero is special
76621 * cased here but still creates a valid nc_ctx, and goes
76622 * through normal formatting in case special formatting has
76623 * been requested (e.g. forced exponential format: 0 -> "0e+0").
76624 */
76625
76626 /* Would be nice to bulk clear the allocation, but the context
76627 * is 1-2 kilobytes and nothing should rely on it being zeroed.
76628 */
76629#if 0
76630 DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */
76631#endif
76632
76633 nc_ctx->is_s2n = 0;
76634 nc_ctx->b = 2;
76635 nc_ctx->B = radix;
76636 nc_ctx->abs_pos = 0;
76637 if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
76638 nc_ctx->is_fixed = 1;
76639 if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
76640 /* absolute req_digits; e.g. digits = 1 -> last digit is 0,
76641 * but add an extra digit for rounding.
76642 */
76643 nc_ctx->abs_pos = 1;
76644 nc_ctx->req_digits = (-digits + 1) - 1;
76645 } else {
76646 nc_ctx->req_digits = digits + 1;
76647 }
76648 } else {
76649 nc_ctx->is_fixed = 0;
76650 nc_ctx->req_digits = 0;
76651 }
76652
76653 if (c == DUK_FP_ZERO) {
76654 /* Zero special case: fake requested number of zero digits; ensure
76655 * no sign bit is printed. Relative and absolute fixed format
76656 * require separate handling.
76657 */
76658 duk_small_int_t count;
76659 if (nc_ctx->is_fixed) {
76660 if (nc_ctx->abs_pos) {
76661 count = digits + 2; /* lead zero + 'digits' fractions + 1 for rounding */
76662 } else {
76663 count = digits + 1; /* + 1 for rounding */
76664 }
76665 } else {
76666 count = 1;
76667 }
76668 DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
76669 DUK_ASSERT(count >= 1);
76670 DUK_MEMZERO((void *) nc_ctx->digits, count);
76671 nc_ctx->count = count;
76672 nc_ctx->k = 1; /* 0.000... */
76673 neg = 0;
76674 goto zero_skip;
76675 }
76676
76677 duk__dragon4_double_to_ctx(nc_ctx, x); /* -> sets 'f' and 'e' */
76678 DUK__BI_PRINT("f", &nc_ctx->f);
76679 DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
76680
76681 /*
76682 * Dragon4 slow path digit generation.
76683 */
76684
76685 duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
76686
76687 DUK_DDD(DUK_DDDPRINT("after prepare:"));
76688 DUK__BI_PRINT("r", &nc_ctx->r);
76689 DUK__BI_PRINT("s", &nc_ctx->s);
76690 DUK__BI_PRINT("mp", &nc_ctx->mp);
76691 DUK__BI_PRINT("mm", &nc_ctx->mm);
76692
76693 duk__dragon4_scale(nc_ctx);
76694
76695 DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
76696 DUK__BI_PRINT("r", &nc_ctx->r);
76697 DUK__BI_PRINT("s", &nc_ctx->s);
76698 DUK__BI_PRINT("mp", &nc_ctx->mp);
76699 DUK__BI_PRINT("mm", &nc_ctx->mm);
76700
76701 duk__dragon4_generate(nc_ctx);
76702
76703 /*
76704 * Convert and push final string.
76705 */
76706
76707 zero_skip:
76708
76709 if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
76710 /* Perform fixed-format rounding. */
76711 duk_small_int_t roundpos;
76712 if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
76713 /* 'roundpos' is relative to nc_ctx->k and increases to the right
76714 * (opposite of how 'k' changes).
76715 */
76716 roundpos = -digits; /* absolute position for digit considered for rounding */
76717 roundpos = nc_ctx->k - roundpos;
76718 } else {
76719 roundpos = digits;
76720 }
76721 DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
76722 (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
76723 (void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
76724
76725 /* Note: 'count' is currently not adjusted by rounding (i.e. the
76726 * digits are not "chopped off". That shouldn't matter because
76727 * the digit position (absolute or relative) is passed on to the
76728 * convert-and-push function.
76729 */
76730 }
76731
76732 duk__dragon4_convert_and_push(nc_ctx, ctx, radix, digits, flags, neg);
76733}
76734
76735/*
76736 * Exposed string-to-number API
76737 *
76738 * Input: [ string ]
76739 * Output: [ number ]
76740 *
76741 * If number parsing fails, a NaN is pushed as the result. If number parsing
76742 * fails due to an internal error, an InternalError is thrown.
76743 */
76744
76746 duk_hthread *thr = (duk_hthread *) ctx;
76747 duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
76748 duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
76749 duk_double_t res;
76750 duk_hstring *h_str;
76751 duk_small_int_t expt;
76752 duk_small_int_t expt_neg;
76753 duk_small_int_t expt_adj;
76754 duk_small_int_t neg;
76755 duk_small_int_t dig;
76756 duk_small_int_t dig_whole;
76757 duk_small_int_t dig_lzero;
76758 duk_small_int_t dig_frac;
76759 duk_small_int_t dig_expt;
76760 duk_small_int_t dig_prec;
76761 const duk__exp_limits *explim;
76762 const duk_uint8_t *p;
76763 duk_small_int_t ch;
76764
76765 /* This seems to waste a lot of stack frame entries, but good compilers
76766 * will compute these as needed below. Some of these initial flags are
76767 * also modified in the code below, so they can't all be removed.
76768 */
76769 duk_small_int_t trim_white = (flags & DUK_S2N_FLAG_TRIM_WHITE);
76770 duk_small_int_t allow_expt = (flags & DUK_S2N_FLAG_ALLOW_EXP);
76771 duk_small_int_t allow_garbage = (flags & DUK_S2N_FLAG_ALLOW_GARBAGE);
76772 duk_small_int_t allow_plus = (flags & DUK_S2N_FLAG_ALLOW_PLUS);
76773 duk_small_int_t allow_minus = (flags & DUK_S2N_FLAG_ALLOW_MINUS);
76774 duk_small_int_t allow_infinity = (flags & DUK_S2N_FLAG_ALLOW_INF);
76775 duk_small_int_t allow_frac = (flags & DUK_S2N_FLAG_ALLOW_FRAC);
76776 duk_small_int_t allow_naked_frac = (flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC);
76777 duk_small_int_t allow_empty_frac = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC);
76778 duk_small_int_t allow_empty = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
76779 duk_small_int_t allow_leading_zero = (flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO);
76780 duk_small_int_t allow_auto_hex_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT);
76781 duk_small_int_t allow_auto_oct_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT);
76782
76783 DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
76784 (duk_tval *) duk_get_tval(ctx, -1),
76785 (long) radix, (unsigned long) flags));
76786
76787 DUK_ASSERT(radix >= 2 && radix <= 36);
76789
76790 /*
76791 * Preliminaries: trim, sign, Infinity check
76792 *
76793 * We rely on the interned string having a NUL terminator, which will
76794 * cause a parse failure wherever it is encountered. As a result, we
76795 * don't need separate pointer checks.
76796 *
76797 * There is no special parsing for 'NaN' in the specification although
76798 * 'Infinity' (with an optional sign) is allowed in some contexts.
76799 * Some contexts allow plus/minus sign, while others only allow the
76800 * minus sign (like JSON.parse()).
76801 *
76802 * Automatic hex number detection (leading '0x' or '0X') and octal
76803 * number detection (leading '0' followed by at least one octal digit)
76804 * is done here too.
76805 */
76806
76807 if (trim_white) {
76808 /* Leading / trailing whitespace is sometimes accepted and
76809 * sometimes not. After white space trimming, all valid input
76810 * characters are pure ASCII.
76811 */
76812 duk_trim(ctx, -1);
76813 }
76814 h_str = duk_require_hstring(ctx, -1);
76815 DUK_ASSERT(h_str != NULL);
76816 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
76817
76818 neg = 0;
76819 ch = *p;
76820 if (ch == (duk_small_int_t) '+') {
76821 if (!allow_plus) {
76822 DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
76823 goto parse_fail;
76824 }
76825 p++;
76826 } else if (ch == (duk_small_int_t) '-') {
76827 if (!allow_minus) {
76828 DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
76829 goto parse_fail;
76830 }
76831 p++;
76832 neg = 1;
76833 }
76834
76835 ch = *p;
76836 if (allow_infinity && ch == (duk_small_int_t) 'I') {
76837 /* Don't check for Infinity unless the context allows it.
76838 * 'Infinity' is a valid integer literal in e.g. base-36:
76839 *
76840 * parseInt('Infinity', 36)
76841 * 1461559270678
76842 */
76843
76844 const duk_uint8_t *q;
76845
76846 /* borrow literal Infinity from builtin string */
76847 q = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(DUK_HTHREAD_STRING_INFINITY(thr));
76848 if (DUK_STRNCMP((const char *) p, (const char *) q, 8) == 0) {
76849 if (!allow_garbage && (p[8] != (duk_uint8_t) 0)) {
76850 DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
76851 goto parse_fail;
76852 } else {
76853 res = DUK_DOUBLE_INFINITY;
76854 goto negcheck_and_ret;
76855 }
76856 }
76857 }
76858 if (ch == (duk_small_int_t) '0') {
76859 duk_small_int_t detect_radix = 0;
76860 ch = p[1];
76861 if (allow_auto_hex_int && (ch == (duk_small_int_t) 'x' || ch == (duk_small_int_t) 'X')) {
76862 DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
76863 detect_radix = 16;
76864 allow_empty = 0; /* interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
76865 p += 2;
76866 } else if (allow_auto_oct_int && (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
76867 DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
76868 detect_radix = 8;
76869 allow_empty = 1; /* interpret e.g. '09' as '0', not NaN */
76870 p += 1;
76871 }
76872 if (detect_radix > 0) {
76873 radix = detect_radix;
76874 allow_expt = 0;
76875 allow_frac = 0;
76876 allow_naked_frac = 0;
76877 allow_empty_frac = 0;
76878 allow_leading_zero = 1; /* allow e.g. '0x0009' and '00077' */
76879 }
76880 }
76881
76882 /*
76883 * Scan number and setup for Dragon4.
76884 *
76885 * The fast path case is detected during setup: an integer which
76886 * can be converted without rounding, no net exponent. The fast
76887 * path could be implemented as a separate scan, but may not really
76888 * be worth it: the multiplications for building 'f' are not
76889 * expensive when 'f' is small.
76890 *
76891 * The significand ('f') must contain enough bits of (apparent)
76892 * accuracy, so that Dragon4 will generate enough binary output digits.
76893 * For decimal numbers, this means generating a 20-digit significand,
76894 * which should yield enough practical accuracy to parse IEEE doubles.
76895 * In fact, the Ecmascript specification explicitly allows an
76896 * implementation to treat digits beyond 20 as zeroes (and even
76897 * to round the 20th digit upwards). For non-decimal numbers, the
76898 * appropriate number of digits has been precomputed for comparable
76899 * accuracy.
76900 *
76901 * Digit counts:
76902 *
76903 * [ dig_lzero ]
76904 * |
76905 * .+-..---[ dig_prec ]----.
76906 * | || |
76907 * 0000123.456789012345678901234567890e+123456
76908 * | | | | | |
76909 * `--+--' `------[ dig_frac ]-------' `-+--'
76910 * | |
76911 * [ dig_whole ] [ dig_expt ]
76912 *
76913 * dig_frac and dig_expt are -1 if not present
76914 * dig_lzero is only computed for whole number part
76915 *
76916 * Parsing state
76917 *
76918 * Parsing whole part dig_frac < 0 AND dig_expt < 0
76919 * Parsing fraction part dig_frac >= 0 AND dig_expt < 0
76920 * Parsing exponent part dig_expt >= 0 (dig_frac may be < 0 or >= 0)
76921 *
76922 * Note: in case we hit an implementation limit (like exponent range),
76923 * we should throw an error, NOT return NaN or Infinity. Even with
76924 * very large exponent (or significand) values the final result may be
76925 * finite, so NaN/Infinity would be incorrect.
76926 */
76927
76928 duk__bi_set_small(&nc_ctx->f, 0);
76929 dig_prec = 0;
76930 dig_lzero = 0;
76931 dig_whole = 0;
76932 dig_frac = -1;
76933 dig_expt = -1;
76934 expt = 0;
76935 expt_adj = 0; /* essentially tracks digit position of lowest 'f' digit */
76936 expt_neg = 0;
76937 for (;;) {
76938 ch = *p++;
76939
76940 DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
76941 "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
76942 (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
76943 (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
76944 (long) dig_expt, (long) dig_lzero, (long) dig_prec));
76945 DUK__BI_PRINT("f", &nc_ctx->f);
76946
76947 /* Most common cases first. */
76948 if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
76949 dig = (int) ch - '0' + 0;
76950 } else if (ch == (duk_small_int_t) '.') {
76951 /* A leading digit is not required in some cases, e.g. accept ".123".
76952 * In other cases (JSON.parse()) a leading digit is required. This
76953 * is checked for after the loop.
76954 */
76955 if (dig_frac >= 0 || dig_expt >= 0) {
76956 if (allow_garbage) {
76957 DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
76958 break;
76959 } else {
76960 DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
76961 goto parse_fail;
76962 }
76963 }
76964
76965 if (!allow_frac) {
76966 /* Some contexts don't allow fractions at all; this can't be a
76967 * post-check because the state ('f' and expt) would be incorrect.
76968 */
76969 if (allow_garbage) {
76970 DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
76971 break;
76972 } else {
76973 DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
76974 }
76975 }
76976
76977 DUK_DDD(DUK_DDDPRINT("start fraction part"));
76978 dig_frac = 0;
76979 continue;
76980 } else if (ch == (duk_small_int_t) 0) {
76981 DUK_DDD(DUK_DDDPRINT("NUL termination"));
76982 break;
76983 } else if (allow_expt && dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
76984 /* Note: we don't parse back exponent notation for anything else
76985 * than radix 10, so this is not an ambiguous check (e.g. hex
76986 * exponent values may have 'e' either as a significand digit
76987 * or as an exponent separator).
76988 *
76989 * If the exponent separator occurs twice, 'e' will be interpreted
76990 * as a digit (= 14) and will be rejected as an invalid decimal
76991 * digit.
76992 */
76993
76994 DUK_DDD(DUK_DDDPRINT("start exponent part"));
76995
76996 /* Exponent without a sign or with a +/- sign is accepted
76997 * by all call sites (even JSON.parse()).
76998 */
76999 ch = *p;
77000 if (ch == (duk_small_int_t) '-') {
77001 expt_neg = 1;
77002 p++;
77003 } else if (ch == (duk_small_int_t) '+') {
77004 p++;
77005 }
77006 dig_expt = 0;
77007 continue;
77008 } else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
77009 dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
77010 } else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
77011 dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
77012 } else {
77013 dig = 255; /* triggers garbage digit check below */
77014 }
77015 DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
77016
77017 if (dig >= radix) {
77018 if (allow_garbage) {
77019 DUK_DDD(DUK_DDDPRINT("garbage termination"));
77020 break;
77021 } else {
77022 DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
77023 goto parse_fail;
77024 }
77025 }
77026
77027 if (dig_expt < 0) {
77028 /* whole or fraction digit */
77029
77030 if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
77031 /* significant from precision perspective */
77032
77033 duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
77034 if (f_zero && dig == 0) {
77035 /* Leading zero is not counted towards precision digits; not
77036 * in the integer part, nor in the fraction part.
77037 */
77038 if (dig_frac < 0) {
77039 dig_lzero++;
77040 }
77041 } else {
77042 /* XXX: join these ops (multiply-accumulate), but only if
77043 * code footprint decreases.
77044 */
77045 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, radix);
77046 duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, dig);
77047 dig_prec++;
77048 }
77049 } else {
77050 /* Ignore digits beyond a radix-specific limit, but note them
77051 * in expt_adj.
77052 */
77053 expt_adj++;
77054 }
77055
77056 if (dig_frac >= 0) {
77057 dig_frac++;
77058 expt_adj--;
77059 } else {
77060 dig_whole++;
77061 }
77062 } else {
77063 /* exponent digit */
77064
77065 expt = expt * radix + dig;
77066 if (expt > DUK_S2N_MAX_EXPONENT) {
77067 /* impose a reasonable exponent limit, so that exp
77068 * doesn't need to get tracked using a bigint.
77069 */
77070 DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
77071 goto parse_explimit_error;
77072 }
77073 dig_expt++;
77074 }
77075 }
77076
77077 /* Leading zero. */
77078
77079 if (dig_lzero > 0 && dig_whole > 1) {
77080 if (!allow_leading_zero) {
77081 DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
77082 goto parse_fail;
77083 }
77084 }
77085
77086 /* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
77087
77088 if (dig_whole == 0) {
77089 if (dig_frac == 0) {
77090 /* "." is not accepted in any format */
77091 DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
77092 goto parse_fail;
77093 } else if (dig_frac > 0) {
77094 /* ".123" */
77095 if (!allow_naked_frac) {
77096 DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
77097 "leading integer digit(s)"));
77098 goto parse_fail;
77099 }
77100 } else {
77101 /* empty ("") is allowed in some formats (e.g. Number(''), as zero */
77102 if (!allow_empty) {
77103 DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
77104 goto parse_fail;
77105 }
77106 }
77107 } else {
77108 if (dig_frac == 0) {
77109 /* "123." is allowed in some formats */
77110 if (!allow_empty_frac) {
77111 DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
77112 goto parse_fail;
77113 }
77114 } else if (dig_frac > 0) {
77115 /* "123.456" */
77116 ;
77117 } else {
77118 /* "123" */
77119 ;
77120 }
77121 }
77122
77123 /* Exponent without digits (e.g. "1e" or "1e+"). If trailing garbage is
77124 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
77125 */
77126
77127 if (dig_expt == 0) {
77128 if (!allow_garbage) {
77129 DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
77130 goto parse_fail;
77131 }
77132 DUK_ASSERT(expt == 0);
77133 }
77134
77135 if (expt_neg) {
77136 expt = -expt;
77137 }
77138 DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
77139 (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
77140 expt += expt_adj;
77141
77142 /* Fast path check. */
77143
77144 if (nc_ctx->f.n <= 1 && /* 32-bit value */
77145 expt == 0 /* no net exponent */) {
77146 /* Fast path is triggered for no exponent and also for balanced exponent
77147 * and fraction parts, e.g. for "1.23e2" == "123". Remember to respect
77148 * zero sign.
77149 */
77150
77151 /* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
77152 DUK_DDD(DUK_DDDPRINT("fast path number parse"));
77153 if (nc_ctx->f.n == 1) {
77154 res = (double) nc_ctx->f.v[0];
77155 } else {
77156 res = 0.0;
77157 }
77158 goto negcheck_and_ret;
77159 }
77160
77161 /* Significand ('f') padding. */
77162
77163 while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
77164 /* Pad significand with "virtual" zero digits so that Dragon4 will
77165 * have enough (apparent) precision to work with.
77166 */
77167 DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
77168 duk__bi_mul_small_copy(&nc_ctx->f, radix, &nc_ctx->t1);
77169 DUK__BI_PRINT("f", &nc_ctx->f);
77170 expt--;
77171 dig_prec++;
77172 }
77173
77174 DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
77175
77176 /* Detect zero special case. */
77177
77178 if (nc_ctx->f.n == 0) {
77179 /* This may happen even after the fast path check, if exponent is
77180 * not balanced (e.g. "0e1"). Remember to respect zero sign.
77181 */
77182 DUK_DDD(DUK_DDDPRINT("significand is zero"));
77183 res = 0.0;
77184 goto negcheck_and_ret;
77185 }
77186
77187
77188 /* Quick reject of too large or too small exponents. This check
77189 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
77190 * so zero check must be above.
77191 */
77192
77193 explim = &duk__str2num_exp_limits[radix - 2];
77194 if (expt > explim->upper) {
77195 DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
77197 goto negcheck_and_ret;
77198 } else if (expt < explim->lower) {
77199 DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
77200 res = (duk_double_t) 0.0;
77201 goto negcheck_and_ret;
77202 }
77203
77204 nc_ctx->is_s2n = 1;
77205 nc_ctx->e = expt;
77206 nc_ctx->b = radix;
77207 nc_ctx->B = 2;
77208 nc_ctx->is_fixed = 1;
77209 nc_ctx->abs_pos = 0;
77210 nc_ctx->req_digits = 53 + 1;
77211
77212 DUK__BI_PRINT("f", &nc_ctx->f);
77213 DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
77214
77215 /*
77216 * Dragon4 slow path (binary) digit generation.
77217 * An extra digit is generated for rounding.
77218 */
77219
77220 duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
77221
77222 DUK_DDD(DUK_DDDPRINT("after prepare:"));
77223 DUK__BI_PRINT("r", &nc_ctx->r);
77224 DUK__BI_PRINT("s", &nc_ctx->s);
77225 DUK__BI_PRINT("mp", &nc_ctx->mp);
77226 DUK__BI_PRINT("mm", &nc_ctx->mm);
77227
77228 duk__dragon4_scale(nc_ctx);
77229
77230 DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
77231 DUK__BI_PRINT("r", &nc_ctx->r);
77232 DUK__BI_PRINT("s", &nc_ctx->s);
77233 DUK__BI_PRINT("mp", &nc_ctx->mp);
77234 DUK__BI_PRINT("mm", &nc_ctx->mm);
77235
77236 duk__dragon4_generate(nc_ctx);
77237
77238 DUK_ASSERT(nc_ctx->count == 53 + 1);
77239
77240 /*
77241 * Convert binary digits into an IEEE double. Need to handle
77242 * denormals and rounding correctly.
77243 */
77244
77245 duk__dragon4_ctx_to_double(nc_ctx, &res);
77246 goto negcheck_and_ret;
77247
77248 negcheck_and_ret:
77249 if (neg) {
77250 res = -res;
77251 }
77252 duk_pop(ctx);
77253 duk_push_number(ctx, (double) res);
77254 DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
77255 return;
77256
77257 parse_fail:
77258 DUK_DDD(DUK_DDDPRINT("parse failed"));
77259 duk_pop(ctx);
77260 duk_push_nan(ctx);
77261 return;
77262
77263 parse_explimit_error:
77264 DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
77265 DUK_ERROR_RANGE(thr, "exponent too large");
77266 return;
77267}
77268/*
77269 * Regexp compilation.
77270 *
77271 * See doc/regexp.rst for a discussion of the compilation approach and
77272 * current limitations.
77273 *
77274 * Regexp bytecode assumes jumps can be expressed with signed 32-bit
77275 * integers. Consequently the bytecode size must not exceed 0x7fffffffL.
77276 * The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
77277 * in many places. Although this could be changed, the bytecode format
77278 * limit would still prevent regexps exceeding the signed 32-bit limit
77279 * from working.
77280 *
77281 * XXX: The implementation does not prevent bytecode from exceeding the
77282 * maximum supported size. This could be done by limiting the maximum
77283 * input string size (assuming an upper bound can be computed for number
77284 * of bytecode bytes emitted per input byte) or checking buffer maximum
77285 * size when emitting bytecode (slower).
77286 */
77287
77288/* include removed: duk_internal.h */
77290#ifdef DUK_USE_REGEXP_SUPPORT
77291
77292/*
77293 * Helper macros
77295
77296#define DUK__RE_INITIAL_BUFSIZE 64
77297
77298#undef DUK__RE_BUFLEN
77299#define DUK__RE_BUFLEN(re_ctx) \
77300 DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
77301
77302/*
77303 * Disjunction struct: result of parsing a disjunction
77304 */
77305
77306typedef struct {
77307 /* Number of characters that the atom matches (e.g. 3 for 'abc'),
77308 * -1 if atom is complex and number of matched characters either
77309 * varies or is not known.
77310 */
77311 duk_int32_t charlen;
77312
77313#if 0
77314 /* These are not needed to implement quantifier capture handling,
77315 * but might be needed at some point.
77316 */
77317
77318 /* re_ctx->captures at start and end of atom parsing.
77319 * Since 'captures' indicates highest capture number emitted
77320 * so far in a DUK_REOP_SAVE, the captures numbers saved by
77321 * the atom are: ]start_captures,end_captures].
77322 */
77323 duk_uint32_t start_captures;
77324 duk_uint32_t end_captures;
77325#endif
77327
77328/*
77329 * Encoding helpers
77330 *
77331 * Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
77332 * even though the buffer operations will use duk_size_t.
77333 */
77334
77335/* XXX: the insert helpers should ensure that the bytecode result is not
77336 * larger than expected (or at least assert for it). Many things in the
77337 * bytecode, like skip offsets, won't work correctly if the bytecode is
77338 * larger than say 2G.
77339 */
77340
77341DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
77342 if (x < 0) {
77343 return ((duk_uint32_t) (-x)) * 2 + 1;
77344 } else {
77345 return ((duk_uint32_t) x) * 2;
77346 }
77347}
77348
77349/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
77350 * maximum size.
77351 */
77352DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
77354 duk_small_int_t len;
77355
77357 DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len);
77358 return (duk_uint32_t) len;
77359}
77360
77361DUK_LOCAL duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
77362 duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
77363 duk_small_int_t len;
77366 DUK_BW_WRITE_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, buf, len);
77367 return (duk_uint32_t) len;
77368}
77369
77370DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
77371 return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
77373
77374#if 0 /* unused */
77375DUK_LOCAL duk_uint32_t duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
77377}
77378#endif
77379
77380/* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
77381DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
77382 /* Call sites don't need the result length so it's not accumulated. */
77383 while (count > 0) {
77384 (void) duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
77385 count--;
77386 }
77387}
77388
77389DUK_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) {
77390 DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
77391}
77392
77393DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
77394 DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
77395}
77396
77397DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
77398 DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
77399}
77400
77401/*
77402 * Insert a jump offset at 'offset' to complete an instruction
77403 * (the jump offset is always the last component of an instruction).
77404 * The 'skip' argument must be computed relative to 'offset',
77405 * -without- taking into account the skip field being inserted.
77406 *
77407 * ... A B C ins X Y Z ... (ins may be a JUMP, SPLIT1/SPLIT2, etc)
77408 * => ... A B C ins SKIP X Y Z
77409 *
77410 * Computing the final (adjusted) skip value, which is relative to the
77411 * first byte of the next instruction, is a bit tricky because of the
77412 * variable length UTF-8 encoding. See doc/regexp.rst for discussion.
77413 */
77414DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
77415 duk_small_int_t len;
77416
77417 /* XXX: solve into closed form (smaller code) */
77418
77419 if (skip < 0) {
77420 /* two encoding attempts suffices */
77422 len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
77423 DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len); /* no change */
77424 skip -= (duk_int32_t) len;
77425 }
77426 return duk__insert_i32(re_ctx, offset, skip);
77427}
77428
77429DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
77430 return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
77431}
77432
77433/*
77434 * duk_re_range_callback for generating character class ranges.
77436 * When ignoreCase is false, the range is simply emitted as is.
77437 * We don't, for instance, eliminate duplicates or overlapping
77438 * ranges in a character class.
77439 *
77440 * When ignoreCase is true, the range needs to be normalized through
77441 * canonicalization. Unfortunately a canonicalized version of a
77442 * continuous range is not necessarily continuous (e.g. [x-{] is
77443 * continuous but [X-{] is not). The current algorithm creates the
77444 * canonicalized range(s) space efficiently at the cost of compile
77445 * time execution time (see doc/regexp.rst for discussion).
77446 *
77447 * Note that the ctx->nranges is a context-wide temporary value
77448 * (this is OK because there cannot be multiple character classes
77449 * being parsed simultaneously).
77450 */
77451
77452DUK_LOCAL void duk__generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
77453 duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
77454
77455 DUK_DD(DUK_DDPRINT("duk__generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
77456 (void *) re_ctx, (long) r1, (long) r2, (long) direct));
77457
77458 if (!direct && (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE)) {
77459 /*
77460 * Canonicalize a range, generating result ranges as necessary.
77461 * Needs to exhaustively scan the entire range (at most 65536
77462 * code points). If 'direct' is set, caller (lexer) has ensured
77463 * that the range is already canonicalization compatible (this
77464 * is used to avoid unnecessary canonicalization of built-in
77465 * ranges like \W, which are not affected by canonicalization).
77466 *
77467 * NOTE: here is one place where we don't want to support chars
77468 * outside the BMP, because the exhaustive search would be
77469 * massively larger.
77470 */
77471
77474 duk_codepoint_t r_start, r_end;
77475
77476 r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
77477 r_end = r_start;
77478 for (i = r1 + 1; i <= r2; i++) {
77479 t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
77480 if (t == r_end + 1) {
77481 r_end = t;
77482 } else {
77483 DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
77484 duk__append_u32(re_ctx, (duk_uint32_t) r_start);
77485 duk__append_u32(re_ctx, (duk_uint32_t) r_end);
77486 re_ctx->nranges++;
77487 r_start = t;
77488 r_end = t;
77489 }
77490 }
77491 DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
77492 duk__append_u32(re_ctx, (duk_uint32_t) r_start);
77493 duk__append_u32(re_ctx, (duk_uint32_t) r_end);
77494 re_ctx->nranges++;
77495 } else {
77496 DUK_DD(DUK_DDPRINT("direct, emit range: [%ld,%ld]", (long) r1, (long) r2));
77497 duk__append_u32(re_ctx, (duk_uint32_t) r1);
77498 duk__append_u32(re_ctx, (duk_uint32_t) r2);
77499 re_ctx->nranges++;
77500 }
77501}
77502
77503/*
77504 * Parse regexp Disjunction. Most of regexp compilation happens here.
77505 *
77506 * Handles Disjunction, Alternative, and Term productions directly without
77507 * recursion. The only constructs requiring recursion are positive/negative
77508 * lookaheads, capturing parentheses, and non-capturing parentheses.
77509 *
77510 * The function determines whether the entire disjunction is a 'simple atom'
77511 * (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
77512 * returns the atom character length which is needed by the caller to keep
77513 * track of its own atom character length. A disjunction with more than one
77514 * alternative is never considered a simple atom (although in some cases
77515 * that might be the case).
77516 *
77517 * Return value: simple atom character length or < 0 if not a simple atom.
77518 * Appends the bytecode for the disjunction matcher to the end of the temp
77519 * buffer.
77520 *
77521 * Regexp top level structure is:
77522 *
77523 * Disjunction = Term*
77524 * | Term* | Disjunction
77525 *
77526 * Term = Assertion
77527 * | Atom
77528 * | Atom Quantifier
77529 *
77530 * An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
77531 *
77532 * Notes:
77533 *
77534 * * Tracking of the 'simple-ness' of the current atom vs. the entire
77535 * disjunction are separate matters. For instance, the disjunction
77536 * may be complex, but individual atoms may be simple. Furthermore,
77537 * simple quantifiers are used whenever possible, even if the
77538 * disjunction as a whole is complex.
77539 *
77540 * * The estimate of whether an atom is simple is conservative now,
77541 * and it would be possible to expand it. For instance, captures
77542 * cause the disjunction to be marked complex, even though captures
77543 * -can- be handled by simple quantifiers with some minor modifications.
77544 *
77545 * * Disjunction 'tainting' as 'complex' is handled at the end of the
77546 * main for loop collectively for atoms. Assertions, quantifiers,
77547 * and '|' tokens need to taint the result manually if necessary.
77548 * Assertions cannot add to result char length, only atoms (and
77549 * quantifiers) can; currently quantifiers will taint the result
77550 * as complex though.
77551 */
77552
77554 duk_int32_t atom_start_offset = -1; /* negative -> no atom matched on previous round */
77555 duk_int32_t atom_char_length = 0; /* negative -> complex atom */
77556 duk_uint32_t atom_start_captures = re_ctx->captures; /* value of re_ctx->captures at start of atom */
77557 duk_int32_t unpatched_disjunction_split = -1;
77558 duk_int32_t unpatched_disjunction_jump = -1;
77559 duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
77560 duk_int32_t res_charlen = 0; /* -1 if disjunction is complex, char length if simple */
77561 duk__re_disjunction_info tmp_disj;
77562
77563 DUK_ASSERT(out_atom_info != NULL);
77564
77565 if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
77567 }
77568 re_ctx->recursion_depth++;
77569
77570#if 0
77571 out_atom_info->start_captures = re_ctx->captures;
77572#endif
77573
77574 for (;;) {
77575 /* atom_char_length, atom_start_offset, atom_start_offset reflect the
77576 * atom matched on the previous loop. If a quantifier is encountered
77577 * on this loop, these are needed to handle the quantifier correctly.
77578 * new_atom_char_length etc are for the atom parsed on this round;
77579 * they're written to atom_char_length etc at the end of the round.
77580 */
77581 duk_int32_t new_atom_char_length; /* char length of the atom parsed in this loop */
77582 duk_int32_t new_atom_start_offset; /* bytecode start offset of the atom parsed in this loop
77583 * (allows quantifiers to copy the atom bytecode)
77584 */
77585 duk_uint32_t new_atom_start_captures; /* re_ctx->captures at the start of the atom parsed in this loop */
77586
77587 duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
77588
77589 DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
77590 (long) re_ctx->curr_token.t,
77591 (long) re_ctx->curr_token.num,
77592 (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
77593 (int) re_ctx->curr_token.num : (int) '?'));
77594
77595 /* set by atom case clauses */
77596 new_atom_start_offset = -1;
77597 new_atom_char_length = -1;
77598 new_atom_start_captures = re_ctx->captures;
77599
77600 switch (re_ctx->curr_token.t) {
77601 case DUK_RETOK_DISJUNCTION: {
77602 /*
77603 * The handling here is a bit tricky. If a previous '|' has been processed,
77604 * we have a pending split1 and a pending jump (for a previous match). These
77605 * need to be back-patched carefully. See docs for a detailed example.
77606 */
77607
77608 /* patch pending jump and split */
77609 if (unpatched_disjunction_jump >= 0) {
77610 duk_uint32_t offset;
77611
77612 DUK_ASSERT(unpatched_disjunction_split >= 0);
77613 offset = unpatched_disjunction_jump;
77614 offset += duk__insert_jump_offset(re_ctx,
77615 offset,
77616 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
77617 /* offset is now target of the pending split (right after jump) */
77619 unpatched_disjunction_split,
77620 offset - unpatched_disjunction_split);
77621 }
77622
77623 /* add a new pending split to the beginning of the entire disjunction */
77624 (void) duk__insert_u32(re_ctx,
77625 entry_offset,
77626 DUK_REOP_SPLIT1); /* prefer direct execution */
77627 unpatched_disjunction_split = entry_offset + 1; /* +1 for opcode */
77628
77629 /* add a new pending match jump for latest finished alternative */
77631 unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77632
77633 /* 'taint' result as complex */
77634 res_charlen = -1;
77635 break;
77636 }
77637 case DUK_RETOK_QUANTIFIER: {
77638 if (atom_start_offset < 0) {
77640 }
77641 if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
77643 }
77644 if (atom_char_length >= 0) {
77645 /*
77646 * Simple atom
77647 *
77648 * If atom_char_length is zero, we'll have unbounded execution time for e.g.
77649 * /()*x/.exec('x'). We can't just skip the match because it might have some
77650 * side effects (for instance, if we allowed captures in simple atoms, the
77651 * capture needs to happen). The simple solution below is to force the
77652 * quantifier to match at most once, since the additional matches have no effect.
77653 *
77654 * With a simple atom there can be no capture groups, so no captures need
77655 * to be reset.
77656 */
77657 duk_int32_t atom_code_length;
77658 duk_uint32_t offset;
77659 duk_uint32_t qmin, qmax;
77660
77661 qmin = re_ctx->curr_token.qmin;
77662 qmax = re_ctx->curr_token.qmax;
77663 if (atom_char_length == 0) {
77664 /* qmin and qmax will be 0 or 1 */
77665 if (qmin > 1) {
77666 qmin = 1;
77667 }
77668 if (qmax > 1) {
77669 qmax = 1;
77670 }
77671 }
77672
77673 duk__append_u32(re_ctx, DUK_REOP_MATCH); /* complete 'sub atom' */
77674 atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - atom_start_offset);
77675
77676 offset = atom_start_offset;
77677 if (re_ctx->curr_token.greedy) {
77678 offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
77679 offset += duk__insert_u32(re_ctx, offset, qmin);
77680 offset += duk__insert_u32(re_ctx, offset, qmax);
77681 offset += duk__insert_u32(re_ctx, offset, atom_char_length);
77682 offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
77683 } else {
77684 offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
77685 offset += duk__insert_u32(re_ctx, offset, qmin);
77686 offset += duk__insert_u32(re_ctx, offset, qmax);
77687 offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
77688 }
77689 DUK_UNREF(offset); /* silence scan-build warning */
77690 } else {
77691 /*
77692 * Complex atom
77693 *
77694 * The original code is used as a template, and removed at the end
77695 * (this differs from the handling of simple quantifiers).
77696 *
77697 * NOTE: there is no current solution for empty atoms in complex
77698 * quantifiers. This would need some sort of a 'progress' instruction.
77699 *
77700 * XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
77701 */
77702 duk_int32_t atom_code_length;
77703 duk_uint32_t atom_copies;
77704 duk_uint32_t tmp_qmin, tmp_qmax;
77705
77706 /* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
77707 atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
77708 re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
77709 if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
77711 }
77712
77713 /* wipe the capture range made by the atom (if any) */
77714 DUK_ASSERT(atom_start_captures <= re_ctx->captures);
77715 if (atom_start_captures != re_ctx->captures) {
77716 DUK_ASSERT(atom_start_captures < re_ctx->captures);
77717 DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
77718 (long) atom_start_captures, (long) re_ctx->captures));
77719
77720 /* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
77721 duk__insert_u32(re_ctx, atom_start_offset, (re_ctx->captures - atom_start_captures) * 2);
77722 duk__insert_u32(re_ctx, atom_start_offset, (atom_start_captures + 1) * 2);
77723 duk__insert_u32(re_ctx, atom_start_offset, DUK_REOP_WIPERANGE);
77724 } else {
77725 DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
77726 (long) atom_start_captures));
77727 }
77728
77729 atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
77730
77731 /* insert the required matches (qmin) by copying the atom */
77732 tmp_qmin = re_ctx->curr_token.qmin;
77733 tmp_qmax = re_ctx->curr_token.qmax;
77734 while (tmp_qmin > 0) {
77735 duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
77736 tmp_qmin--;
77737 if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
77738 tmp_qmax--;
77739 }
77740 }
77741 DUK_ASSERT(tmp_qmin == 0);
77742
77743 /* insert code for matching the remainder - infinite or finite */
77744 if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
77745 /* reuse last emitted atom for remaining 'infinite' quantifier */
77746
77747 if (re_ctx->curr_token.qmin == 0) {
77748 /* Special case: original qmin was zero so there is nothing
77749 * to repeat. Emit an atom copy but jump over it here.
77750 */
77752 duk__append_jump_offset(re_ctx, atom_code_length);
77753 duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
77754 }
77755 if (re_ctx->curr_token.greedy) {
77756 duk__append_u32(re_ctx, DUK_REOP_SPLIT2); /* prefer jump */
77757 } else {
77758 duk__append_u32(re_ctx, DUK_REOP_SPLIT1); /* prefer direct */
77759 }
77760 duk__append_jump_offset(re_ctx, -atom_code_length - 1); /* -1 for opcode */
77761 } else {
77762 /*
77763 * The remaining matches are emitted as sequence of SPLITs and atom
77764 * copies; the SPLITs skip the remaining copies and match the sequel.
77765 * This sequence needs to be emitted starting from the last copy
77766 * because the SPLITs are variable length due to the variable length
77767 * skip offset. This causes a lot of memory copying now.
77768 *
77769 * Example structure (greedy, match maximum # atoms):
77770 *
77771 * SPLIT1 LSEQ
77772 * (atom)
77773 * SPLIT1 LSEQ ; <- the byte length of this instruction is needed
77774 * (atom) ; to encode the above SPLIT1 correctly
77775 * ...
77776 * LSEQ:
77777 */
77778 duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
77779 while (tmp_qmax > 0) {
77780 duk__insert_slice(re_ctx, offset, atom_start_offset, atom_code_length);
77781 if (re_ctx->curr_token.greedy) {
77782 duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1); /* prefer direct */
77783 } else {
77784 duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2); /* prefer jump */
77785 }
77787 offset + 1, /* +1 for opcode */
77788 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
77789 tmp_qmax--;
77790 }
77791 }
77792
77793 /* remove the original 'template' atom */
77794 duk__remove_slice(re_ctx, atom_start_offset, atom_code_length);
77795 }
77796
77797 /* 'taint' result as complex */
77798 res_charlen = -1;
77799 break;
77800 }
77803 break;
77804 }
77805 case DUK_RETOK_ASSERT_END: {
77807 break;
77808 }
77811 break;
77812 }
77815 break;
77816 }
77819 duk_uint32_t offset;
77820 duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
77822
77823 offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
77824 duk__parse_disjunction(re_ctx, 0, &tmp_disj);
77826
77827 (void) duk__insert_u32(re_ctx, offset, opcode);
77828 (void) duk__insert_jump_offset(re_ctx,
77829 offset + 1, /* +1 for opcode */
77830 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
77831
77832 /* 'taint' result as complex -- this is conservative,
77833 * as lookaheads do not backtrack.
77834 */
77835 res_charlen = -1;
77836 break;
77837 }
77838 case DUK_RETOK_ATOM_PERIOD: {
77839 new_atom_char_length = 1;
77840 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77842 break;
77843 }
77844 case DUK_RETOK_ATOM_CHAR: {
77845 /* Note: successive characters could be joined into string matches
77846 * but this is not trivial (consider e.g. '/xyz+/); see docs for
77847 * more discussion.
77848 */
77849 duk_uint32_t ch;
77850
77851 new_atom_char_length = 1;
77852 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77854 ch = re_ctx->curr_token.num;
77855 if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
77856 ch = duk_unicode_re_canonicalize_char(re_ctx->thr, ch);
77857 }
77858 duk__append_u32(re_ctx, ch);
77859 break;
77860 }
77863 new_atom_char_length = 1;
77864 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77865 duk__append_u32(re_ctx,
77866 (re_ctx->curr_token.t == DUK_RETOK_ATOM_DIGIT) ?
77868 duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)));
77869 duk__append_u16_list(re_ctx, duk_unicode_re_ranges_digit, sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
77870 break;
77871 }
77874 new_atom_char_length = 1;
77875 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77876 duk__append_u32(re_ctx,
77877 (re_ctx->curr_token.t == DUK_RETOK_ATOM_WHITE) ?
77879 duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)));
77880 duk__append_u16_list(re_ctx, duk_unicode_re_ranges_white, sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
77881 break;
77882 }
77885 new_atom_char_length = 1;
77886 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77887 duk__append_u32(re_ctx,
77890 duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t)));
77892 break;
77893 }
77895 duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
77896 if (backref > re_ctx->highest_backref) {
77897 re_ctx->highest_backref = backref;
77898 }
77899 new_atom_char_length = -1; /* mark as complex */
77900 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77902 duk__append_u32(re_ctx, backref);
77903 break;
77904 }
77906 duk_uint32_t cap;
77907
77908 new_atom_char_length = -1; /* mark as complex (capture handling) */
77909 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77910 cap = ++re_ctx->captures;
77912 duk__append_u32(re_ctx, cap * 2);
77913 duk__parse_disjunction(re_ctx, 0, &tmp_disj); /* retval (sub-atom char length) unused, tainted as complex above */
77915 duk__append_u32(re_ctx, cap * 2 + 1);
77916 break;
77917 }
77919 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77920 duk__parse_disjunction(re_ctx, 0, &tmp_disj);
77921 new_atom_char_length = tmp_disj.charlen;
77922 break;
77923 }
77926 /*
77927 * Range parsing is done with a special lexer function which calls
77928 * us for every range parsed. This is different from how rest of
77929 * the parsing works, but avoids a heavy, arbitrary size intermediate
77930 * value type to hold the ranges.
77931 *
77932 * Another complication is the handling of character ranges when
77933 * case insensitive matching is used (see docs for discussion).
77934 * The range handler callback given to the lexer takes care of this
77935 * as well.
77936 *
77937 * Note that duplicate ranges are not eliminated when parsing character
77938 * classes, so that canonicalization of
77939 *
77940 * [0-9a-fA-Fx-{]
77941 *
77942 * creates the result (note the duplicate ranges):
77943 *
77944 * [0-9A-FA-FX-Z{-{]
77945 *
77946 * where [x-{] is split as a result of canonicalization. The duplicate
77947 * ranges are not a semantics issue: they work correctly.
77948 */
77949
77950 duk_uint32_t offset;
77951
77952 DUK_DD(DUK_DDPRINT("character class"));
77953
77954 /* insert ranges instruction, range count patched in later */
77955 new_atom_char_length = 1;
77956 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77957 duk__append_u32(re_ctx,
77960 offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); /* patch in range count later */
77961
77962 /* parse ranges until character class ends */
77963 re_ctx->nranges = 0; /* note: ctx-wide temporary */
77964 duk_lexer_parse_re_ranges(&re_ctx->lex, duk__generate_ranges, (void *) re_ctx);
77965
77966 /* insert range count */
77967 duk__insert_u32(re_ctx, offset, re_ctx->nranges);
77968 break;
77969 }
77971 if (expect_eof) {
77973 }
77974 goto done;
77975 }
77976 case DUK_RETOK_EOF: {
77977 if (!expect_eof) {
77979 }
77980 goto done;
77981 }
77982 default: {
77984 }
77985 }
77986
77987 /* a complex (new) atom taints the result */
77988 if (new_atom_start_offset >= 0) {
77989 if (new_atom_char_length < 0) {
77990 res_charlen = -1;
77991 } else if (res_charlen >= 0) {
77992 /* only advance if not tainted */
77993 res_charlen += new_atom_char_length;
77994 }
77995 }
77996
77997 /* record previous atom info in case next token is a quantifier */
77998 atom_start_offset = new_atom_start_offset;
77999 atom_char_length = new_atom_char_length;
78000 atom_start_captures = new_atom_start_captures;
78001 }
78002
78003 done:
78004
78005 /* finish up pending jump and split for last alternative */
78006 if (unpatched_disjunction_jump >= 0) {
78007 duk_uint32_t offset;
78008
78009 DUK_ASSERT(unpatched_disjunction_split >= 0);
78010 offset = unpatched_disjunction_jump;
78011 offset += duk__insert_jump_offset(re_ctx,
78012 offset,
78013 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
78014 /* offset is now target of the pending split (right after jump) */
78016 unpatched_disjunction_split,
78017 offset - unpatched_disjunction_split);
78018 }
78019
78020#if 0
78021 out_atom_info->end_captures = re_ctx->captures;
78022#endif
78023 out_atom_info->charlen = res_charlen;
78024 DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
78025 (long) out_atom_info->charlen));
78026
78027 re_ctx->recursion_depth--;
78028}
78029
78030/*
78031 * Flags parsing (see E5 Section 15.10.4.1).
78032 */
78033
78035 const duk_uint8_t *p;
78036 const duk_uint8_t *p_end;
78037 duk_uint32_t flags = 0;
78038
78039 p = DUK_HSTRING_GET_DATA(h);
78040 p_end = p + DUK_HSTRING_GET_BYTELEN(h);
78041
78042 /* Note: can be safely scanned as bytes (undecoded) */
78043
78044 while (p < p_end) {
78045 duk_uint8_t c = *p++;
78046 switch ((int) c) {
78047 case (int) 'g': {
78048 if (flags & DUK_RE_FLAG_GLOBAL) {
78049 goto error;
78050 }
78051 flags |= DUK_RE_FLAG_GLOBAL;
78052 break;
78053 }
78054 case (int) 'i': {
78055 if (flags & DUK_RE_FLAG_IGNORE_CASE) {
78056 goto error;
78057 }
78058 flags |= DUK_RE_FLAG_IGNORE_CASE;
78059 break;
78060 }
78061 case (int) 'm': {
78062 if (flags & DUK_RE_FLAG_MULTILINE) {
78063 goto error;
78064 }
78065 flags |= DUK_RE_FLAG_MULTILINE;
78066 break;
78067 }
78068 default: {
78069 goto error;
78070 }
78071 }
78072 }
78073
78074 return flags;
78075
78076 error:
78078 return 0; /* never here */
78079}
78080
78081/*
78082 * Create escaped RegExp source (E5 Section 15.10.3).
78083 *
78084 * The current approach is to special case the empty RegExp
78085 * ('' -> '(?:)') and otherwise replace unescaped '/' characters
78086 * with '\/' regardless of where they occur in the regexp.
78087 *
78088 * Note that normalization does not seem to be necessary for
78089 * RegExp literals (e.g. '/foo/') because to be acceptable as
78090 * a RegExp literal, the text between forward slashes must
78091 * already match the escaping requirements (e.g. must not contain
78092 * unescaped forward slashes or be empty). Escaping IS needed
78093 * for expressions like 'new Regexp("...", "")' however.
78094 * Currently, we re-escape in either case.
78095 *
78096 * Also note that we process the source here in UTF-8 encoded
78097 * form. This is correct, because any non-ASCII characters are
78098 * passed through without change.
78099 */
78100
78101DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
78102 duk_context *ctx = (duk_context *) thr;
78103 duk_hstring *h;
78104 const duk_uint8_t *p;
78105 duk_bufwriter_ctx bw_alloc;
78107 duk_uint8_t *q;
78108 duk_size_t i, n;
78109 duk_uint_fast8_t c_prev, c;
78110
78111 h = duk_get_hstring(ctx, idx_pattern);
78112 DUK_ASSERT(h != NULL);
78113 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
78115
78116 if (n == 0) {
78117 /* return '(?:)' */
78119 return;
78120 }
78121
78122 bw = &bw_alloc;
78123 DUK_BW_INIT_PUSHBUF(thr, bw, n);
78124 q = DUK_BW_GET_PTR(thr, bw);
78125
78126 c_prev = (duk_uint_fast8_t) 0;
78127
78128 for (i = 0; i < n; i++) {
78129 c = p[i];
78130
78131 q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
78132
78133 if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
78134 /* Unescaped '/' ANYWHERE in the regexp (in disjunction,
78135 * inside a character class, ...) => same escape works.
78136 */
78137 *q++ = DUK_ASC_BACKSLASH;
78138 }
78139 *q++ = (duk_uint8_t) c;
78140
78141 c_prev = c;
78142 }
78143
78144 DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
78145 duk_to_string(ctx, -1); /* -> [ ... escaped_source ] */
78147
78148/*
78149 * Exposed regexp compilation primitive.
78150 *
78151 * Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
78152 * actual parsing. Handles generation of the compiled regexp header and the
78153 * "boilerplate" capture of the matching substring (save 0 and 1). Also does some
78154 * global level regexp checks after recursive compilation has finished.
78155 *
78156 * An escaped version of the regexp source, suitable for use as a RegExp instance
78157 * 'source' property (see E5 Section 15.10.3), is also left on the stack.
78158 *
78159 * Input stack: [ pattern flags ]
78160 * Output stack: [ bytecode escaped_source ] (both as strings)
78161 */
78162
78164 duk_context *ctx = (duk_context *) thr;
78165 duk_re_compiler_ctx re_ctx;
78166 duk_lexer_point lex_point;
78167 duk_hstring *h_pattern;
78168 duk_hstring *h_flags;
78169 duk__re_disjunction_info ign_disj;
78170
78171 DUK_ASSERT(thr != NULL);
78172 DUK_ASSERT(ctx != NULL);
78173
78174 /*
78175 * Args validation
78176 */
78177
78178 /* TypeError if fails */
78179 h_pattern = duk_require_hstring(ctx, -2);
78180 h_flags = duk_require_hstring(ctx, -1);
78181
78182 /*
78183 * Create normalized 'source' property (E5 Section 15.10.3).
78184 */
78185
78186 /* [ ... pattern flags ] */
78187
78189
78190 /* [ ... pattern flags escaped_source ] */
78191
78192 /*
78193 * Init compilation context
78194 */
78195
78196 /* [ ... pattern flags escaped_source buffer ] */
78197
78198 DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
78199 DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */
78200 re_ctx.thr = thr;
78201 re_ctx.lex.thr = thr;
78202 re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
78203 re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
78206 re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
78207
78209
78210 DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
78211 (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
78212
78213 /*
78214 * Init lexer
78215 */
78216
78217 lex_point.offset = 0; /* expensive init, just want to fill window */
78218 lex_point.line = 1;
78219 DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
78220
78221 /*
78222 * Compilation
78223 */
78224
78225 DUK_DD(DUK_DDPRINT("starting regexp compilation"));
78226
78228 duk__append_u32(&re_ctx, 0);
78229 duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
78231 duk__append_u32(&re_ctx, 1);
78233
78234 /*
78235 * Check for invalid backreferences; note that it is NOT an error
78236 * to back-reference a capture group which has not yet been introduced
78237 * in the pattern (as in /\1(foo)/); in fact, the backreference will
78238 * always match! It IS an error to back-reference a capture group
78239 * which will never be introduced in the pattern. Thus, we can check
78240 * for such references only after parsing is complete.
78241 */
78242
78243 if (re_ctx.highest_backref > re_ctx.captures) {
78245 }
78246
78247 /*
78248 * Emit compiled regexp header: flags, ncaptures
78249 * (insertion order inverted on purpose)
78250 */
78251
78252 duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
78253 duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
78254
78255 /* [ ... pattern flags escaped_source buffer ] */
78256
78257 DUK_BW_COMPACT(thr, &re_ctx.bw);
78258 duk_to_string(ctx, -1); /* coerce to string */
78259
78260 /* [ ... pattern flags escaped_source bytecode ] */
78261
78262 /*
78263 * Finalize stack
78264 */
78265
78266 duk_remove(ctx, -4); /* -> [ ... flags escaped_source bytecode ] */
78267 duk_remove(ctx, -3); /* -> [ ... escaped_source bytecode ] */
78268
78269 DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
78270 (duk_tval *) duk_get_tval(ctx, -1), (duk_tval *) duk_get_tval(ctx, -2)));
78271}
78272
78273/*
78274 * Create a RegExp instance (E5 Section 15.10.7).
78275 *
78276 * Note: the output stack left by duk_regexp_compile() is directly compatible
78277 * with the input here.
78278 *
78279 * Input stack: [ escaped_source bytecode ] (both as strings)
78280 * Output stack: [ RegExp ]
78281 */
78282
78284 duk_context *ctx = (duk_context *) thr;
78285 duk_hobject *h;
78286 duk_hstring *h_bc;
78287 duk_small_int_t re_flags;
78288
78289 /* [ ... escape_source bytecode ] */
78290
78291 h_bc = duk_get_hstring(ctx, -1);
78292 DUK_ASSERT(h_bc != NULL);
78293 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1); /* always at least the header */
78295 DUK_ASSERT((duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80); /* flags always encodes to 1 byte */
78296 re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
78297
78298 /* [ ... escaped_source bytecode ] */
78299
78300 duk_push_object(ctx);
78301 h = duk_get_hobject(ctx, -1);
78302 DUK_ASSERT(h != NULL);
78303 duk_insert(ctx, -3);
78304
78305 /* [ ... regexp_object escaped_source bytecode ] */
78306
78309
78311
78312 /* [ ... regexp_object escaped_source ] */
78313
78315
78316 /* [ ... regexp_object ] */
78317
78318 duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_GLOBAL));
78320
78321 duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
78323
78324 duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_MULTILINE));
78326
78327 duk_push_int(ctx, 0);
78329
78330 /* [ ... regexp_object ] */
78331}
78332
78333#undef DUK__RE_BUFLEN
78334
78335#else /* DUK_USE_REGEXP_SUPPORT */
78336
78337/* regexp support disabled */
78338
78339#endif /* DUK_USE_REGEXP_SUPPORT */
78340/*
78341 * Regexp executor.
78342 *
78343 * Safety: the Ecmascript executor should prevent user from reading and
78344 * replacing regexp bytecode. Even so, the executor must validate all
78345 * memory accesses etc. When an invalid access is detected (e.g. a 'save'
78346 * opcode to invalid, unallocated index) it should fail with an internal
78347 * error but not cause a segmentation fault.
78348 *
78349 * Notes:
78351 * - Backtrack counts are limited to unsigned 32 bits but should
78352 * technically be duk_size_t for strings longer than 4G chars.
78353 * This also requires a regexp bytecode change.
78355
78356/* include removed: duk_internal.h */
78357
78358#ifdef DUK_USE_REGEXP_SUPPORT
78359
78360/*
78361 * Helpers for UTF-8 handling
78362 *
78363 * For bytecode readers the duk_uint32_t and duk_int32_t types are correct
78364 * because they're used for more than just codepoints.
78365 */
78367DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
78368 return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
78369}
78370
78371DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
78372 duk_uint32_t t;
78373
78374 /* signed integer encoding needed to work with UTF-8 */
78375 t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
78376 if (t & 1) {
78377 return -((duk_int32_t) (t >> 1));
78378 } else {
78379 return (duk_int32_t) (t >> 1);
78380 }
78381}
78382
78383DUK_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) {
78384 const duk_uint8_t *p;
78385
78386 /* Note: allow backtracking from p == ptr_end */
78387 p = *ptr;
78388 if (p < ptr_start || p > ptr_end) {
78389 goto fail;
78390 }
78391
78392 while (count > 0) {
78393 for (;;) {
78394 p--;
78395 if (p < ptr_start) {
78396 goto fail;
78397 }
78398 if ((*p & 0xc0) != 0x80) {
78399 /* utf-8 continuation bytes have the form 10xx xxxx */
78400 break;
78401 }
78402 }
78403 count--;
78404 }
78405 *ptr = p;
78406 return p;
78407
78408 fail:
78410 return NULL; /* never here */
78411}
78412
78413DUK_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) {
78414 const duk_uint8_t *p;
78415
78416 p = *ptr;
78417 if (p < ptr_start || p >= ptr_end) {
78418 goto fail;
78419 }
78420
78421 while (count > 0) {
78422 for (;;) {
78423 p++;
78424
78425 /* Note: if encoding ends by hitting end of input, we don't check that
78426 * the encoding is valid, we just assume it is.
78427 */
78428 if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
78429 /* utf-8 continuation bytes have the form 10xx xxxx */
78430 break;
78431 }
78432 }
78433 count--;
78434 }
78436 *ptr = p;
78437 return p;
78438
78439 fail:
78441 return NULL; /* never here */
78442}
78444/*
78445 * Helpers for dealing with the input string
78446 */
78447
78448/* Get a (possibly canonicalized) input character from current sp. The input
78449 * itself is never modified, and captures always record non-canonicalized
78450 * characters even in case-insensitive matching.
78451 */
78452DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
78454 if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
78455 res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
78456 }
78457 return res;
78458}
78459
78460DUK_LOCAL const duk_uint8_t *duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count) {
78461 return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
78462}
78463
78464/* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
78466 /* note: caller 'sp' is intentionally not updated here */
78467 (void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
78468 return duk__inp_get_cp(re_ctx, &sp);
78469}
78470
78471/*
78472 * Regexp recursive matching function.
78473 *
78474 * Returns 'sp' on successful match (points to character after last matched one),
78475 * NULL otherwise.
78476 *
78477 * The C recursion depth limit check is only performed in this function, this
78478 * suffices because the function is present in all true recursion required by
78479 * regexp execution.
78480 */
78481
78482DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) {
78483 if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
78485 }
78486 re_ctx->recursion_depth++;
78487
78488 for (;;) {
78489 duk_small_int_t op;
78490
78491 if (re_ctx->steps_count >= re_ctx->steps_limit) {
78493 }
78494 re_ctx->steps_count++;
78495
78496 op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
78497
78498 DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
78499 (long) re_ctx->recursion_depth,
78500 (long) re_ctx->steps_count,
78501 (long) (pc - re_ctx->bytecode),
78502 (long) (sp - re_ctx->input),
78503 (long) op));
78504
78505 switch (op) {
78506 case DUK_REOP_MATCH: {
78507 goto match;
78508 }
78509 case DUK_REOP_CHAR: {
78510 /*
78511 * Byte-based matching would be possible for case-sensitive
78512 * matching but not for case-insensitive matching. So, we
78513 * match by decoding the input and bytecode character normally.
78514 *
78515 * Bytecode characters are assumed to be already canonicalized.
78516 * Input characters are canonicalized automatically by
78517 * duk__inp_get_cp() if necessary.
78518 *
78519 * There is no opcode for matching multiple characters. The
78520 * regexp compiler has trouble joining strings efficiently
78521 * during compilation. See doc/regexp.rst for more discussion.
78522 */
78523 duk_codepoint_t c1, c2;
78524
78525 c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78527 c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1)); /* canonicalized by compiler */
78528 if (sp >= re_ctx->input_end) {
78529 goto fail;
78530 }
78531 c2 = duk__inp_get_cp(re_ctx, &sp);
78532 DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
78533 if (c1 != c2) {
78534 goto fail;
78535 }
78536 break;
78537 }
78538 case DUK_REOP_PERIOD: {
78540
78541 if (sp >= re_ctx->input_end) {
78542 goto fail;
78543 }
78544 c = duk__inp_get_cp(re_ctx, &sp);
78546 /* E5 Sections 15.10.2.8, 7.3 */
78547 goto fail;
78548 }
78549 break;
78550 }
78551 case DUK_REOP_RANGES:
78552 case DUK_REOP_INVRANGES: {
78553 duk_uint32_t n;
78556
78557 n = duk__bc_get_u32(re_ctx, &pc);
78558 if (sp >= re_ctx->input_end) {
78559 goto fail;
78560 }
78561 c = duk__inp_get_cp(re_ctx, &sp);
78562
78563 match = 0;
78564 while (n) {
78565 duk_codepoint_t r1, r2;
78566 r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78567 r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78568 DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
78569 (long) n, (long) r1, (long) r2, (long) c));
78570 if (c >= r1 && c <= r2) {
78571 /* Note: don't bail out early, we must read all the ranges from
78572 * bytecode. Another option is to skip them efficiently after
78573 * breaking out of here. Prefer smallest code.
78574 */
78575 match = 1;
78576 }
78577 n--;
78578 }
78579
78580 if (op == DUK_REOP_RANGES) {
78581 if (!match) {
78582 goto fail;
78583 }
78584 } else {
78586 if (match) {
78587 goto fail;
78588 }
78589 }
78590 break;
78591 }
78592 case DUK_REOP_ASSERT_START: {
78594
78595 if (sp <= re_ctx->input) {
78596 break;
78597 }
78598 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
78599 goto fail;
78600 }
78601 c = duk__inp_get_prev_cp(re_ctx, sp);
78603 /* E5 Sections 15.10.2.8, 7.3 */
78604 break;
78605 }
78606 goto fail;
78607 }
78608 case DUK_REOP_ASSERT_END: {
78610 const duk_uint8_t *tmp_sp;
78611
78612 if (sp >= re_ctx->input_end) {
78613 break;
78614 }
78615 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
78616 goto fail;
78617 }
78618 tmp_sp = sp;
78619 c = duk__inp_get_cp(re_ctx, &tmp_sp);
78621 /* E5 Sections 15.10.2.8, 7.3 */
78622 break;
78623 }
78624 goto fail;
78625 }
78628 /*
78629 * E5 Section 15.10.2.6. The previous and current character
78630 * should -not- be canonicalized as they are now. However,
78631 * canonicalization does not affect the result of IsWordChar()
78632 * (which depends on Unicode characters never canonicalizing
78633 * into ASCII characters) so this does not matter.
78634 */
78635 duk_small_int_t w1, w2;
78636
78637 if (sp <= re_ctx->input) {
78638 w1 = 0; /* not a wordchar */
78639 } else {
78641 c = duk__inp_get_prev_cp(re_ctx, sp);
78643 }
78644 if (sp >= re_ctx->input_end) {
78645 w2 = 0; /* not a wordchar */
78646 } else {
78647 const duk_uint8_t *tmp_sp = sp; /* dummy so sp won't get updated */
78649 c = duk__inp_get_cp(re_ctx, &tmp_sp);
78651 }
78652
78654 if (w1 == w2) {
78655 goto fail;
78656 }
78657 } else {
78659 if (w1 != w2) {
78660 goto fail;
78661 }
78662 }
78663 break;
78664 }
78665 case DUK_REOP_JUMP: {
78666 duk_int32_t skip;
78667
78668 skip = duk__bc_get_i32(re_ctx, &pc);
78669 pc += skip;
78670 break;
78671 }
78672 case DUK_REOP_SPLIT1: {
78673 /* split1: prefer direct execution (no jump) */
78674 const duk_uint8_t *sub_sp;
78675 duk_int32_t skip;
78676
78677 skip = duk__bc_get_i32(re_ctx, &pc);
78678 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78679 if (sub_sp) {
78680 sp = sub_sp;
78681 goto match;
78682 }
78683 pc += skip;
78684 break;
78685 }
78686 case DUK_REOP_SPLIT2: {
78687 /* split2: prefer jump execution (not direct) */
78688 const duk_uint8_t *sub_sp;
78689 duk_int32_t skip;
78690
78691 skip = duk__bc_get_i32(re_ctx, &pc);
78692 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78693 if (sub_sp) {
78694 sp = sub_sp;
78695 goto match;
78696 }
78697 break;
78698 }
78699 case DUK_REOP_SQMINIMAL: {
78700 duk_uint32_t q, qmin, qmax;
78701 duk_int32_t skip;
78702 const duk_uint8_t *sub_sp;
78703
78704 qmin = duk__bc_get_u32(re_ctx, &pc);
78705 qmax = duk__bc_get_u32(re_ctx, &pc);
78706 skip = duk__bc_get_i32(re_ctx, &pc);
78707 DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
78708 (unsigned long) qmin, (unsigned long) qmax, (long) skip));
78709
78710 q = 0;
78711 while (q <= qmax) {
78712 if (q >= qmin) {
78713 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78714 if (sub_sp) {
78715 sp = sub_sp;
78716 goto match;
78717 }
78718 }
78719 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78720 if (!sub_sp) {
78721 break;
78722 }
78723 sp = sub_sp;
78724 q++;
78725 }
78726 goto fail;
78727 }
78728 case DUK_REOP_SQGREEDY: {
78729 duk_uint32_t q, qmin, qmax, atomlen;
78730 duk_int32_t skip;
78731 const duk_uint8_t *sub_sp;
78732
78733 qmin = duk__bc_get_u32(re_ctx, &pc);
78734 qmax = duk__bc_get_u32(re_ctx, &pc);
78735 atomlen = duk__bc_get_u32(re_ctx, &pc);
78736 skip = duk__bc_get_i32(re_ctx, &pc);
78737 DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
78738 (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
78739
78740 q = 0;
78741 while (q < qmax) {
78742 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78743 if (!sub_sp) {
78744 break;
78745 }
78746 sp = sub_sp;
78747 q++;
78748 }
78749 while (q >= qmin) {
78750 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78751 if (sub_sp) {
78752 sp = sub_sp;
78753 goto match;
78754 }
78755 if (q == qmin) {
78756 break;
78757 }
78758
78759 /* Note: if atom were to contain e.g. captures, we would need to
78760 * re-match the atom to get correct captures. Simply quantifiers
78761 * do not allow captures in their atom now, so this is not an issue.
78762 */
78763
78764 DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
78765 (long) atomlen));
78766 sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
78767 q--;
78768 }
78769 goto fail;
78770 }
78771 case DUK_REOP_SAVE: {
78772 duk_uint32_t idx;
78773 const duk_uint8_t *old;
78774 const duk_uint8_t *sub_sp;
78775
78776 idx = duk__bc_get_u32(re_ctx, &pc);
78777 if (idx >= re_ctx->nsaved) {
78778 /* idx is unsigned, < 0 check is not necessary */
78779 DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
78780 goto internal_error;
78781 }
78782 old = re_ctx->saved[idx];
78783 re_ctx->saved[idx] = sp;
78784 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78785 if (sub_sp) {
78786 sp = sub_sp;
78787 goto match;
78788 }
78789 re_ctx->saved[idx] = old;
78790 goto fail;
78791 }
78792 case DUK_REOP_WIPERANGE: {
78793 /* Wipe capture range and save old values for backtracking.
78794 *
78795 * XXX: this typically happens with a relatively small idx_count.
78796 * It might be useful to handle cases where the count is small
78797 * (say <= 8) by saving the values in stack instead. This would
78798 * reduce memory churn and improve performance, at the cost of a
78799 * slightly higher code footprint.
78800 */
78801 duk_uint32_t idx_start, idx_count;
78802#ifdef DUK_USE_EXPLICIT_NULL_INIT
78803 duk_uint32_t idx_end, idx;
78804#endif
78805 duk_uint8_t **range_save;
78806 const duk_uint8_t *sub_sp;
78807
78808 idx_start = duk__bc_get_u32(re_ctx, &pc);
78809 idx_count = duk__bc_get_u32(re_ctx, &pc);
78810 DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
78811 (long) idx_start, (long) idx_count,
78812 (long) idx_start, (long) (idx_start + idx_count - 1),
78813 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
78814 if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
78815 /* idx is unsigned, < 0 check is not necessary */
78816 DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
78817 (long) idx_start, (long) idx_count));
78818 goto internal_error;
78819 }
78820 DUK_ASSERT(idx_count > 0);
78821
78822 duk_require_stack((duk_context *) re_ctx->thr, 1);
78823 range_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
78824 sizeof(duk_uint8_t *) * idx_count);
78825 DUK_ASSERT(range_save != NULL);
78826 DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
78827#ifdef DUK_USE_EXPLICIT_NULL_INIT
78828 idx_end = idx_start + idx_count;
78829 for (idx = idx_start; idx < idx_end; idx++) {
78830 re_ctx->saved[idx] = NULL;
78831 }
78832#else
78833 DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
78834#endif
78835
78836 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78837 if (sub_sp) {
78838 /* match: keep wiped/resaved values */
78839 DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
78840 (long) idx_start, (long) (idx_start + idx_count - 1),
78841 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
78842 duk_pop((duk_context *) re_ctx->thr);
78843 sp = sub_sp;
78844 goto match;
78845 }
78846
78847 /* fail: restore saves */
78848 DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
78849 (long) idx_start, (long) (idx_start + idx_count - 1),
78850 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
78851 DUK_MEMCPY((void *) (re_ctx->saved + idx_start),
78852 (const void *) range_save,
78853 sizeof(duk_uint8_t *) * idx_count);
78854 duk_pop((duk_context *) re_ctx->thr);
78855 goto fail;
78856 }
78857 case DUK_REOP_LOOKPOS:
78858 case DUK_REOP_LOOKNEG: {
78859 /*
78860 * Needs a save of multiple saved[] entries depending on what range
78861 * may be overwritten. Because the regexp parser does no such analysis,
78862 * we currently save the entire saved array here. Lookaheads are thus
78863 * a bit expensive. Note that the saved array is not needed for just
78864 * the lookahead sub-match, but for the matching of the entire sequel.
78865 *
78866 * The temporary save buffer is pushed on to the valstack to handle
78867 * errors correctly. Each lookahead causes a C recursion and pushes
78868 * more stuff on the value stack. If the C recursion limit is less
78869 * than the value stack spare, there is no need to check the stack.
78870 * We do so regardless, just in case.
78871 */
78872
78873 duk_int32_t skip;
78874 duk_uint8_t **full_save;
78875 const duk_uint8_t *sub_sp;
78876
78877 DUK_ASSERT(re_ctx->nsaved > 0);
78878
78879 duk_require_stack((duk_context *) re_ctx->thr, 1);
78880 full_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
78881 sizeof(duk_uint8_t *) * re_ctx->nsaved);
78882 DUK_ASSERT(full_save != NULL);
78883 DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
78884
78885 skip = duk__bc_get_i32(re_ctx, &pc);
78886 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78887 if (op == DUK_REOP_LOOKPOS) {
78888 if (!sub_sp) {
78889 goto lookahead_fail;
78890 }
78891 } else {
78892 if (sub_sp) {
78893 goto lookahead_fail;
78894 }
78895 }
78896 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78897 if (sub_sp) {
78898 /* match: keep saves */
78899 duk_pop((duk_context *) re_ctx->thr);
78900 sp = sub_sp;
78901 goto match;
78902 }
78903
78904 /* fall through */
78905
78906 lookahead_fail:
78907 /* fail: restore saves */
78908 DUK_MEMCPY((void *) re_ctx->saved,
78909 (const void *) full_save,
78910 sizeof(duk_uint8_t *) * re_ctx->nsaved);
78911 duk_pop((duk_context *) re_ctx->thr);
78912 goto fail;
78913 }
78915 /*
78916 * Byte matching for back-references would be OK in case-
78917 * sensitive matching. In case-insensitive matching we need
78918 * to canonicalize characters, so back-reference matching needs
78919 * to be done with codepoints instead. So, we just decode
78920 * everything normally here, too.
78921 *
78922 * Note: back-reference index which is 0 or higher than
78923 * NCapturingParens (= number of capturing parens in the
78924 * -entire- regexp) is a compile time error. However, a
78925 * backreference referring to a valid capture which has
78926 * not matched anything always succeeds! See E5 Section
78927 * 15.10.2.9, step 5, sub-step 3.
78928 */
78929 duk_uint32_t idx;
78930 const duk_uint8_t *p;
78931
78932 idx = duk__bc_get_u32(re_ctx, &pc);
78933 idx = idx << 1; /* backref n -> saved indices [n*2, n*2+1] */
78934 if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
78935 /* regexp compiler should catch these */
78936 DUK_D(DUK_DPRINT("internal error, backreference index insane"));
78937 goto internal_error;
78938 }
78939 if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
78940 /* capture is 'undefined', always matches! */
78941 DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
78942 (long) idx, (long) (idx + 1)));
78943 break;
78944 }
78945 DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
78946
78947 p = re_ctx->saved[idx];
78948 while (p < re_ctx->saved[idx+1]) {
78949 duk_codepoint_t c1, c2;
78950
78951 /* Note: not necessary to check p against re_ctx->input_end:
78952 * the memory access is checked by duk__inp_get_cp(), while
78953 * valid compiled regexps cannot write a saved[] entry
78954 * which points to outside the string.
78955 */
78956 if (sp >= re_ctx->input_end) {
78957 goto fail;
78958 }
78959 c1 = duk__inp_get_cp(re_ctx, &p);
78960 c2 = duk__inp_get_cp(re_ctx, &sp);
78961 if (c1 != c2) {
78962 goto fail;
78963 }
78964 }
78965 break;
78966 }
78967 default: {
78968 DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
78969 goto internal_error;
78970 }
78971 }
78972 }
78973
78974 match:
78975 re_ctx->recursion_depth--;
78976 return sp;
78977
78978 fail:
78979 re_ctx->recursion_depth--;
78980 return NULL;
78981
78982 internal_error:
78984 return NULL; /* never here */
78985}
78986
78987/*
78988 * Exposed matcher function which provides the semantics of RegExp.prototype.exec().
78989 *
78990 * RegExp.prototype.test() has the same semantics as exec() but does not return the
78991 * result object (which contains the matching string and capture groups). Currently
78992 * there is no separate test() helper, so a temporary result object is created and
78993 * discarded if test() is needed. This is intentional, to save code space.
78994 *
78995 * Input stack: [ ... re_obj input ]
78996 * Output stack: [ ... result ]
78997 */
78998
79000 duk_context *ctx = (duk_context *) thr;
79001 duk_re_matcher_ctx re_ctx;
79002 duk_hobject *h_regexp;
79003 duk_hstring *h_bytecode;
79004 duk_hstring *h_input;
79005 duk_uint8_t *p_buf;
79006 const duk_uint8_t *pc;
79007 const duk_uint8_t *sp;
79009 duk_small_int_t global;
79011 double d;
79012 duk_uint32_t char_offset;
79013
79014 DUK_ASSERT(thr != NULL);
79015 DUK_ASSERT(ctx != NULL);
79016
79017 DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
79018 (duk_tval *) duk_get_tval(ctx, -2),
79019 (duk_tval *) duk_get_tval(ctx, -1)));
79020
79021 /*
79022 * Regexp instance check, bytecode check, input coercion.
79023 *
79024 * See E5 Section 15.10.6.
79025 */
79026
79027 /* TypeError if wrong; class check, see E5 Section 15.10.6 */
79029 DUK_ASSERT(h_regexp != NULL);
79031 DUK_UNREF(h_regexp);
79032
79033 duk_to_string(ctx, -1);
79034 h_input = duk_get_hstring(ctx, -1);
79035 DUK_ASSERT(h_input != NULL);
79036
79037 duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_BYTECODE); /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
79038 h_bytecode = duk_require_hstring(ctx, -1); /* no regexp instance should exist without a non-configurable bytecode property */
79039 DUK_ASSERT(h_bytecode != NULL);
79040
79041 /*
79042 * Basic context initialization.
79043 *
79044 * Some init values are read from the bytecode header
79045 * whose format is (UTF-8 codepoints):
79046 *
79047 * uint flags
79048 * uint nsaved (even, 2n+2 where n = num captures)
79049 */
79050
79051 /* [ ... re_obj input bc ] */
79052
79053 DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
79054
79055 re_ctx.thr = thr;
79056 re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
79057 re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
79058 re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
79059 re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
79060 re_ctx.saved = NULL;
79063
79064 /* read header */
79065 pc = re_ctx.bytecode;
79066 re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
79067 re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
79068 re_ctx.bytecode = pc;
79069
79070 DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL); /* must fit into duk_small_int_t */
79071 global = (duk_small_int_t) (force_global | (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
79072
79073 DUK_ASSERT(re_ctx.nsaved >= 2);
79074 DUK_ASSERT((re_ctx.nsaved % 2) == 0);
79075
79076 p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sizeof(duk_uint8_t *) * re_ctx.nsaved);
79077 DUK_UNREF(p_buf);
79078 re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(ctx, -1, NULL);
79079 DUK_ASSERT(re_ctx.saved != NULL);
79080
79081 /* [ ... re_obj input bc saved_buf ] */
79082
79083#if defined(DUK_USE_EXPLICIT_NULL_INIT)
79084 for (i = 0; i < re_ctx.nsaved; i++) {
79085 re_ctx.saved[i] = (duk_uint8_t *) NULL;
79086 }
79087#elif defined(DUK_USE_ZERO_BUFFER_DATA)
79088 /* buffer is automatically zeroed */
79089#else
79090 DUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
79091#endif
79092
79093 DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
79094 (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
79095 (long) re_ctx.steps_limit));
79096
79097 /*
79098 * Get starting character offset for match, and initialize 'sp' based on it.
79099 *
79100 * Note: lastIndex is non-configurable so it must be present (we check the
79101 * internal class of the object above, so we know it is). User code can set
79102 * its value to an arbitrary (garbage) value though; E5 requires that lastIndex
79103 * be coerced to a number before using. The code below works even if the
79104 * property is missing: the value will then be coerced to zero.
79105 *
79106 * Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
79107 * For instance, ToInteger(+Infinity) = +Infinity. We track the match offset
79108 * as an integer, but pre-check it to be inside the 32-bit range before the loop.
79109 * If not, the check in E5 Section 15.10.6.2, step 9.a applies.
79110 */
79111
79112 /* XXX: lastIndex handling produces a lot of asm */
79113
79114 /* [ ... re_obj input bc saved_buf ] */
79115
79116 duk_get_prop_stridx(ctx, -4, DUK_STRIDX_LAST_INDEX); /* -> [ ... re_obj input bc saved_buf lastIndex ] */
79117 (void) duk_to_int(ctx, -1); /* ToInteger(lastIndex) */
79118 d = duk_get_number(ctx, -1); /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
79119 duk_pop(ctx);
79120
79121 if (global) {
79122 if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
79123 /* match fail */
79124 char_offset = 0; /* not really necessary */
79125 DUK_ASSERT(match == 0);
79126 goto match_over;
79127 }
79128 char_offset = (duk_uint32_t) d;
79129 } else {
79130 /* lastIndex must be ignored for non-global regexps, but get the
79131 * value for (theoretical) side effects. No side effects can
79132 * really occur, because lastIndex is a normal property and is
79133 * always non-configurable for RegExp instances.
79134 */
79135 char_offset = (duk_uint32_t) 0;
79136 }
79137
79138 sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
79139
79140 /*
79141 * Match loop.
79142 *
79143 * Try matching at different offsets until match found or input exhausted.
79144 */
79145
79146 /* [ ... re_obj input bc saved_buf ] */
79147
79148 DUK_ASSERT(match == 0);
79149
79150 for (;;) {
79151 /* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
79152 DUK_ASSERT_DISABLE(char_offset >= 0);
79153 DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
79154
79155 /* Note: ctx.steps is intentionally not reset, it applies to the entire unanchored match */
79156 DUK_ASSERT(re_ctx.recursion_depth == 0);
79157
79158 DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
79159 (long) char_offset, (const void *) sp,
79160 (const void *) re_ctx.input, (const void *) re_ctx.input_end));
79161
79162 /*
79163 * Note:
79164 *
79165 * - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
79166 * conditions; a longjmp() will terminate the entire matching process.
79167 *
79168 * - Clearing saved[] is not necessary because backtracking does it
79169 *
79170 * - Backtracking also rewinds ctx.recursion back to zero, unless an
79171 * internal/limit error occurs (which causes a longjmp())
79172 *
79173 * - If we supported anchored matches, we would break out here
79174 * unconditionally; however, Ecmascript regexps don't have anchored
79175 * matches. It might make sense to implement a fast bail-out if
79176 * the regexp begins with '^' and sp is not 0: currently we'll just
79177 * run through the entire input string, trivially failing the match
79178 * at every non-zero offset.
79179 */
79180
79181 if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
79182 DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
79183 match = 1;
79184 break;
79185 }
79186
79187 /* advance by one character (code point) and one char_offset */
79188 char_offset++;
79189 if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
79190 /*
79191 * Note:
79192 *
79193 * - Intentionally attempt (empty) match at char_offset == k_input->clen
79194 *
79195 * - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
79196 * -> no need or use for a negative check
79197 */
79198
79199 DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
79200 break;
79201 }
79202
79203 /* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
79204 (void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
79205 }
79206
79207 match_over:
79208
79209 /*
79210 * Matching complete, create result array or return a 'null'. Update lastIndex
79211 * if necessary. See E5 Section 15.10.6.2.
79212 *
79213 * Because lastIndex is a character (not byte) offset, we need the character
79214 * length of the match which we conveniently get as a side effect of interning
79215 * the matching substring (0th index of result array).
79216 *
79217 * saved[0] start pointer (~ byte offset) of current match
79218 * saved[1] end pointer (~ byte offset) of current match (exclusive)
79219 * char_offset start character offset of current match (-> .index of result)
79220 * char_end_offset end character offset (computed below)
79221 */
79222
79223 /* [ ... re_obj input bc saved_buf ] */
79224
79225 if (match) {
79226#ifdef DUK_USE_ASSERTIONS
79227 duk_hobject *h_res;
79228#endif
79229 duk_uint32_t char_end_offset = 0;
79230
79231 DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
79232
79233 DUK_ASSERT(re_ctx.nsaved >= 2); /* must have start and end */
79234 DUK_ASSERT((re_ctx.nsaved % 2) == 0); /* and even number */
79235
79236 /* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
79237 * advantage of now. The array is not compacted either, as regexp match
79238 * objects are usually short lived.
79239 */
79240
79241 duk_push_array(ctx);
79242
79243#ifdef DUK_USE_ASSERTIONS
79244 h_res = duk_require_hobject(ctx, -1);
79248#endif
79249
79250 /* [ ... re_obj input bc saved_buf res_obj ] */
79251
79252 duk_push_u32(ctx, char_offset);
79254
79255 duk_dup(ctx, -4);
79257
79258 for (i = 0; i < re_ctx.nsaved; i += 2) {
79259 /* Captures which are undefined have NULL pointers and are returned
79260 * as 'undefined'. The same is done when saved[] pointers are insane
79261 * (this should, of course, never happen in practice).
79262 */
79263 if (re_ctx.saved[i] && re_ctx.saved[i+1] && re_ctx.saved[i+1] >= re_ctx.saved[i]) {
79264 duk_hstring *h_saved;
79265
79266 duk_push_lstring(ctx,
79267 (const char *) re_ctx.saved[i],
79268 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
79269 h_saved = duk_get_hstring(ctx, -1);
79270 DUK_ASSERT(h_saved != NULL);
79271
79272 if (i == 0) {
79273 /* Assumes that saved[0] and saved[1] are always
79274 * set by regexp bytecode (if not, char_end_offset
79275 * will be zero). Also assumes clen reflects the
79276 * correct char length.
79277 */
79278 char_end_offset = char_offset + DUK_HSTRING_GET_CHARLEN(h_saved);
79279 }
79280 } else {
79281 duk_push_undefined(ctx);
79282 }
79283
79284 /* [ ... re_obj input bc saved_buf res_obj val ] */
79285 duk_put_prop_index(ctx, -2, i / 2);
79286 }
79287
79288 /* [ ... re_obj input bc saved_buf res_obj ] */
79289
79290 /* NB: 'length' property is automatically updated by the array setup loop */
79291
79292 if (global) {
79293 /* global regexp: lastIndex updated on match */
79294 duk_push_u32(ctx, char_end_offset);
79296 } else {
79297 /* non-global regexp: lastIndex never updated on match */
79298 ;
79299 }
79300 } else {
79301 /*
79302 * No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
79303 * of 'global' flag of the RegExp. In particular, if lastIndex is invalid
79304 * initially, it is reset to zero.
79305 */
79306
79307 DUK_DDD(DUK_DDDPRINT("regexp does not match"));
79308
79309 duk_push_null(ctx);
79310
79311 /* [ ... re_obj input bc saved_buf res_obj ] */
79312
79313 duk_push_int(ctx, 0);
79316
79317 /* [ ... re_obj input bc saved_buf res_obj ] */
79318
79319 duk_insert(ctx, -5);
79320
79321 /* [ ... res_obj re_obj input bc saved_buf ] */
79323 duk_pop_n(ctx, 4);
79324
79325 /* [ ... res_obj ] */
79326
79327 /* XXX: these last tricks are unnecessary if the function is made
79328 * a genuine native function.
79329 */
79330}
79331
79333 duk__regexp_match_helper(thr, 0 /*force_global*/);
79334}
79335
79336/* This variant is needed by String.prototype.split(); it needs to perform
79337 * global-style matching on a cloned RegExp which is potentially non-global.
79338 */
79340 duk__regexp_match_helper(thr, 1 /*force_global*/);
79341}
79342
79343#else /* DUK_USE_REGEXP_SUPPORT */
79344
79345/* regexp support disabled */
79346
79347#endif /* DUK_USE_REGEXP_SUPPORT */
79348/*
79349 * Self tests to ensure execution environment is sane. Intended to catch
79350 * compiler/platform problems which cannot be detected at compile time.
79351 */
79352
79353/* include removed: duk_internal.h */
79354
79355#if defined(DUK_USE_SELF_TESTS)
79356
79357/*
79358 * Unions and structs for self tests
79359 */
79360
79361typedef union {
79362 double d;
79363 duk_uint8_t c[8];
79364} duk__test_double_union;
79365
79366#define DUK__DBLUNION_CMP_TRUE(a,b) do { \
79367 if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
79368 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares false (expected true)"); \
79369 } \
79370 } while (0)
79371
79372#define DUK__DBLUNION_CMP_FALSE(a,b) do { \
79373 if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
79374 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares true (expected false)"); \
79375 } \
79376 } while (0)
79377
79378typedef union {
79379 duk_uint32_t i;
79380 duk_uint8_t c[8];
79381} duk__test_u32_union;
79382
79383/*
79384 * Various sanity checks for typing
79385 */
79386
79387DUK_LOCAL void duk__selftest_types(void) {
79388 if (!(sizeof(duk_int8_t) == 1 &&
79389 sizeof(duk_uint8_t) == 1 &&
79390 sizeof(duk_int16_t) == 2 &&
79391 sizeof(duk_uint16_t) == 2 &&
79392 sizeof(duk_int32_t) == 4 &&
79393 sizeof(duk_uint32_t) == 4)) {
79394 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int{8,16,32}_t size");
79395 }
79396#if defined(DUK_USE_64BIT_OPS)
79397 if (!(sizeof(duk_int64_t) == 8 &&
79398 sizeof(duk_uint64_t) == 8)) {
79399 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int64_t size");
79400 }
79401#endif
79402
79403 if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
79404 /* Some internal code now assumes that all duk_uint_t values
79405 * can be expressed with a duk_size_t.
79406 */
79407 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_size_t is smaller than duk_uint_t");
79408 }
79409 if (!(sizeof(duk_int_t) >= 4)) {
79410 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_int_t is not 32 bits");
79411 }
79412}
79413
79414/*
79415 * Packed tval sanity
79416 */
79417
79418DUK_LOCAL void duk__selftest_packed_tval(void) {
79419#if defined(DUK_USE_PACKED_TVAL)
79420 if (sizeof(void *) > 4) {
79421 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: packed duk_tval in use but sizeof(void *) > 4");
79422 }
79423#endif
79424}
79425
79426/*
79427 * Two's complement arithmetic.
79428 */
79429
79430DUK_LOCAL void duk__selftest_twos_complement(void) {
79431 volatile int test;
79432 test = -1;
79433
79434 /* Note that byte order doesn't affect this test: all bytes in
79435 * 'test' will be 0xFF for two's complement.
79436 */
79437 if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
79438 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic");
79439 }
79440}
79441
79442/*
79443 * Byte order. Important to self check, because on some exotic platforms
79444 * there is no actual detection but rather assumption based on platform
79445 * defines.
79446 */
79447
79448DUK_LOCAL void duk__selftest_byte_order(void) {
79449 duk__test_u32_union u1;
79450 duk__test_double_union u2;
79451
79452 /*
79453 * >>> struct.pack('>d', 102030405060).encode('hex')
79454 * '4237c17c6dc40000'
79455 */
79456#if defined(DUK_USE_INTEGER_LE)
79457 u1.c[0] = 0xef; u1.c[1] = 0xbe; u1.c[2] = 0xad; u1.c[3] = 0xde;
79458#elif defined(DUK_USE_INTEGER_ME)
79459#error integer mixed endian not supported now
79460#elif defined(DUK_USE_INTEGER_BE)
79461 u1.c[0] = 0xde; u1.c[1] = 0xad; u1.c[2] = 0xbe; u1.c[3] = 0xef;
79462#else
79463#error unknown integer endianness
79464#endif
79465
79466#if defined(DUK_USE_DOUBLE_LE)
79467 u2.c[0] = 0x00; u2.c[1] = 0x00; u2.c[2] = 0xc4; u2.c[3] = 0x6d;
79468 u2.c[4] = 0x7c; u2.c[5] = 0xc1; u2.c[6] = 0x37; u2.c[7] = 0x42;
79469#elif defined(DUK_USE_DOUBLE_ME)
79470 u2.c[0] = 0x7c; u2.c[1] = 0xc1; u2.c[2] = 0x37; u2.c[3] = 0x42;
79471 u2.c[4] = 0x00; u2.c[5] = 0x00; u2.c[6] = 0xc4; u2.c[7] = 0x6d;
79472#elif defined(DUK_USE_DOUBLE_BE)
79473 u2.c[0] = 0x42; u2.c[1] = 0x37; u2.c[2] = 0xc1; u2.c[3] = 0x7c;
79474 u2.c[4] = 0x6d; u2.c[5] = 0xc4; u2.c[6] = 0x00; u2.c[7] = 0x00;
79475#else
79476#error unknown double endianness
79477#endif
79478
79479 if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
79480 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_uint32_t byte order");
79481 }
79482
79483 if (u2.d != (double) 102030405060.0) {
79484 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double byte order");
79485 }
79486}
79487
79488/*
79489 * DUK_BSWAP macros
79490 */
79491
79492DUK_LOCAL void duk__selftest_bswap_macros(void) {
79493 duk_uint32_t x32;
79494 duk_uint16_t x16;
79496 duk_double_t du_diff;
79497
79498 x16 = 0xbeefUL;
79499 x16 = DUK_BSWAP16(x16);
79500 if (x16 != (duk_uint16_t) 0xefbeUL) {
79501 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP16");
79502 }
79503
79504 x32 = 0xdeadbeefUL;
79505 x32 = DUK_BSWAP32(x32);
79506 if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
79507 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP32");
79508 }
79509
79510 /* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
79511 * (2.008366013071895,)
79512 */
79513
79514 du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
79515 du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
79517 du_diff = du.d - 2.008366013071895;
79518#if 0
79519 DUK_FPRINTF(DUK_STDERR, "du_diff: %lg\n", (double) du_diff);
79520#endif
79521 if (du_diff > 1e-15) {
79522 /* Allow very small lenience because some compilers won't parse
79523 * exact IEEE double constants (happened in matrix testing with
79524 * Linux gcc-4.8 -m32 at least).
79525 */
79526#if 0
79527 DUK_FPRINTF(DUK_STDERR, "Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
79528 (unsigned int) du.uc[0], (unsigned int) du.uc[1],
79529 (unsigned int) du.uc[2], (unsigned int) du.uc[3],
79530 (unsigned int) du.uc[4], (unsigned int) du.uc[5],
79531 (unsigned int) du.uc[6], (unsigned int) du.uc[7]);
79532#endif
79533 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_DBLUNION_DOUBLE_NTOH");
79534 }
79535}
79536
79537/*
79538 * Basic double / byte union memory layout.
79539 */
79540
79541DUK_LOCAL void duk__selftest_double_union_size(void) {
79542 if (sizeof(duk__test_double_union) != 8) {
79543 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: invalid union size");
79544 }
79545}
79546
79547/*
79548 * Union aliasing, see misc/clang_aliasing.c.
79549 */
79550
79551DUK_LOCAL void duk__selftest_double_aliasing(void) {
79552 duk__test_double_union a, b;
79553
79554 /* This testcase fails when Emscripten-generated code runs on Firefox.
79555 * It's not an issue because the failure should only affect packed
79556 * duk_tval representation, which is not used with Emscripten.
79557 */
79558#if !defined(DUK_USE_PACKED_TVAL)
79559 DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
79560 return;
79561#endif
79562
79563 /* Test signaling NaN and alias assignment in all endianness combinations.
79564 */
79565
79566 /* little endian */
79567 a.c[0] = 0x11; a.c[1] = 0x22; a.c[2] = 0x33; a.c[3] = 0x44;
79568 a.c[4] = 0x00; a.c[5] = 0x00; a.c[6] = 0xf1; a.c[7] = 0xff;
79569 b = a;
79570 DUK__DBLUNION_CMP_TRUE(&a, &b);
79571
79572 /* big endian */
79573 a.c[0] = 0xff; a.c[1] = 0xf1; a.c[2] = 0x00; a.c[3] = 0x00;
79574 a.c[4] = 0x44; a.c[5] = 0x33; a.c[6] = 0x22; a.c[7] = 0x11;
79575 b = a;
79576 DUK__DBLUNION_CMP_TRUE(&a, &b);
79577
79578 /* mixed endian */
79579 a.c[0] = 0x00; a.c[1] = 0x00; a.c[2] = 0xf1; a.c[3] = 0xff;
79580 a.c[4] = 0x11; a.c[5] = 0x22; a.c[6] = 0x33; a.c[7] = 0x44;
79581 b = a;
79582 DUK__DBLUNION_CMP_TRUE(&a, &b);
79583}
79584
79585/*
79586 * Zero sign, see misc/tcc_zerosign2.c.
79587 */
79588
79589DUK_LOCAL void duk__selftest_double_zero_sign(void) {
79590 duk__test_double_union a, b;
79591
79592 a.d = 0.0;
79593 b.d = -a.d;
79594 DUK__DBLUNION_CMP_FALSE(&a, &b);
79595}
79596
79597/*
79598 * Struct size/alignment if platform requires it
79599 *
79600 * There are some compiler specific struct padding pragmas etc in use, this
79601 * selftest ensures they're correctly detected and used.
79602 */
79603
79604DUK_LOCAL void duk__selftest_struct_align(void) {
79605#if (DUK_USE_ALIGN_BY == 4)
79606 if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
79607 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 4");
79608 }
79609#elif (DUK_USE_ALIGN_BY == 8)
79610 if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
79611 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 8");
79612 }
79613#elif (DUK_USE_ALIGN_BY == 1)
79614 /* no check */
79615#else
79616#error invalid DUK_USE_ALIGN_BY
79617#endif
79618}
79619
79620/*
79621 * 64-bit arithmetic
79622 *
79623 * There are some platforms/compilers where 64-bit types are available
79624 * but don't work correctly. Test for known cases.
79625 */
79626
79627DUK_LOCAL void duk__selftest_64bit_arithmetic(void) {
79628#if defined(DUK_USE_64BIT_OPS)
79629 volatile duk_int64_t i;
79630 volatile duk_double_t d;
79631
79632 /* Catch a double-to-int64 cast issue encountered in practice. */
79633 d = 2147483648.0;
79634 i = (duk_int64_t) d;
79635 if (i != 0x80000000LL) {
79636 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: casting 2147483648.0 to duk_int64_t failed");
79637 }
79638#else
79639 /* nop */
79640#endif
79641}
79642
79643/*
79644 * Casting
79645 */
79646
79647DUK_LOCAL void duk__selftest_cast_double_to_small_uint(void) {
79648 /*
79649 * https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
79650 */
79651
79652 duk_double_t d1, d2;
79654
79655 duk_double_t d1v, d2v;
79657
79658 /* Test without volatiles */
79659
79660 d1 = 1.0;
79661 u = (duk_small_uint_t) d1;
79662 d2 = (duk_double_t) u;
79663
79664 if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
79665 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
79666 }
79667
79668 /* Same test with volatiles */
79669
79670 d1v = 1.0;
79671 uv = (duk_small_uint_t) d1v;
79672 d2v = (duk_double_t) uv;
79673
79674 if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
79675 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
79676 }
79677}
79678
79679DUK_LOCAL void duk__selftest_cast_double_to_uint32(void) {
79680 /*
79681 * This test fails on an exotic ARM target; double-to-uint
79682 * cast is incorrectly clamped to -signed- int highest value.
79683 *
79684 * https://github.com/svaarala/duktape/issues/336
79685 */
79686
79687 duk_double_t dv;
79688 duk_uint32_t uv;
79689
79690 dv = 3735928559.0; /* 0xdeadbeef in decimal */
79691 uv = (duk_uint32_t) dv;
79692
79693 if (uv != 0xdeadbeefUL) {
79694 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_uint32_t cast failed");
79695 }
79696}
79697
79698/*
79699 * Self test main
79700 */
79701
79702DUK_INTERNAL void duk_selftest_run_tests(void) {
79703 duk__selftest_types();
79704 duk__selftest_packed_tval();
79705 duk__selftest_twos_complement();
79706 duk__selftest_byte_order();
79707 duk__selftest_bswap_macros();
79708 duk__selftest_double_union_size();
79709 duk__selftest_double_aliasing();
79710 duk__selftest_double_zero_sign();
79711 duk__selftest_struct_align();
79712 duk__selftest_64bit_arithmetic();
79713 duk__selftest_cast_double_to_small_uint();
79714 duk__selftest_cast_double_to_uint32();
79715}
79716
79717#undef DUK__DBLUNION_CMP_TRUE
79718#undef DUK__DBLUNION_CMP_FALSE
79719
79720#endif /* DUK_USE_SELF_TESTS */
79721/* include removed: duk_internal.h */
79722
79723#if defined(DUK_USE_FASTINT)
79724
79725/*
79726 * Manually optimized double-to-fastint downgrade check.
79727 *
79728 * This check has a large impact on performance, especially for fastint
79729 * slow paths, so must be changed carefully. The code should probably be
79730 * optimized for the case where the result does not fit into a fastint,
79731 * to minimize the penalty for "slow path code" dealing with fractions etc.
79732 *
79733 * At least on one tested soft float ARM platform double-to-int64 coercion
79734 * is very slow (and sometimes produces incorrect results, see self tests).
79735 * This algorithm combines a fastint compatibility check and extracting the
79736 * integer value from an IEEE double for setting the tagged fastint. For
79737 * other platforms a more naive approach might be better.
79738 *
79739 * See doc/fastint.rst for details.
79740 */
79741
79742DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x) {
79744 duk_int64_t i;
79745 duk_small_int_t expt;
79746 duk_small_int_t shift;
79747
79748 /* XXX: optimize for packed duk_tval directly? */
79749
79750 du.d = x;
79751 i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
79752 expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
79753 shift = expt - 1023;
79754
79755 if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */
79756 duk_int64_t t;
79757
79758 if (((0x000fffffffffffffLL >> shift) & i) == 0) {
79759 t = i | 0x0010000000000000LL; /* implicit leading one */
79760 t = t & 0x001fffffffffffffLL;
79761 t = t >> (52 - shift);
79762 if (i < 0) {
79763 t = -t;
79764 }
79765 DUK_TVAL_SET_FASTINT(tv, t);
79766 return;
79767 }
79768 } else if (shift == -1023) { /* exponent 0 */
79769 if (i >= 0 && (i & 0x000fffffffffffffLL) == 0) {
79770 /* Note: reject negative zero. */
79771 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
79772 return;
79773 }
79774 } else if (shift == 47) { /* exponent 1070 */
79775 if (i < 0 && (i & 0x000fffffffffffffLL) == 0) {
79776 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
79777 return;
79778 }
79779 }
79780
79781 DUK_TVAL_SET_DOUBLE(tv, x);
79782 return;
79783}
79784
79785/*
79786 * Manually optimized number-to-double conversion
79787 */
79788
79789#if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
79790DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
79792 duk_uint64_t t;
79793
79794 t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
79795 if ((t >> 48) != DUK_TAG_FASTINT) {
79796 return tv->d;
79797 } else if (t & 0x0000800000000000ULL) {
79798 t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */
79799 t = t & 0x0000ffffffffffffULL; /* negative */
79800 t |= 0xc330000000000000ULL;
79801 DUK_DBLUNION_SET_UINT64(&du, t);
79802 return du.d + 4503599627370496.0; /* 1 << 52 */
79803 } else if (t != 0) {
79804 t &= 0x0000ffffffffffffULL; /* positive */
79805 t |= 0x4330000000000000ULL;
79806 DUK_DBLUNION_SET_UINT64(&du, t);
79807 return du.d - 4503599627370496.0; /* 1 << 52 */
79808 } else {
79809 return 0.0; /* zero */
79810 }
79811}
79812#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
79813
79814#if 0 /* unused */
79815#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
79816DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
79818 duk_uint64_t t;
79819
79820 DUK_ASSERT(tv->t == DUK__TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
79821
79822 if (tv->t == DUK_TAG_FASTINT) {
79823 if (tv->v.fi >= 0) {
79824 t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
79825 DUK_DBLUNION_SET_UINT64(&du, t);
79826 return du.d - 4503599627370496.0; /* 1 << 52 */
79827 } else {
79828 t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
79829 DUK_DBLUNION_SET_UINT64(&du, t);
79830 return du.d + 4503599627370496.0; /* 1 << 52 */
79831 }
79832 } else {
79833 return tv->v.d;
79834 }
79835}
79836#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
79837#endif /* 0 */
79838
79839#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
79840DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
79842 duk_uint64_t t;
79843
79844 DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
79845
79846 if (tv->v.fi >= 0) {
79847 t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
79848 DUK_DBLUNION_SET_UINT64(&du, t);
79849 return du.d - 4503599627370496.0; /* 1 << 52 */
79850 } else {
79851 t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
79852 DUK_DBLUNION_SET_UINT64(&du, t);
79853 return du.d + 4503599627370496.0; /* 1 << 52 */
79854 }
79855}
79856#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
79857
79858#endif /* DUK_USE_FASTINT */
79859/*
79860 * Unicode support tables automatically generated during build.
79861 */
79862
79863/* include removed: duk_internal.h */
79864
79865/*
79866 * Unicode tables containing ranges of Unicode characters in a
79867 * packed format. These tables are used to match non-ASCII
79868 * characters of complex productions by resorting to a linear
79869 * range-by-range comparison. This is very slow, but is expected
79870 * to be very rare in practical Ecmascript source code, and thus
79871 * compactness is most important.
79872 *
79873 * The tables are matched using uni_range_match() and the format
79874 * is described in src/extract_chars.py.
79875 */
79876
79877#ifdef DUK_USE_SOURCE_NONBMP
79878/* IdentifierStart production with ASCII excluded */
79879/* duk_unicode_ids_noa[] */
79880/*
79881 * Automatically generated by extract_chars.py, do not edit!
79882 */
79883
79884const duk_uint8_t duk_unicode_ids_noa[791] = {
79885249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
79886240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
7988718,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
79888101,10,4,15,9,240,159,157,242,100,15,4,8,159,1,98,102,115,19,240,98,98,4,
7988952,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,2,130,34,
79890240,98,98,18,68,15,4,15,1,31,21,115,19,240,98,98,18,68,15,16,18,47,1,15,3,
798912,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,146,68,15,12,23,31,21,
79892114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,15,3,31,10,86,
79893240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,34,2,3,18,50,
7989426,3,66,15,7,31,20,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,24,37,
79895205,15,3,241,107,241,178,4,255,224,59,35,54,32,35,63,25,35,63,17,35,54,32,
7989635,62,47,41,35,63,51,241,127,0,240,47,69,223,254,21,227,240,18,240,166,243,
79897180,47,1,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,137,241,
79898146,6,243,107,240,223,37,240,227,76,241,207,7,111,42,240,122,242,95,68,15,
7989979,241,255,3,111,41,240,238,31,2,241,111,12,241,79,27,43,241,79,93,50,63,0,
79900251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,15,63,37,38,32,66,38,67,53,
7990192,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
79902240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
79903122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
7990474,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
79905255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
7990647,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
7990734,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
79908240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
79909240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
7991024,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
79911171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,241,91,47,10,47,3,
7991233,46,61,241,79,107,243,127,37,255,223,13,79,33,242,31,15,240,63,11,242,
79913127,14,63,20,87,36,241,207,142,255,226,86,83,2,241,194,20,3,240,127,156,
79914240,107,240,175,184,15,1,50,34,240,191,30,240,223,117,242,107,240,107,240,
7991563,127,243,159,254,42,239,37,243,223,29,255,238,68,255,226,97,248,63,83,
79916255,234,145,255,227,33,255,240,2,44,95,254,18,191,255,0,52,187,31,255,0,18,
79917242,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,
79918255,224,70,63,9,47,9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,
79919240,1,114,143,255,0,149,201,241,191,254,242,124,252,239,255,0,46,214,255,
79920225,16,0,
79921};
79922#else
79923/* IdentifierStart production with ASCII and non-BMP excluded */
79924/* duk_unicode_ids_noabmp[] */
79925/*
79926 * Automatically generated by extract_chars.py, do not edit!
79927 */
79928
79929const duk_uint8_t duk_unicode_ids_noabmp[611] = {
79930249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
79931240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
7993218,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
79933101,10,4,15,9,240,159,157,242,100,15,4,8,159,1,98,102,115,19,240,98,98,4,
7993452,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,2,130,34,
79935240,98,98,18,68,15,4,15,1,31,21,115,19,240,98,98,18,68,15,16,18,47,1,15,3,
799362,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,146,68,15,12,23,31,21,
79937114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,15,3,31,10,86,
79938240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,34,2,3,18,50,
7993926,3,66,15,7,31,20,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,24,37,
79940205,15,3,241,107,241,178,4,255,224,59,35,54,32,35,63,25,35,63,17,35,54,32,
7994135,62,47,41,35,63,51,241,127,0,240,47,69,223,254,21,227,240,18,240,166,243,
79942180,47,1,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,137,241,
79943146,6,243,107,240,223,37,240,227,76,241,207,7,111,42,240,122,242,95,68,15,
7994479,241,255,3,111,41,240,238,31,2,241,111,12,241,79,27,43,241,79,93,50,63,0,
79945251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,15,63,37,38,32,66,38,67,53,
7994692,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
79947240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
79948122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
7994974,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
79950255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
7995147,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
7995234,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
79953240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
79954240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
7995524,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
79956171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,0,
79957};
79958#endif
79959
79960#ifdef DUK_USE_SOURCE_NONBMP
79961/* IdentifierStart production with Letter and ASCII excluded */
79962/* duk_unicode_ids_m_let_noa[] */
79963/*
79964 * Automatically generated by extract_chars.py, do not edit!
79965 */
79966
79967const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
79968255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
79969249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,48,
79970};
79971#else
79972/* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
79973/* duk_unicode_ids_m_let_noabmp[] */
79975 * Automatically generated by extract_chars.py, do not edit!
79976 */
79977
79978const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
79979255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
79980249,0,
79981};
79982#endif
79983
79984#ifdef DUK_USE_SOURCE_NONBMP
79985/* IdentifierPart production with IdentifierStart and ASCII excluded */
79986/* duk_unicode_idp_m_ids_noa[] */
79987/*
79988 * Automatically generated by extract_chars.py, do not edit!
79989 */
79990
79991const duk_uint8_t duk_unicode_idp_m_ids_noa[397] = {
79992255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
79993245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
7999436,241,210,249,99,242,130,47,2,38,177,57,240,50,242,160,38,49,50,160,177,
7999557,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,97,57,
79996240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,240,50,
79997242,198,34,35,129,193,57,240,65,242,160,38,34,35,129,193,57,240,65,242,198,
7999834,35,160,177,57,240,65,243,128,85,32,39,240,65,242,240,54,215,41,244,144,
7999953,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,111,4,41,
80000211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,241,1,243,
8000179,14,160,57,241,50,57,248,16,246,139,91,185,245,47,1,129,121,242,244,242,
80002185,47,13,58,121,245,132,242,31,1,201,240,56,210,241,9,105,241,237,242,47,
800034,153,121,246,130,47,5,80,80,251,255,23,240,115,255,225,0,31,35,31,5,15,
80004109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,255,0,100,
80005121,159,55,13,31,100,31,254,0,64,64,80,240,148,244,161,242,79,1,201,127,2,
80006240,9,240,231,240,188,241,227,242,29,240,25,244,29,208,145,57,241,48,242,
8000796,34,49,97,32,255,224,21,114,19,159,255,0,62,24,15,254,29,95,0,240,38,209,
80008240,162,251,41,241,112,255,225,177,15,254,25,105,255,228,75,34,22,63,26,37,
8000915,254,75,66,242,126,241,25,240,34,241,250,255,240,10,249,228,69,151,54,
80010241,3,248,98,255,228,125,242,47,255,12,23,244,254,0,
80011};
80012#else
80013/* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
80014/* duk_unicode_idp_m_ids_noabmp[] */
80015/*
80016 * Automatically generated by extract_chars.py, do not edit!
80017 */
80018
80019const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348] = {
80020255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
80021245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
8002236,241,210,249,99,242,130,47,2,38,177,57,240,50,242,160,38,49,50,160,177,
8002357,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,97,57,
80024240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,240,50,
80025242,198,34,35,129,193,57,240,65,242,160,38,34,35,129,193,57,240,65,242,198,
8002634,35,160,177,57,240,65,243,128,85,32,39,240,65,242,240,54,215,41,244,144,
8002753,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,111,4,41,
80028211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,241,1,243,
8002979,14,160,57,241,50,57,248,16,246,139,91,185,245,47,1,129,121,242,244,242,
80030185,47,13,58,121,245,132,242,31,1,201,240,56,210,241,9,105,241,237,242,47,
800314,153,121,246,130,47,5,80,80,251,255,23,240,115,255,225,0,31,35,31,5,15,
80032109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,255,0,100,
80033121,159,55,13,31,100,31,254,0,64,64,80,240,148,244,161,242,79,1,201,127,2,
80034240,9,240,231,240,188,241,227,242,29,240,25,244,29,208,145,57,241,48,242,
8003596,34,49,97,32,255,224,21,114,19,159,255,0,62,24,15,254,29,95,0,240,38,209,
80036240,162,251,41,241,112,0,
80037};
80038#endif
80039
80040/*
80041 * Case conversion tables generated using src/extract_caseconv.py.
80042 */
80043
80044/* duk_unicode_caseconv_uc[] */
80045/* duk_unicode_caseconv_lc[] */
80046
80047/*
80048 * Automatically generated by extract_caseconv.py, do not edit!
80049 */
80050
80051const duk_uint8_t duk_unicode_caseconv_uc[1288] = {
80052132,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
80053128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
80054104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,15,128,15,132,8,31,16,
8005531,24,12,62,64,62,80,32,124,192,124,224,64,250,0,250,64,97,246,1,246,129,3,
80056238,3,247,64,135,220,135,242,2,15,187,15,237,2,31,120,31,248,4,62,244,63,
80057212,8,125,240,127,232,16,253,128,253,192,33,253,1,253,128,67,252,3,253,0,
80058136,92,8,88,8,18,104,18,91,26,44,48,44,0,94,90,0,33,64,155,253,7,252,132,
80059212,0,32,32,32,6,0,76,192,76,129,128,157,0,156,136,1,75,1,74,46,2,244,2,
80060242,12,6,12,6,8,16,13,8,13,0,48,27,64,27,48,64,57,192,57,162,0,119,192,119,
80061132,128,252,128,252,20,2,35,2,34,18,4,142,4,140,20,13,196,13,192,16,30,200,
8006230,192,192,70,16,70,2,32,145,96,145,70,193,48,129,48,67,130,104,130,104,44,
8006330,1,30,0,150,61,66,61,64,192,125,68,125,100,33,99,65,99,56,50,200,18,200,
800646,69,157,133,157,96,169,144,105,144,11,211,64,211,64,12,167,35,167,34,15,
8006578,103,78,100,126,157,234,157,228,21,59,253,59,240,90,122,26,122,0,163,128,
80066214,128,214,2,1,197,1,196,6,3,140,3,136,12,7,200,7,196,16,20,0,13,48,32,63,
80067128,63,112,69,142,101,142,64,130,1,136,1,135,4,3,114,3,112,8,26,120,202,
80068120,176,65,1,30,1,29,130,2,105,1,150,5,255,96,22,160,115,128,31,224,47,0,
8006938,32,9,32,47,224,10,96,48,0,72,96,50,64,50,32,50,160,62,192,51,32,51,0,51,
8007064,71,160,51,192,68,0,53,0,52,224,55,224,62,224,59,160,49,192,62,96,62,32,
8007174,5,141,224,74,37,141,160,74,69,142,0,74,96,48,32,74,128,48,192,75,32,49,
80072224,75,96,50,0,76,0,50,96,76,96,50,128,76,180,241,160,77,0,50,224,77,101,
80073140,64,78,37,141,192,78,64,51,160,78,160,51,224,79,165,140,128,81,0,53,192,
8007481,32,72,128,81,128,72,160,82,64,54,224,104,160,115,32,110,224,110,192,117,
80075128,112,192,120,64,116,96,121,128,113,128,122,0,114,64,122,32,115,0,122,
80076160,116,192,122,192,116,0,122,224,121,224,126,0,115,64,126,32,116,32,126,
8007764,127,32,126,160,114,160,153,224,152,3,175,52,239,163,175,165,140,99,211,
8007899,204,3,247,192,115,35,252,163,253,132,41,196,38,68,48,132,48,101,140,37,
80079140,5,140,160,71,69,140,192,71,217,128,55,224,5,48,5,48,20,152,10,240,1,56,
800807,194,0,74,3,12,3,144,192,230,64,194,0,192,64,236,48,58,80,48,128,48,16,88,
80081120,20,212,21,72,122,90,0,72,3,49,30,151,128,21,0,194,7,166,32,5,112,48,
80082161,233,152,1,100,12,40,122,106,0,65,2,190,31,80,128,233,64,196,199,212,
80083176,58,80,49,48,48,1,245,76,14,148,12,76,12,4,125,91,3,165,3,19,3,66,31,
80084128,135,194,0,230,71,224,97,240,144,57,145,248,40,124,40,14,100,126,14,31,
8008511,3,153,31,132,135,195,0,230,71,225,97,240,208,57,145,248,104,124,56,14,
80086100,126,30,31,15,3,153,31,136,135,194,0,230,71,226,97,240,144,57,145,248,
80087168,124,40,14,100,126,46,31,11,3,153,31,140,135,195,0,230,71,227,97,240,
80088208,57,145,248,232,124,56,14,100,126,62,31,15,3,153,31,144,135,202,0,230,
8008971,228,97,242,144,57,145,249,40,124,168,14,100,126,78,31,43,3,153,31,148,
80090135,203,0,230,71,229,97,242,208,57,145,249,104,124,184,14,100,126,94,31,47,
800913,153,31,152,135,202,0,230,71,230,97,242,144,57,145,249,168,124,168,14,100,
80092126,110,31,43,3,153,31,156,135,203,0,230,71,231,97,242,208,57,145,249,232,
80093124,184,14,100,126,126,31,47,3,153,31,160,135,218,0,230,71,232,97,246,144,
8009457,145,250,40,125,168,14,100,126,142,31,107,3,153,31,164,135,219,0,230,71,
80095233,97,246,208,57,145,250,104,125,184,14,100,126,158,31,111,3,153,31,168,
80096135,218,0,230,71,234,97,246,144,57,145,250,168,125,168,14,100,126,174,31,
80097107,3,153,31,172,135,219,0,230,71,235,97,246,208,57,145,250,232,125,184,14,
80098100,126,190,31,111,3,153,31,178,135,238,128,230,71,236,224,57,16,57,145,
80099251,72,14,24,14,100,126,218,3,145,3,66,31,183,192,228,64,208,128,230,71,
80100239,32,57,16,57,145,252,40,127,40,14,100,127,14,3,151,3,153,31,196,128,226,
8010164,230,71,241,160,57,112,52,33,252,124,14,92,13,8,14,100,127,50,3,151,3,
80102153,31,210,192,230,64,194,0,192,7,244,240,57,144,48,128,48,17,253,104,14,
80103100,13,8,127,95,3,153,3,8,3,66,31,226,192,233,64,194,0,192,7,248,240,58,80,
8010448,128,48,17,254,72,14,132,12,76,127,154,3,165,3,66,31,231,192,233,64,194,
801050,208,135,252,161,255,160,57,145,255,56,14,164,14,100,127,210,3,143,3,153,
8010631,246,128,234,64,208,135,253,240,58,144,52,32,57,145,255,200,14,164,14,
80107103,236,2,0,70,0,70,251,1,128,17,128,18,126,192,160,4,96,4,207,176,60,1,24,
801081,24,1,39,236,19,0,70,0,70,0,76,251,5,128,20,192,21,62,193,160,5,48,5,79,
80109177,56,21,16,21,27,236,82,5,68,5,53,251,21,129,81,1,78,254,197,160,84,224,
8011084,111,177,120,21,16,20,244,
80111};
80112const duk_uint8_t duk_unicode_caseconv_lc[616] = {
80113144,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
80114235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
801150,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,15,132,15,128,8,31,24,
8011631,16,12,62,80,62,64,32,124,224,124,192,64,250,64,250,0,97,246,129,246,1,3,
80117241,3,240,2,7,230,7,228,4,15,212,15,208,8,31,184,31,176,4,63,116,62,224,8,
80118127,32,125,200,32,254,192,254,128,33,253,161,247,96,67,253,3,252,0,135,250,
80119135,222,129,15,252,15,188,2,31,250,31,124,4,66,192,66,224,64,146,216,147,
8012064,209,96,1,97,130,242,199,224,35,240,95,228,63,232,38,161,1,0,1,1,48,2,
80121100,2,102,12,4,228,4,232,64,10,80,10,89,112,23,144,23,160,96,48,64,48,96,
80122128,104,0,104,65,128,217,128,218,2,1,203,1,204,18,3,188,3,190,36,7,200,7,
80123204,16,15,192,15,201,64,34,32,34,49,32,72,192,72,225,64,220,0,220,65,1,236,
801241,236,140,4,96,4,97,34,9,20,9,22,108,19,4,19,8,56,38,128,38,138,193,224,1,
80125224,25,99,212,3,212,44,7,214,71,212,66,22,51,150,52,3,44,128,44,129,100,89,
80126214,89,216,10,153,2,153,4,189,52,5,52,8,202,114,42,114,48,244,230,84,230,
80127103,233,222,105,222,129,83,191,83,191,133,167,160,167,161,10,48,13,48,20,0,
8012832,26,192,26,208,64,56,128,56,192,192,113,64,113,129,1,251,129,252,2,44,
80129114,44,115,4,16,12,56,12,64,32,27,128,27,144,64,211,197,211,198,2,8,6,88,9,
80130164,16,17,216,17,224,47,245,1,120,0,255,1,129,2,83,1,134,2,84,1,142,1,221,
801311,143,2,89,1,144,2,91,1,145,1,146,1,147,2,96,1,148,2,99,1,151,2,104,1,152,
801321,153,1,157,2,114,1,159,2,117,1,167,1,168,1,174,2,136,1,183,2,146,1,241,1,
80133243,1,246,1,149,1,247,1,191,2,32,1,158,2,58,44,101,2,61,1,154,2,62,44,102,
801342,67,1,128,2,68,2,137,2,69,2,140,3,118,3,119,3,134,3,172,3,140,3,204,3,207,
801353,215,3,244,3,184,3,249,3,242,4,192,4,207,30,158,0,223,31,188,31,179,31,
80136204,31,195,31,236,31,229,31,252,31,243,33,38,3,201,33,42,0,107,33,43,0,229,
8013733,50,33,78,33,131,33,132,44,96,44,97,44,98,2,107,44,99,29,125,44,100,2,
80138125,44,109,2,81,44,110,2,113,44,111,2,80,44,112,2,82,167,125,29,121,167,
80139141,2,101,2,2,97,0,52,129,131,128,
80140};
80141
80142#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
80143/*
80144 * Automatically generated by extract_caseconv.py, do not edit!
80145 */
80146
80147const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
801480,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,
8014928,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
8015053,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
8015178,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,
8015271,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
80153126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
80154144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
80155162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
80156180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
80157198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
80158216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
80159202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
80160220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
80161270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
80162288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
80163306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
80164323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
80165342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
80166360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
80167377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
80168395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
80169544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
80170431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
80171450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
80172467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
80173486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
80174504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
80175522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
80176540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
80177558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
8017811391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
8017911373,11376,385,390,597,393,394,600,399,602,400,604,605,606,607,403,609,
80180610,404,612,42893L,614,615,407,406,618,11362,620,621,622,412,624,11374,413,
80181627,628,415,630,631,632,633,634,635,636,11364,638,639,422,641,642,425,644,
80182645,646,647,430,580,433,434,581,653,654,655,656,657,439,659,660,661,662,
80183663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,
80184681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,
80185699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,
80186717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,
80187735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,
80188753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,
80189771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,
80190789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,
80191807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,
80192825,826,827,828,829,830,831,832,833,834,835,836,921,838,839,840,841,842,
80193843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,
80194861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,
80195879,880,880,882,882,884,885,886,886,888,889,890,1021,1022,1023,894,895,896,
80196897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,
80197915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,
80198933,934,935,936,937,938,939,902,904,905,906,944,913,914,915,916,917,918,
80199919,920,921,922,923,924,925,926,927,928,929,931,931,932,933,934,935,936,
80200937,938,939,908,910,911,975,914,920,978,979,980,934,928,975,984,984,986,
80201986,988,988,990,990,992,992,994,994,996,996,998,998,1000,1000,1002,1002,
802021004,1004,1006,1006,922,929,1017,1011,1012,917,1014,1015,1015,1017,1018,
802031018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,
802041034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,
802051049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,
802061064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,1043,1044,1045,1046,
802071047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,
802081062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,1025,1026,1027,1028,
802091029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1120,1120,1122,1122,
802101124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,1134,1136,1136,1138,
802111138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,1150,1150,1152,1152,
802121154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,1164,1166,1166,1168,
802131168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,1180,1180,1182,1182,
802141184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,1194,1196,1196,1198,
802151198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,1210,1210,1212,1212,
802161214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,1225,1225,1227,1227,
802171229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,1240,1240,1242,1242,
802181244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,1254,1256,1256,1258,
802191258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,1270,1270,1272,1272,
802201274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,1284,1286,1286,1288,
802211288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,1300,1300,1302,1302,
802221304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,1314,1316,1316,1318,
802231318,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,
802241334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,
802251349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,
802261364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1329,1330,
802271331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,
802281346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,
802291361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,1420,1421,1422,1423,
802301424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,
802311439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,
802321454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,
802331469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,
802341484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,
802351499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,
802361514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,
802371529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,
802381544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,
802391559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,
802401574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,
802411589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,
802421604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,
802431619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,
802441634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,
802451649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,
802461664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,
802471679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,
802481694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,
802491709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,
802501724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,
802511739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,
802521754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,
802531769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,
802541784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,
802551799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,
802561814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,
802571829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,
802581844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,
802591859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,
802601874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,
802611889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,
802621904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,
802631919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,
802641934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,
802651949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,
802661964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,
802671979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,
802681994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,
802692009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,
802702024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,
802712039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,
802722054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,
802732069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,
802742084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,
802752099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,
802762114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,
802772129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,
802782144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,
802792159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,
802802174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,
802812189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,
802822204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,
802832219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,
802842234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,
802852249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,
802862264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,
802872279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,
802882294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,
802892309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,
802902324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,
802912339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,
802922354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,
802932369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,
802942384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,
802952399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,
802962414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,
802972429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,
802982444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,
802992459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,
803002474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,
803012489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,
803022504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,
803032519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,
803042534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,
803052549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562,2563,
803062564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,
803072579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,
803082594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,
803092609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,
803102624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,
803112639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,
803122654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,
803132669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,
803142684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,
803152699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,
803162714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,
803172729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,
803182744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,
803192759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,
803202774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,
803212789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,
803222804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,
803232819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,
803242834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,
803252849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,
803262864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,
803272879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,
803282894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,
803292909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,
803302924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,
803312939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,
803322954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,
803332969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,
803342984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,
803352999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,
803363014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,
803373029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,
803383044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,
803393059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,
803403074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,
803413089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,
803423104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,
803433119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,
803443134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,
803453149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,
803463164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,
803473179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,
803483194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,
803493209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,
803503224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,
803513239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,
803523254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,
803533269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,
803543284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,
803553299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,
803563314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,
803573329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,
803583344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,
803593359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,
803603374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,
803613389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,
803623404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,
803633419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,
803643434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,
803653449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,
803663464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,
803673479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,
803683494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,
803693509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,
803703524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,
803713539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,
803723554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,
803733569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,
803743584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,
803753599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,
803763614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,
803773629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,
803783644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,
803793659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,
803803674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685,3686,3687,3688,
803813689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,
803823704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,
803833719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,
803843734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,
803853749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,
803863764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,
803873779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,
803883794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,
803893809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,
803903824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,
803913839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852,3853,
803923854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,
803933869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,
803943884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,
803953899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,
803963914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,
803973929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,
803983944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,
803993959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,
804003974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,
804013989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,
804024004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,
804034019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,
804044034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,
804054049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,
804064064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,
804074079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,
804084094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,
804094109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,
804104124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,
804114139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,
804124154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,
804134169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,
804144184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,
804154199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,
804164214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4226,4227,4228,
804174229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,
804184244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,
804194259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,
804204274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,
804214289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,
804224304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,
804234319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,
804244334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,
804254349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,
804264364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,
804274379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,
804284394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,
804294409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,4420,4421,4422,4423,
804304424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,
804314439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,
804324454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,
804334469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,
804344484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,
804354499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,
804364514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,
804374529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,
804384544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,
804394559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,
804404574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,
804414589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,
804424604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,
804434619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,
804444634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,
804454649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,
804464664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,
804474679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,
804484694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,
804494709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,
804504724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,
804514739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,
804524754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,
804534769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,
804544784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796,4797,4798,
804554799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,
804564814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,
804574829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,
804584844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,
804594859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,
804604874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,
804614889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,
804624904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,
804634919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,
804644934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,
804654949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,
804664964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,
804674979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,4992,4993,
804684994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,
804695009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,
804705024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,
804715039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,
804725054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,
804735069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,
804745084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,
804755099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,
804765114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,
804775129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,
804785144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,
804795159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,
804805174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,
804815189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,
804825204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,
804835219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,
804845234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,
804855249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,
804865264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,
804875279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,
804885294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,
804895309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,
804905324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,
804915339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,
804925354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,
804935369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,
804945384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,
804955399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,
804965414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,
804975429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,
804985444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,
804995459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,
805005474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,
805015489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,
805025504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,
805035519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,
805045534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,
805055549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,
805065564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,
805075579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,
805085594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,
805095609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,
805105624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,5635,5636,5637,5638,
805115639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,
805125654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,
805135669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,
805145684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,
805155699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,
805165714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,
805175729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,
805185744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,
805195759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,
805205774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,
805215789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,
805225804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,
805235819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,
805245834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,
805255849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,
805265864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876,5877,5878,
805275879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892,5893,
805285894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908,
805295909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,
805305924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,
805315939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952,5953,
805325954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,
805335969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,
805345984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,
805355999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,
805366014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,
805376029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,
805386044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,
805396059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071,6072,6073,
805406074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,
805416089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102,6103,
805426104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,
805436119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132,6133,
805446134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,6145,6146,6147,6148,
805456149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,
805466164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,
805476179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,
805486194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,
805496209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,
805506224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,
805516239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,
805526254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,6265,6266,6267,6268,
805536269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,
805546284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,
805556299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6313,
805566314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,
805576329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,6340,6341,6342,6343,
805586344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,
805596359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,
805606374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,
805616389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,6400,6401,6402,6403,
805626404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,
805636419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6431,6432,6433,
805646434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,6445,6446,6447,6448,
805656449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6460,6461,6462,6463,
805666464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,6475,6476,6477,6478,
805676479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,
805686494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,
805696509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,6520,6521,6522,6523,
805706524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,
805716539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,
805726554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,
805736569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,6582,6583,
805746584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,6598,
805756599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613,
805766614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,
805776629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,6640,6641,6642,6643,
805786644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,
805796659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,
805806674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,
805816689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,
805826704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,
805836719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,
805846734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,6746,6747,6748,
805856749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,
805866764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,
805876779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,
805886794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,
805896809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,
805906824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,6837,6838,
805916839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,
805926854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,
805936869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,
805946884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,
805956899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,6910,6911,6912,6913,
805966914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,
805976929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,
805986944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,
805996959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,
806006974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,6985,6986,6987,6988,
806016989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7002,7003,
806027004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,7015,7016,7017,7018,
806037019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,7030,7031,7032,7033,
806047034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,7045,7046,7047,7048,
806057049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,
806067064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,7075,7076,7077,7078,
806077079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090,7091,7092,7093,
806087094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105,7106,7107,7108,
806097109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,
806107124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,
806117139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,
806127154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167,7168,
806137169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,
806147184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,
806157199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,
806167214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,
806177229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,
806187244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,
806197259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,
806207274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,
806217289,7290,7291,7292,7293,7294,7295,7296,7297,7298,7299,7300,7301,7302,7303,
806227304,7305,7306,7307,7308,7309,7310,7311,7312,7313,7314,7315,7316,7317,7318,
806237319,7320,7321,7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,
806247334,7335,7336,7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,
806257349,7350,7351,7352,7353,7354,7355,7356,7357,7358,7359,7360,7361,7362,7363,
806267364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375,7376,7377,7378,
806277379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,
806287394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407,7408,
806297409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423,
806307424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,
806317439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,
806327454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,
806337469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,
806347484,7485,7486,7487,7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,
806357499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,
806367514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,
806377529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,
806387544,42877L,7546,7547,7548,11363,7550,7551,7552,7553,7554,7555,7556,7557,
806397558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,
806407573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,
806417588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,
806427603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7616,7617,
806437618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,
806447633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,
806457648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,
806467663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7677,
806477678,7679,7680,7680,7682,7682,7684,7684,7686,7686,7688,7688,7690,7690,7692,
806487692,7694,7694,7696,7696,7698,7698,7700,7700,7702,7702,7704,7704,7706,7706,
806497708,7708,7710,7710,7712,7712,7714,7714,7716,7716,7718,7718,7720,7720,7722,
806507722,7724,7724,7726,7726,7728,7728,7730,7730,7732,7732,7734,7734,7736,7736,
806517738,7738,7740,7740,7742,7742,7744,7744,7746,7746,7748,7748,7750,7750,7752,
806527752,7754,7754,7756,7756,7758,7758,7760,7760,7762,7762,7764,7764,7766,7766,
806537768,7768,7770,7770,7772,7772,7774,7774,7776,7776,7778,7778,7780,7780,7782,
806547782,7784,7784,7786,7786,7788,7788,7790,7790,7792,7792,7794,7794,7796,7796,
806557798,7798,7800,7800,7802,7802,7804,7804,7806,7806,7808,7808,7810,7810,7812,
806567812,7814,7814,7816,7816,7818,7818,7820,7820,7822,7822,7824,7824,7826,7826,
806577828,7828,7830,7831,7832,7833,7834,7776,7836,7837,7838,7839,7840,7840,7842,
806587842,7844,7844,7846,7846,7848,7848,7850,7850,7852,7852,7854,7854,7856,7856,
806597858,7858,7860,7860,7862,7862,7864,7864,7866,7866,7868,7868,7870,7870,7872,
806607872,7874,7874,7876,7876,7878,7878,7880,7880,7882,7882,7884,7884,7886,7886,
806617888,7888,7890,7890,7892,7892,7894,7894,7896,7896,7898,7898,7900,7900,7902,
806627902,7904,7904,7906,7906,7908,7908,7910,7910,7912,7912,7914,7914,7916,7916,
806637918,7918,7920,7920,7922,7922,7924,7924,7926,7926,7928,7928,7930,7930,7932,
806647932,7934,7934,7944,7945,7946,7947,7948,7949,7950,7951,7944,7945,7946,7947,
806657948,7949,7950,7951,7960,7961,7962,7963,7964,7965,7958,7959,7960,7961,7962,
806667963,7964,7965,7966,7967,7976,7977,7978,7979,7980,7981,7982,7983,7976,7977,
806677978,7979,7980,7981,7982,7983,7992,7993,7994,7995,7996,7997,7998,7999,7992,
806687993,7994,7995,7996,7997,7998,7999,8008,8009,8010,8011,8012,8013,8006,8007,
806698008,8009,8010,8011,8012,8013,8014,8015,8016,8025,8018,8027,8020,8029,8022,
806708031,8024,8025,8026,8027,8028,8029,8030,8031,8040,8041,8042,8043,8044,8045,
806718046,8047,8040,8041,8042,8043,8044,8045,8046,8047,8122,8123,8136,8137,8138,
806728139,8154,8155,8184,8185,8170,8171,8186,8187,8062,8063,8064,8065,8066,8067,
806738068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080,8081,8082,
806748083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,
806758098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,8120,
806768121,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,921,8127,
806778128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,
806788143,8152,8153,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,
806798158,8159,8168,8169,8162,8163,8164,8172,8166,8167,8168,8169,8170,8171,8172,
806808173,8174,8175,8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,
806818188,8189,8190,8191,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,
806828203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,
806838218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229,8230,8231,8232,
806848233,8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245,8246,8247,
806858248,8249,8250,8251,8252,8253,8254,8255,8256,8257,8258,8259,8260,8261,8262,
806868263,8264,8265,8266,8267,8268,8269,8270,8271,8272,8273,8274,8275,8276,8277,
806878278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,8290,8291,8292,
806888293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,
806898308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322,
806908323,8324,8325,8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337,
806918338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,
806928353,8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,
806938368,8369,8370,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382,
806948383,8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,
806958398,8399,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,
806968413,8414,8415,8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,
806978428,8429,8430,8431,8432,8433,8434,8435,8436,8437,8438,8439,8440,8441,8442,
806988443,8444,8445,8446,8447,8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,
806998458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8468,8469,8470,8471,8472,
807008473,8474,8475,8476,8477,8478,8479,8480,8481,8482,8483,8484,8485,8486,8487,
807018488,8489,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,
807028503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517,
807038518,8519,8520,8521,8522,8523,8524,8525,8498,8527,8528,8529,8530,8531,8532,
807048533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,
807058548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8544,8545,8546,
807068547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8576,8577,
807078578,8579,8579,8581,8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,8592,
807088593,8594,8595,8596,8597,8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,
807098608,8609,8610,8611,8612,8613,8614,8615,8616,8617,8618,8619,8620,8621,8622,
807108623,8624,8625,8626,8627,8628,8629,8630,8631,8632,8633,8634,8635,8636,8637,
807118638,8639,8640,8641,8642,8643,8644,8645,8646,8647,8648,8649,8650,8651,8652,
807128653,8654,8655,8656,8657,8658,8659,8660,8661,8662,8663,8664,8665,8666,8667,
807138668,8669,8670,8671,8672,8673,8674,8675,8676,8677,8678,8679,8680,8681,8682,
807148683,8684,8685,8686,8687,8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,
807158698,8699,8700,8701,8702,8703,8704,8705,8706,8707,8708,8709,8710,8711,8712,
807168713,8714,8715,8716,8717,8718,8719,8720,8721,8722,8723,8724,8725,8726,8727,
807178728,8729,8730,8731,8732,8733,8734,8735,8736,8737,8738,8739,8740,8741,8742,
807188743,8744,8745,8746,8747,8748,8749,8750,8751,8752,8753,8754,8755,8756,8757,
807198758,8759,8760,8761,8762,8763,8764,8765,8766,8767,8768,8769,8770,8771,8772,
807208773,8774,8775,8776,8777,8778,8779,8780,8781,8782,8783,8784,8785,8786,8787,
807218788,8789,8790,8791,8792,8793,8794,8795,8796,8797,8798,8799,8800,8801,8802,
807228803,8804,8805,8806,8807,8808,8809,8810,8811,8812,8813,8814,8815,8816,8817,
807238818,8819,8820,8821,8822,8823,8824,8825,8826,8827,8828,8829,8830,8831,8832,
807248833,8834,8835,8836,8837,8838,8839,8840,8841,8842,8843,8844,8845,8846,8847,
807258848,8849,8850,8851,8852,8853,8854,8855,8856,8857,8858,8859,8860,8861,8862,
807268863,8864,8865,8866,8867,8868,8869,8870,8871,8872,8873,8874,8875,8876,8877,
807278878,8879,8880,8881,8882,8883,8884,8885,8886,8887,8888,8889,8890,8891,8892,
807288893,8894,8895,8896,8897,8898,8899,8900,8901,8902,8903,8904,8905,8906,8907,
807298908,8909,8910,8911,8912,8913,8914,8915,8916,8917,8918,8919,8920,8921,8922,
807308923,8924,8925,8926,8927,8928,8929,8930,8931,8932,8933,8934,8935,8936,8937,
807318938,8939,8940,8941,8942,8943,8944,8945,8946,8947,8948,8949,8950,8951,8952,
807328953,8954,8955,8956,8957,8958,8959,8960,8961,8962,8963,8964,8965,8966,8967,
807338968,8969,8970,8971,8972,8973,8974,8975,8976,8977,8978,8979,8980,8981,8982,
807348983,8984,8985,8986,8987,8988,8989,8990,8991,8992,8993,8994,8995,8996,8997,
807358998,8999,9000,9001,9002,9003,9004,9005,9006,9007,9008,9009,9010,9011,9012,
807369013,9014,9015,9016,9017,9018,9019,9020,9021,9022,9023,9024,9025,9026,9027,
807379028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039,9040,9041,9042,
807389043,9044,9045,9046,9047,9048,9049,9050,9051,9052,9053,9054,9055,9056,9057,
807399058,9059,9060,9061,9062,9063,9064,9065,9066,9067,9068,9069,9070,9071,9072,
807409073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085,9086,9087,
807419088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9101,9102,
807429103,9104,9105,9106,9107,9108,9109,9110,9111,9112,9113,9114,9115,9116,9117,
807439118,9119,9120,9121,9122,9123,9124,9125,9126,9127,9128,9129,9130,9131,9132,
807449133,9134,9135,9136,9137,9138,9139,9140,9141,9142,9143,9144,9145,9146,9147,
807459148,9149,9150,9151,9152,9153,9154,9155,9156,9157,9158,9159,9160,9161,9162,
807469163,9164,9165,9166,9167,9168,9169,9170,9171,9172,9173,9174,9175,9176,9177,
807479178,9179,9180,9181,9182,9183,9184,9185,9186,9187,9188,9189,9190,9191,9192,
807489193,9194,9195,9196,9197,9198,9199,9200,9201,9202,9203,9204,9205,9206,9207,
807499208,9209,9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,9221,9222,
807509223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,
807519238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9248,9249,9250,9251,9252,
807529253,9254,9255,9256,9257,9258,9259,9260,9261,9262,9263,9264,9265,9266,9267,
807539268,9269,9270,9271,9272,9273,9274,9275,9276,9277,9278,9279,9280,9281,9282,
807549283,9284,9285,9286,9287,9288,9289,9290,9291,9292,9293,9294,9295,9296,9297,
807559298,9299,9300,9301,9302,9303,9304,9305,9306,9307,9308,9309,9310,9311,9312,
807569313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,
807579328,9329,9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,
807589343,9344,9345,9346,9347,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,
807599358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9372,
807609373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,
807619388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,
807629403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,
807639418,9419,9420,9421,9422,9423,9398,9399,9400,9401,9402,9403,9404,9405,9406,
807649407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,
807659422,9423,9450,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461,9462,
807669463,9464,9465,9466,9467,9468,9469,9470,9471,9472,9473,9474,9475,9476,9477,
807679478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,
807689493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,
807699508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,
807709523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,
807719538,9539,9540,9541,9542,9543,9544,9545,9546,9547,9548,9549,9550,9551,9552,
807729553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,
807739568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,
807749583,9584,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,
807759598,9599,9600,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,
807769613,9614,9615,9616,9617,9618,9619,9620,9621,9622,9623,9624,9625,9626,9627,
807779628,9629,9630,9631,9632,9633,9634,9635,9636,9637,9638,9639,9640,9641,9642,
807789643,9644,9645,9646,9647,9648,9649,9650,9651,9652,9653,9654,9655,9656,9657,
807799658,9659,9660,9661,9662,9663,9664,9665,9666,9667,9668,9669,9670,9671,9672,
807809673,9674,9675,9676,9677,9678,9679,9680,9681,9682,9683,9684,9685,9686,9687,
807819688,9689,9690,9691,9692,9693,9694,9695,9696,9697,9698,9699,9700,9701,9702,
807829703,9704,9705,9706,9707,9708,9709,9710,9711,9712,9713,9714,9715,9716,9717,
807839718,9719,9720,9721,9722,9723,9724,9725,9726,9727,9728,9729,9730,9731,9732,
807849733,9734,9735,9736,9737,9738,9739,9740,9741,9742,9743,9744,9745,9746,9747,
807859748,9749,9750,9751,9752,9753,9754,9755,9756,9757,9758,9759,9760,9761,9762,
807869763,9764,9765,9766,9767,9768,9769,9770,9771,9772,9773,9774,9775,9776,9777,
807879778,9779,9780,9781,9782,9783,9784,9785,9786,9787,9788,9789,9790,9791,9792,
807889793,9794,9795,9796,9797,9798,9799,9800,9801,9802,9803,9804,9805,9806,9807,
807899808,9809,9810,9811,9812,9813,9814,9815,9816,9817,9818,9819,9820,9821,9822,
807909823,9824,9825,9826,9827,9828,9829,9830,9831,9832,9833,9834,9835,9836,9837,
807919838,9839,9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,
807929853,9854,9855,9856,9857,9858,9859,9860,9861,9862,9863,9864,9865,9866,9867,
807939868,9869,9870,9871,9872,9873,9874,9875,9876,9877,9878,9879,9880,9881,9882,
807949883,9884,9885,9886,9887,9888,9889,9890,9891,9892,9893,9894,9895,9896,9897,
807959898,9899,9900,9901,9902,9903,9904,9905,9906,9907,9908,9909,9910,9911,9912,
807969913,9914,9915,9916,9917,9918,9919,9920,9921,9922,9923,9924,9925,9926,9927,
807979928,9929,9930,9931,9932,9933,9934,9935,9936,9937,9938,9939,9940,9941,9942,
807989943,9944,9945,9946,9947,9948,9949,9950,9951,9952,9953,9954,9955,9956,9957,
807999958,9959,9960,9961,9962,9963,9964,9965,9966,9967,9968,9969,9970,9971,9972,
808009973,9974,9975,9976,9977,9978,9979,9980,9981,9982,9983,9984,9985,9986,9987,
808019988,9989,9990,9991,9992,9993,9994,9995,9996,9997,9998,9999,10000,10001,
8080210002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,
8080310014,10015,10016,10017,10018,10019,10020,10021,10022,10023,10024,10025,
8080410026,10027,10028,10029,10030,10031,10032,10033,10034,10035,10036,10037,
8080510038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,10049,
8080610050,10051,10052,10053,10054,10055,10056,10057,10058,10059,10060,10061,
8080710062,10063,10064,10065,10066,10067,10068,10069,10070,10071,10072,10073,
8080810074,10075,10076,10077,10078,10079,10080,10081,10082,10083,10084,10085,
8080910086,10087,10088,10089,10090,10091,10092,10093,10094,10095,10096,10097,
8081010098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,
8081110110,10111,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,
8081210122,10123,10124,10125,10126,10127,10128,10129,10130,10131,10132,10133,
8081310134,10135,10136,10137,10138,10139,10140,10141,10142,10143,10144,10145,
8081410146,10147,10148,10149,10150,10151,10152,10153,10154,10155,10156,10157,
8081510158,10159,10160,10161,10162,10163,10164,10165,10166,10167,10168,10169,
8081610170,10171,10172,10173,10174,10175,10176,10177,10178,10179,10180,10181,
8081710182,10183,10184,10185,10186,10187,10188,10189,10190,10191,10192,10193,
8081810194,10195,10196,10197,10198,10199,10200,10201,10202,10203,10204,10205,
8081910206,10207,10208,10209,10210,10211,10212,10213,10214,10215,10216,10217,
8082010218,10219,10220,10221,10222,10223,10224,10225,10226,10227,10228,10229,
8082110230,10231,10232,10233,10234,10235,10236,10237,10238,10239,10240,10241,
8082210242,10243,10244,10245,10246,10247,10248,10249,10250,10251,10252,10253,
8082310254,10255,10256,10257,10258,10259,10260,10261,10262,10263,10264,10265,
8082410266,10267,10268,10269,10270,10271,10272,10273,10274,10275,10276,10277,
8082510278,10279,10280,10281,10282,10283,10284,10285,10286,10287,10288,10289,
8082610290,10291,10292,10293,10294,10295,10296,10297,10298,10299,10300,10301,
8082710302,10303,10304,10305,10306,10307,10308,10309,10310,10311,10312,10313,
8082810314,10315,10316,10317,10318,10319,10320,10321,10322,10323,10324,10325,
8082910326,10327,10328,10329,10330,10331,10332,10333,10334,10335,10336,10337,
8083010338,10339,10340,10341,10342,10343,10344,10345,10346,10347,10348,10349,
8083110350,10351,10352,10353,10354,10355,10356,10357,10358,10359,10360,10361,
8083210362,10363,10364,10365,10366,10367,10368,10369,10370,10371,10372,10373,
8083310374,10375,10376,10377,10378,10379,10380,10381,10382,10383,10384,10385,
8083410386,10387,10388,10389,10390,10391,10392,10393,10394,10395,10396,10397,
8083510398,10399,10400,10401,10402,10403,10404,10405,10406,10407,10408,10409,
8083610410,10411,10412,10413,10414,10415,10416,10417,10418,10419,10420,10421,
8083710422,10423,10424,10425,10426,10427,10428,10429,10430,10431,10432,10433,
8083810434,10435,10436,10437,10438,10439,10440,10441,10442,10443,10444,10445,
8083910446,10447,10448,10449,10450,10451,10452,10453,10454,10455,10456,10457,
8084010458,10459,10460,10461,10462,10463,10464,10465,10466,10467,10468,10469,
8084110470,10471,10472,10473,10474,10475,10476,10477,10478,10479,10480,10481,
8084210482,10483,10484,10485,10486,10487,10488,10489,10490,10491,10492,10493,
8084310494,10495,10496,10497,10498,10499,10500,10501,10502,10503,10504,10505,
8084410506,10507,10508,10509,10510,10511,10512,10513,10514,10515,10516,10517,
8084510518,10519,10520,10521,10522,10523,10524,10525,10526,10527,10528,10529,
8084610530,10531,10532,10533,10534,10535,10536,10537,10538,10539,10540,10541,
8084710542,10543,10544,10545,10546,10547,10548,10549,10550,10551,10552,10553,
8084810554,10555,10556,10557,10558,10559,10560,10561,10562,10563,10564,10565,
8084910566,10567,10568,10569,10570,10571,10572,10573,10574,10575,10576,10577,
8085010578,10579,10580,10581,10582,10583,10584,10585,10586,10587,10588,10589,
8085110590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,
8085210602,10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,
8085310614,10615,10616,10617,10618,10619,10620,10621,10622,10623,10624,10625,
8085410626,10627,10628,10629,10630,10631,10632,10633,10634,10635,10636,10637,
8085510638,10639,10640,10641,10642,10643,10644,10645,10646,10647,10648,10649,
8085610650,10651,10652,10653,10654,10655,10656,10657,10658,10659,10660,10661,
8085710662,10663,10664,10665,10666,10667,10668,10669,10670,10671,10672,10673,
8085810674,10675,10676,10677,10678,10679,10680,10681,10682,10683,10684,10685,
8085910686,10687,10688,10689,10690,10691,10692,10693,10694,10695,10696,10697,
8086010698,10699,10700,10701,10702,10703,10704,10705,10706,10707,10708,10709,
8086110710,10711,10712,10713,10714,10715,10716,10717,10718,10719,10720,10721,
8086210722,10723,10724,10725,10726,10727,10728,10729,10730,10731,10732,10733,
8086310734,10735,10736,10737,10738,10739,10740,10741,10742,10743,10744,10745,
8086410746,10747,10748,10749,10750,10751,10752,10753,10754,10755,10756,10757,
8086510758,10759,10760,10761,10762,10763,10764,10765,10766,10767,10768,10769,
8086610770,10771,10772,10773,10774,10775,10776,10777,10778,10779,10780,10781,
8086710782,10783,10784,10785,10786,10787,10788,10789,10790,10791,10792,10793,
8086810794,10795,10796,10797,10798,10799,10800,10801,10802,10803,10804,10805,
8086910806,10807,10808,10809,10810,10811,10812,10813,10814,10815,10816,10817,
8087010818,10819,10820,10821,10822,10823,10824,10825,10826,10827,10828,10829,
8087110830,10831,10832,10833,10834,10835,10836,10837,10838,10839,10840,10841,
8087210842,10843,10844,10845,10846,10847,10848,10849,10850,10851,10852,10853,
8087310854,10855,10856,10857,10858,10859,10860,10861,10862,10863,10864,10865,
8087410866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876,10877,
8087510878,10879,10880,10881,10882,10883,10884,10885,10886,10887,10888,10889,
8087610890,10891,10892,10893,10894,10895,10896,10897,10898,10899,10900,10901,
8087710902,10903,10904,10905,10906,10907,10908,10909,10910,10911,10912,10913,
8087810914,10915,10916,10917,10918,10919,10920,10921,10922,10923,10924,10925,
8087910926,10927,10928,10929,10930,10931,10932,10933,10934,10935,10936,10937,
8088010938,10939,10940,10941,10942,10943,10944,10945,10946,10947,10948,10949,
8088110950,10951,10952,10953,10954,10955,10956,10957,10958,10959,10960,10961,
8088210962,10963,10964,10965,10966,10967,10968,10969,10970,10971,10972,10973,
8088310974,10975,10976,10977,10978,10979,10980,10981,10982,10983,10984,10985,
8088410986,10987,10988,10989,10990,10991,10992,10993,10994,10995,10996,10997,
8088510998,10999,11000,11001,11002,11003,11004,11005,11006,11007,11008,11009,
8088611010,11011,11012,11013,11014,11015,11016,11017,11018,11019,11020,11021,
8088711022,11023,11024,11025,11026,11027,11028,11029,11030,11031,11032,11033,
8088811034,11035,11036,11037,11038,11039,11040,11041,11042,11043,11044,11045,
8088911046,11047,11048,11049,11050,11051,11052,11053,11054,11055,11056,11057,
8089011058,11059,11060,11061,11062,11063,11064,11065,11066,11067,11068,11069,
8089111070,11071,11072,11073,11074,11075,11076,11077,11078,11079,11080,11081,
8089211082,11083,11084,11085,11086,11087,11088,11089,11090,11091,11092,11093,
8089311094,11095,11096,11097,11098,11099,11100,11101,11102,11103,11104,11105,
8089411106,11107,11108,11109,11110,11111,11112,11113,11114,11115,11116,11117,
8089511118,11119,11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,
8089611130,11131,11132,11133,11134,11135,11136,11137,11138,11139,11140,11141,
8089711142,11143,11144,11145,11146,11147,11148,11149,11150,11151,11152,11153,
8089811154,11155,11156,11157,11158,11159,11160,11161,11162,11163,11164,11165,
8089911166,11167,11168,11169,11170,11171,11172,11173,11174,11175,11176,11177,
8090011178,11179,11180,11181,11182,11183,11184,11185,11186,11187,11188,11189,
8090111190,11191,11192,11193,11194,11195,11196,11197,11198,11199,11200,11201,
8090211202,11203,11204,11205,11206,11207,11208,11209,11210,11211,11212,11213,
8090311214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225,
8090411226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,
8090511238,11239,11240,11241,11242,11243,11244,11245,11246,11247,11248,11249,
8090611250,11251,11252,11253,11254,11255,11256,11257,11258,11259,11260,11261,
8090711262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
8090811274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
8090911286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
8091011298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
8091111310,11311,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
8091211274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
8091311286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
8091411298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
8091511310,11359,11360,11360,11362,11363,11364,570,574,11367,11367,11369,11369,
8091611371,11371,11373,11374,11375,11376,11377,11378,11378,11380,11381,11381,
8091711383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11392,11394,
8091811394,11396,11396,11398,11398,11400,11400,11402,11402,11404,11404,11406,
8091911406,11408,11408,11410,11410,11412,11412,11414,11414,11416,11416,11418,
8092011418,11420,11420,11422,11422,11424,11424,11426,11426,11428,11428,11430,
8092111430,11432,11432,11434,11434,11436,11436,11438,11438,11440,11440,11442,
8092211442,11444,11444,11446,11446,11448,11448,11450,11450,11452,11452,11454,
8092311454,11456,11456,11458,11458,11460,11460,11462,11462,11464,11464,11466,
8092411466,11468,11468,11470,11470,11472,11472,11474,11474,11476,11476,11478,
8092511478,11480,11480,11482,11482,11484,11484,11486,11486,11488,11488,11490,
8092611490,11492,11493,11494,11495,11496,11497,11498,11499,11499,11501,11501,
8092711503,11504,11505,11506,11507,11508,11509,11510,11511,11512,11513,11514,
8092811515,11516,11517,11518,11519,4256,4257,4258,4259,4260,4261,4262,4263,4264,
809294265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,
809304280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,
8093111558,11559,11560,11561,11562,11563,11564,11565,11566,11567,11568,11569,
8093211570,11571,11572,11573,11574,11575,11576,11577,11578,11579,11580,11581,
8093311582,11583,11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,
8093411594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,11605,
8093511606,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,
8093611618,11619,11620,11621,11622,11623,11624,11625,11626,11627,11628,11629,
8093711630,11631,11632,11633,11634,11635,11636,11637,11638,11639,11640,11641,
8093811642,11643,11644,11645,11646,11647,11648,11649,11650,11651,11652,11653,
8093911654,11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,
8094011666,11667,11668,11669,11670,11671,11672,11673,11674,11675,11676,11677,
8094111678,11679,11680,11681,11682,11683,11684,11685,11686,11687,11688,11689,
8094211690,11691,11692,11693,11694,11695,11696,11697,11698,11699,11700,11701,
8094311702,11703,11704,11705,11706,11707,11708,11709,11710,11711,11712,11713,
8094411714,11715,11716,11717,11718,11719,11720,11721,11722,11723,11724,11725,
8094511726,11727,11728,11729,11730,11731,11732,11733,11734,11735,11736,11737,
8094611738,11739,11740,11741,11742,11743,11744,11745,11746,11747,11748,11749,
8094711750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,
8094811762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,
8094911774,11775,11776,11777,11778,11779,11780,11781,11782,11783,11784,11785,
8095011786,11787,11788,11789,11790,11791,11792,11793,11794,11795,11796,11797,
8095111798,11799,11800,11801,11802,11803,11804,11805,11806,11807,11808,11809,
8095211810,11811,11812,11813,11814,11815,11816,11817,11818,11819,11820,11821,
8095311822,11823,11824,11825,11826,11827,11828,11829,11830,11831,11832,11833,
8095411834,11835,11836,11837,11838,11839,11840,11841,11842,11843,11844,11845,
8095511846,11847,11848,11849,11850,11851,11852,11853,11854,11855,11856,11857,
8095611858,11859,11860,11861,11862,11863,11864,11865,11866,11867,11868,11869,
8095711870,11871,11872,11873,11874,11875,11876,11877,11878,11879,11880,11881,
8095811882,11883,11884,11885,11886,11887,11888,11889,11890,11891,11892,11893,
8095911894,11895,11896,11897,11898,11899,11900,11901,11902,11903,11904,11905,
8096011906,11907,11908,11909,11910,11911,11912,11913,11914,11915,11916,11917,
8096111918,11919,11920,11921,11922,11923,11924,11925,11926,11927,11928,11929,
8096211930,11931,11932,11933,11934,11935,11936,11937,11938,11939,11940,11941,
8096311942,11943,11944,11945,11946,11947,11948,11949,11950,11951,11952,11953,
8096411954,11955,11956,11957,11958,11959,11960,11961,11962,11963,11964,11965,
8096511966,11967,11968,11969,11970,11971,11972,11973,11974,11975,11976,11977,
8096611978,11979,11980,11981,11982,11983,11984,11985,11986,11987,11988,11989,
8096711990,11991,11992,11993,11994,11995,11996,11997,11998,11999,12000,12001,
8096812002,12003,12004,12005,12006,12007,12008,12009,12010,12011,12012,12013,
8096912014,12015,12016,12017,12018,12019,12020,12021,12022,12023,12024,12025,
8097012026,12027,12028,12029,12030,12031,12032,12033,12034,12035,12036,12037,
8097112038,12039,12040,12041,12042,12043,12044,12045,12046,12047,12048,12049,
8097212050,12051,12052,12053,12054,12055,12056,12057,12058,12059,12060,12061,
8097312062,12063,12064,12065,12066,12067,12068,12069,12070,12071,12072,12073,
8097412074,12075,12076,12077,12078,12079,12080,12081,12082,12083,12084,12085,
8097512086,12087,12088,12089,12090,12091,12092,12093,12094,12095,12096,12097,
8097612098,12099,12100,12101,12102,12103,12104,12105,12106,12107,12108,12109,
8097712110,12111,12112,12113,12114,12115,12116,12117,12118,12119,12120,12121,
8097812122,12123,12124,12125,12126,12127,12128,12129,12130,12131,12132,12133,
8097912134,12135,12136,12137,12138,12139,12140,12141,12142,12143,12144,12145,
8098012146,12147,12148,12149,12150,12151,12152,12153,12154,12155,12156,12157,
8098112158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168,12169,
8098212170,12171,12172,12173,12174,12175,12176,12177,12178,12179,12180,12181,
8098312182,12183,12184,12185,12186,12187,12188,12189,12190,12191,12192,12193,
8098412194,12195,12196,12197,12198,12199,12200,12201,12202,12203,12204,12205,
8098512206,12207,12208,12209,12210,12211,12212,12213,12214,12215,12216,12217,
8098612218,12219,12220,12221,12222,12223,12224,12225,12226,12227,12228,12229,
8098712230,12231,12232,12233,12234,12235,12236,12237,12238,12239,12240,12241,
8098812242,12243,12244,12245,12246,12247,12248,12249,12250,12251,12252,12253,
8098912254,12255,12256,12257,12258,12259,12260,12261,12262,12263,12264,12265,
8099012266,12267,12268,12269,12270,12271,12272,12273,12274,12275,12276,12277,
8099112278,12279,12280,12281,12282,12283,12284,12285,12286,12287,12288,12289,
8099212290,12291,12292,12293,12294,12295,12296,12297,12298,12299,12300,12301,
8099312302,12303,12304,12305,12306,12307,12308,12309,12310,12311,12312,12313,
8099412314,12315,12316,12317,12318,12319,12320,12321,12322,12323,12324,12325,
8099512326,12327,12328,12329,12330,12331,12332,12333,12334,12335,12336,12337,
8099612338,12339,12340,12341,12342,12343,12344,12345,12346,12347,12348,12349,
8099712350,12351,12352,12353,12354,12355,12356,12357,12358,12359,12360,12361,
8099812362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,
8099912374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,
8100012386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,
8100112398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,
8100212410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,
8100312422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,
8100412434,12435,12436,12437,12438,12439,12440,12441,12442,12443,12444,12445,
8100512446,12447,12448,12449,12450,12451,12452,12453,12454,12455,12456,12457,
8100612458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,
8100712470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,
8100812482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,
8100912494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,
8101012506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,
8101112518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,
8101212530,12531,12532,12533,12534,12535,12536,12537,12538,12539,12540,12541,
8101312542,12543,12544,12545,12546,12547,12548,12549,12550,12551,12552,12553,
8101412554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,
8101512566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,
8101612578,12579,12580,12581,12582,12583,12584,12585,12586,12587,12588,12589,
8101712590,12591,12592,12593,12594,12595,12596,12597,12598,12599,12600,12601,
8101812602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,
8101912614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,
8102012626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,
8102112638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,
8102212650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,
8102312662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,
8102412674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,
8102512686,12687,12688,12689,12690,12691,12692,12693,12694,12695,12696,12697,
8102612698,12699,12700,12701,12702,12703,12704,12705,12706,12707,12708,12709,
8102712710,12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,
8102812722,12723,12724,12725,12726,12727,12728,12729,12730,12731,12732,12733,
8102912734,12735,12736,12737,12738,12739,12740,12741,12742,12743,12744,12745,
8103012746,12747,12748,12749,12750,12751,12752,12753,12754,12755,12756,12757,
8103112758,12759,12760,12761,12762,12763,12764,12765,12766,12767,12768,12769,
8103212770,12771,12772,12773,12774,12775,12776,12777,12778,12779,12780,12781,
8103312782,12783,12784,12785,12786,12787,12788,12789,12790,12791,12792,12793,
8103412794,12795,12796,12797,12798,12799,12800,12801,12802,12803,12804,12805,
8103512806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,
8103612818,12819,12820,12821,12822,12823,12824,12825,12826,12827,12828,12829,
8103712830,12831,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,
8103812842,12843,12844,12845,12846,12847,12848,12849,12850,12851,12852,12853,
8103912854,12855,12856,12857,12858,12859,12860,12861,12862,12863,12864,12865,
8104012866,12867,12868,12869,12870,12871,12872,12873,12874,12875,12876,12877,
8104112878,12879,12880,12881,12882,12883,12884,12885,12886,12887,12888,12889,
8104212890,12891,12892,12893,12894,12895,12896,12897,12898,12899,12900,12901,
8104312902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,
8104412914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,
8104512926,12927,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,
8104612938,12939,12940,12941,12942,12943,12944,12945,12946,12947,12948,12949,
8104712950,12951,12952,12953,12954,12955,12956,12957,12958,12959,12960,12961,
8104812962,12963,12964,12965,12966,12967,12968,12969,12970,12971,12972,12973,
8104912974,12975,12976,12977,12978,12979,12980,12981,12982,12983,12984,12985,
8105012986,12987,12988,12989,12990,12991,12992,12993,12994,12995,12996,12997,
8105112998,12999,13000,13001,13002,13003,13004,13005,13006,13007,13008,13009,
8105213010,13011,13012,13013,13014,13015,13016,13017,13018,13019,13020,13021,
8105313022,13023,13024,13025,13026,13027,13028,13029,13030,13031,13032,13033,
8105413034,13035,13036,13037,13038,13039,13040,13041,13042,13043,13044,13045,
8105513046,13047,13048,13049,13050,13051,13052,13053,13054,13055,13056,13057,
8105613058,13059,13060,13061,13062,13063,13064,13065,13066,13067,13068,13069,
8105713070,13071,13072,13073,13074,13075,13076,13077,13078,13079,13080,13081,
8105813082,13083,13084,13085,13086,13087,13088,13089,13090,13091,13092,13093,
8105913094,13095,13096,13097,13098,13099,13100,13101,13102,13103,13104,13105,
8106013106,13107,13108,13109,13110,13111,13112,13113,13114,13115,13116,13117,
8106113118,13119,13120,13121,13122,13123,13124,13125,13126,13127,13128,13129,
8106213130,13131,13132,13133,13134,13135,13136,13137,13138,13139,13140,13141,
8106313142,13143,13144,13145,13146,13147,13148,13149,13150,13151,13152,13153,
8106413154,13155,13156,13157,13158,13159,13160,13161,13162,13163,13164,13165,
8106513166,13167,13168,13169,13170,13171,13172,13173,13174,13175,13176,13177,
8106613178,13179,13180,13181,13182,13183,13184,13185,13186,13187,13188,13189,
8106713190,13191,13192,13193,13194,13195,13196,13197,13198,13199,13200,13201,
8106813202,13203,13204,13205,13206,13207,13208,13209,13210,13211,13212,13213,
8106913214,13215,13216,13217,13218,13219,13220,13221,13222,13223,13224,13225,
8107013226,13227,13228,13229,13230,13231,13232,13233,13234,13235,13236,13237,
8107113238,13239,13240,13241,13242,13243,13244,13245,13246,13247,13248,13249,
8107213250,13251,13252,13253,13254,13255,13256,13257,13258,13259,13260,13261,
8107313262,13263,13264,13265,13266,13267,13268,13269,13270,13271,13272,13273,
8107413274,13275,13276,13277,13278,13279,13280,13281,13282,13283,13284,13285,
8107513286,13287,13288,13289,13290,13291,13292,13293,13294,13295,13296,13297,
8107613298,13299,13300,13301,13302,13303,13304,13305,13306,13307,13308,13309,
8107713310,13311,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321,
8107813322,13323,13324,13325,13326,13327,13328,13329,13330,13331,13332,13333,
8107913334,13335,13336,13337,13338,13339,13340,13341,13342,13343,13344,13345,
8108013346,13347,13348,13349,13350,13351,13352,13353,13354,13355,13356,13357,
8108113358,13359,13360,13361,13362,13363,13364,13365,13366,13367,13368,13369,
8108213370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,
8108313382,13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,
8108413394,13395,13396,13397,13398,13399,13400,13401,13402,13403,13404,13405,
8108513406,13407,13408,13409,13410,13411,13412,13413,13414,13415,13416,13417,
8108613418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,
8108713430,13431,13432,13433,13434,13435,13436,13437,13438,13439,13440,13441,
8108813442,13443,13444,13445,13446,13447,13448,13449,13450,13451,13452,13453,
8108913454,13455,13456,13457,13458,13459,13460,13461,13462,13463,13464,13465,
8109013466,13467,13468,13469,13470,13471,13472,13473,13474,13475,13476,13477,
8109113478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,
8109213490,13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,
8109313502,13503,13504,13505,13506,13507,13508,13509,13510,13511,13512,13513,
8109413514,13515,13516,13517,13518,13519,13520,13521,13522,13523,13524,13525,
8109513526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,
8109613538,13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,
8109713550,13551,13552,13553,13554,13555,13556,13557,13558,13559,13560,13561,
8109813562,13563,13564,13565,13566,13567,13568,13569,13570,13571,13572,13573,
8109913574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,
8110013586,13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,
8110113598,13599,13600,13601,13602,13603,13604,13605,13606,13607,13608,13609,
8110213610,13611,13612,13613,13614,13615,13616,13617,13618,13619,13620,13621,
8110313622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,
8110413634,13635,13636,13637,13638,13639,13640,13641,13642,13643,13644,13645,
8110513646,13647,13648,13649,13650,13651,13652,13653,13654,13655,13656,13657,
8110613658,13659,13660,13661,13662,13663,13664,13665,13666,13667,13668,13669,
8110713670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680,13681,
8110813682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,
8110913694,13695,13696,13697,13698,13699,13700,13701,13702,13703,13704,13705,
8111013706,13707,13708,13709,13710,13711,13712,13713,13714,13715,13716,13717,
8111113718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728,13729,
8111213730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,
8111313742,13743,13744,13745,13746,13747,13748,13749,13750,13751,13752,13753,
8111413754,13755,13756,13757,13758,13759,13760,13761,13762,13763,13764,13765,
8111513766,13767,13768,13769,13770,13771,13772,13773,13774,13775,13776,13777,
8111613778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,
8111713790,13791,13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,
8111813802,13803,13804,13805,13806,13807,13808,13809,13810,13811,13812,13813,
8111913814,13815,13816,13817,13818,13819,13820,13821,13822,13823,13824,13825,
8112013826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,
8112113838,13839,13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,
8112213850,13851,13852,13853,13854,13855,13856,13857,13858,13859,13860,13861,
8112313862,13863,13864,13865,13866,13867,13868,13869,13870,13871,13872,13873,
8112413874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,
8112513886,13887,13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,
8112613898,13899,13900,13901,13902,13903,13904,13905,13906,13907,13908,13909,
8112713910,13911,13912,13913,13914,13915,13916,13917,13918,13919,13920,13921,
8112813922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,
8112913934,13935,13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,
8113013946,13947,13948,13949,13950,13951,13952,13953,13954,13955,13956,13957,
8113113958,13959,13960,13961,13962,13963,13964,13965,13966,13967,13968,13969,
8113213970,13971,13972,13973,13974,13975,13976,13977,13978,13979,13980,13981,
8113313982,13983,13984,13985,13986,13987,13988,13989,13990,13991,13992,13993,
8113413994,13995,13996,13997,13998,13999,14000,14001,14002,14003,14004,14005,
8113514006,14007,14008,14009,14010,14011,14012,14013,14014,14015,14016,14017,
8113614018,14019,14020,14021,14022,14023,14024,14025,14026,14027,14028,14029,
8113714030,14031,14032,14033,14034,14035,14036,14037,14038,14039,14040,14041,
8113814042,14043,14044,14045,14046,14047,14048,14049,14050,14051,14052,14053,
8113914054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,
8114014066,14067,14068,14069,14070,14071,14072,14073,14074,14075,14076,14077,
8114114078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,
8114214090,14091,14092,14093,14094,14095,14096,14097,14098,14099,14100,14101,
8114314102,14103,14104,14105,14106,14107,14108,14109,14110,14111,14112,14113,
8114414114,14115,14116,14117,14118,14119,14120,14121,14122,14123,14124,14125,
8114514126,14127,14128,14129,14130,14131,14132,14133,14134,14135,14136,14137,
8114614138,14139,14140,14141,14142,14143,14144,14145,14146,14147,14148,14149,
8114714150,14151,14152,14153,14154,14155,14156,14157,14158,14159,14160,14161,
8114814162,14163,14164,14165,14166,14167,14168,14169,14170,14171,14172,14173,
8114914174,14175,14176,14177,14178,14179,14180,14181,14182,14183,14184,14185,
8115014186,14187,14188,14189,14190,14191,14192,14193,14194,14195,14196,14197,
8115114198,14199,14200,14201,14202,14203,14204,14205,14206,14207,14208,14209,
8115214210,14211,14212,14213,14214,14215,14216,14217,14218,14219,14220,14221,
8115314222,14223,14224,14225,14226,14227,14228,14229,14230,14231,14232,14233,
8115414234,14235,14236,14237,14238,14239,14240,14241,14242,14243,14244,14245,
8115514246,14247,14248,14249,14250,14251,14252,14253,14254,14255,14256,14257,
8115614258,14259,14260,14261,14262,14263,14264,14265,14266,14267,14268,14269,
8115714270,14271,14272,14273,14274,14275,14276,14277,14278,14279,14280,14281,
8115814282,14283,14284,14285,14286,14287,14288,14289,14290,14291,14292,14293,
8115914294,14295,14296,14297,14298,14299,14300,14301,14302,14303,14304,14305,
8116014306,14307,14308,14309,14310,14311,14312,14313,14314,14315,14316,14317,
8116114318,14319,14320,14321,14322,14323,14324,14325,14326,14327,14328,14329,
8116214330,14331,14332,14333,14334,14335,14336,14337,14338,14339,14340,14341,
8116314342,14343,14344,14345,14346,14347,14348,14349,14350,14351,14352,14353,
8116414354,14355,14356,14357,14358,14359,14360,14361,14362,14363,14364,14365,
8116514366,14367,14368,14369,14370,14371,14372,14373,14374,14375,14376,14377,
8116614378,14379,14380,14381,14382,14383,14384,14385,14386,14387,14388,14389,
8116714390,14391,14392,14393,14394,14395,14396,14397,14398,14399,14400,14401,
8116814402,14403,14404,14405,14406,14407,14408,14409,14410,14411,14412,14413,
8116914414,14415,14416,14417,14418,14419,14420,14421,14422,14423,14424,14425,
8117014426,14427,14428,14429,14430,14431,14432,14433,14434,14435,14436,14437,
8117114438,14439,14440,14441,14442,14443,14444,14445,14446,14447,14448,14449,
8117214450,14451,14452,14453,14454,14455,14456,14457,14458,14459,14460,14461,
8117314462,14463,14464,14465,14466,14467,14468,14469,14470,14471,14472,14473,
8117414474,14475,14476,14477,14478,14479,14480,14481,14482,14483,14484,14485,
8117514486,14487,14488,14489,14490,14491,14492,14493,14494,14495,14496,14497,
8117614498,14499,14500,14501,14502,14503,14504,14505,14506,14507,14508,14509,
8117714510,14511,14512,14513,14514,14515,14516,14517,14518,14519,14520,14521,
8117814522,14523,14524,14525,14526,14527,14528,14529,14530,14531,14532,14533,
8117914534,14535,14536,14537,14538,14539,14540,14541,14542,14543,14544,14545,
8118014546,14547,14548,14549,14550,14551,14552,14553,14554,14555,14556,14557,
8118114558,14559,14560,14561,14562,14563,14564,14565,14566,14567,14568,14569,
8118214570,14571,14572,14573,14574,14575,14576,14577,14578,14579,14580,14581,
8118314582,14583,14584,14585,14586,14587,14588,14589,14590,14591,14592,14593,
8118414594,14595,14596,14597,14598,14599,14600,14601,14602,14603,14604,14605,
8118514606,14607,14608,14609,14610,14611,14612,14613,14614,14615,14616,14617,
8118614618,14619,14620,14621,14622,14623,14624,14625,14626,14627,14628,14629,
8118714630,14631,14632,14633,14634,14635,14636,14637,14638,14639,14640,14641,
8118814642,14643,14644,14645,14646,14647,14648,14649,14650,14651,14652,14653,
8118914654,14655,14656,14657,14658,14659,14660,14661,14662,14663,14664,14665,
8119014666,14667,14668,14669,14670,14671,14672,14673,14674,14675,14676,14677,
8119114678,14679,14680,14681,14682,14683,14684,14685,14686,14687,14688,14689,
8119214690,14691,14692,14693,14694,14695,14696,14697,14698,14699,14700,14701,
8119314702,14703,14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,
8119414714,14715,14716,14717,14718,14719,14720,14721,14722,14723,14724,14725,
8119514726,14727,14728,14729,14730,14731,14732,14733,14734,14735,14736,14737,
8119614738,14739,14740,14741,14742,14743,14744,14745,14746,14747,14748,14749,
8119714750,14751,14752,14753,14754,14755,14756,14757,14758,14759,14760,14761,
8119814762,14763,14764,14765,14766,14767,14768,14769,14770,14771,14772,14773,
8119914774,14775,14776,14777,14778,14779,14780,14781,14782,14783,14784,14785,
8120014786,14787,14788,14789,14790,14791,14792,14793,14794,14795,14796,14797,
8120114798,14799,14800,14801,14802,14803,14804,14805,14806,14807,14808,14809,
8120214810,14811,14812,14813,14814,14815,14816,14817,14818,14819,14820,14821,
8120314822,14823,14824,14825,14826,14827,14828,14829,14830,14831,14832,14833,
8120414834,14835,14836,14837,14838,14839,14840,14841,14842,14843,14844,14845,
8120514846,14847,14848,14849,14850,14851,14852,14853,14854,14855,14856,14857,
8120614858,14859,14860,14861,14862,14863,14864,14865,14866,14867,14868,14869,
8120714870,14871,14872,14873,14874,14875,14876,14877,14878,14879,14880,14881,
8120814882,14883,14884,14885,14886,14887,14888,14889,14890,14891,14892,14893,
8120914894,14895,14896,14897,14898,14899,14900,14901,14902,14903,14904,14905,
8121014906,14907,14908,14909,14910,14911,14912,14913,14914,14915,14916,14917,
8121114918,14919,14920,14921,14922,14923,14924,14925,14926,14927,14928,14929,
8121214930,14931,14932,14933,14934,14935,14936,14937,14938,14939,14940,14941,
8121314942,14943,14944,14945,14946,14947,14948,14949,14950,14951,14952,14953,
8121414954,14955,14956,14957,14958,14959,14960,14961,14962,14963,14964,14965,
8121514966,14967,14968,14969,14970,14971,14972,14973,14974,14975,14976,14977,
8121614978,14979,14980,14981,14982,14983,14984,14985,14986,14987,14988,14989,
8121714990,14991,14992,14993,14994,14995,14996,14997,14998,14999,15000,15001,
8121815002,15003,15004,15005,15006,15007,15008,15009,15010,15011,15012,15013,
8121915014,15015,15016,15017,15018,15019,15020,15021,15022,15023,15024,15025,
8122015026,15027,15028,15029,15030,15031,15032,15033,15034,15035,15036,15037,
8122115038,15039,15040,15041,15042,15043,15044,15045,15046,15047,15048,15049,
8122215050,15051,15052,15053,15054,15055,15056,15057,15058,15059,15060,15061,
8122315062,15063,15064,15065,15066,15067,15068,15069,15070,15071,15072,15073,
8122415074,15075,15076,15077,15078,15079,15080,15081,15082,15083,15084,15085,
8122515086,15087,15088,15089,15090,15091,15092,15093,15094,15095,15096,15097,
8122615098,15099,15100,15101,15102,15103,15104,15105,15106,15107,15108,15109,
8122715110,15111,15112,15113,15114,15115,15116,15117,15118,15119,15120,15121,
8122815122,15123,15124,15125,15126,15127,15128,15129,15130,15131,15132,15133,
8122915134,15135,15136,15137,15138,15139,15140,15141,15142,15143,15144,15145,
8123015146,15147,15148,15149,15150,15151,15152,15153,15154,15155,15156,15157,
8123115158,15159,15160,15161,15162,15163,15164,15165,15166,15167,15168,15169,
8123215170,15171,15172,15173,15174,15175,15176,15177,15178,15179,15180,15181,
8123315182,15183,15184,15185,15186,15187,15188,15189,15190,15191,15192,15193,
8123415194,15195,15196,15197,15198,15199,15200,15201,15202,15203,15204,15205,
8123515206,15207,15208,15209,15210,15211,15212,15213,15214,15215,15216,15217,
8123615218,15219,15220,15221,15222,15223,15224,15225,15226,15227,15228,15229,
8123715230,15231,15232,15233,15234,15235,15236,15237,15238,15239,15240,15241,
8123815242,15243,15244,15245,15246,15247,15248,15249,15250,15251,15252,15253,
8123915254,15255,15256,15257,15258,15259,15260,15261,15262,15263,15264,15265,
8124015266,15267,15268,15269,15270,15271,15272,15273,15274,15275,15276,15277,
8124115278,15279,15280,15281,15282,15283,15284,15285,15286,15287,15288,15289,
8124215290,15291,15292,15293,15294,15295,15296,15297,15298,15299,15300,15301,
8124315302,15303,15304,15305,15306,15307,15308,15309,15310,15311,15312,15313,
8124415314,15315,15316,15317,15318,15319,15320,15321,15322,15323,15324,15325,
8124515326,15327,15328,15329,15330,15331,15332,15333,15334,15335,15336,15337,
8124615338,15339,15340,15341,15342,15343,15344,15345,15346,15347,15348,15349,
8124715350,15351,15352,15353,15354,15355,15356,15357,15358,15359,15360,15361,
8124815362,15363,15364,15365,15366,15367,15368,15369,15370,15371,15372,15373,
8124915374,15375,15376,15377,15378,15379,15380,15381,15382,15383,15384,15385,
8125015386,15387,15388,15389,15390,15391,15392,15393,15394,15395,15396,15397,
8125115398,15399,15400,15401,15402,15403,15404,15405,15406,15407,15408,15409,
8125215410,15411,15412,15413,15414,15415,15416,15417,15418,15419,15420,15421,
8125315422,15423,15424,15425,15426,15427,15428,15429,15430,15431,15432,15433,
8125415434,15435,15436,15437,15438,15439,15440,15441,15442,15443,15444,15445,
8125515446,15447,15448,15449,15450,15451,15452,15453,15454,15455,15456,15457,
8125615458,15459,15460,15461,15462,15463,15464,15465,15466,15467,15468,15469,
8125715470,15471,15472,15473,15474,15475,15476,15477,15478,15479,15480,15481,
8125815482,15483,15484,15485,15486,15487,15488,15489,15490,15491,15492,15493,
8125915494,15495,15496,15497,15498,15499,15500,15501,15502,15503,15504,15505,
8126015506,15507,15508,15509,15510,15511,15512,15513,15514,15515,15516,15517,
8126115518,15519,15520,15521,15522,15523,15524,15525,15526,15527,15528,15529,
8126215530,15531,15532,15533,15534,15535,15536,15537,15538,15539,15540,15541,
8126315542,15543,15544,15545,15546,15547,15548,15549,15550,15551,15552,15553,
8126415554,15555,15556,15557,15558,15559,15560,15561,15562,15563,15564,15565,
8126515566,15567,15568,15569,15570,15571,15572,15573,15574,15575,15576,15577,
8126615578,15579,15580,15581,15582,15583,15584,15585,15586,15587,15588,15589,
8126715590,15591,15592,15593,15594,15595,15596,15597,15598,15599,15600,15601,
8126815602,15603,15604,15605,15606,15607,15608,15609,15610,15611,15612,15613,
8126915614,15615,15616,15617,15618,15619,15620,15621,15622,15623,15624,15625,
8127015626,15627,15628,15629,15630,15631,15632,15633,15634,15635,15636,15637,
8127115638,15639,15640,15641,15642,15643,15644,15645,15646,15647,15648,15649,
8127215650,15651,15652,15653,15654,15655,15656,15657,15658,15659,15660,15661,
8127315662,15663,15664,15665,15666,15667,15668,15669,15670,15671,15672,15673,
8127415674,15675,15676,15677,15678,15679,15680,15681,15682,15683,15684,15685,
8127515686,15687,15688,15689,15690,15691,15692,15693,15694,15695,15696,15697,
8127615698,15699,15700,15701,15702,15703,15704,15705,15706,15707,15708,15709,
8127715710,15711,15712,15713,15714,15715,15716,15717,15718,15719,15720,15721,
8127815722,15723,15724,15725,15726,15727,15728,15729,15730,15731,15732,15733,
8127915734,15735,15736,15737,15738,15739,15740,15741,15742,15743,15744,15745,
8128015746,15747,15748,15749,15750,15751,15752,15753,15754,15755,15756,15757,
8128115758,15759,15760,15761,15762,15763,15764,15765,15766,15767,15768,15769,
8128215770,15771,15772,15773,15774,15775,15776,15777,15778,15779,15780,15781,
8128315782,15783,15784,15785,15786,15787,15788,15789,15790,15791,15792,15793,
8128415794,15795,15796,15797,15798,15799,15800,15801,15802,15803,15804,15805,
8128515806,15807,15808,15809,15810,15811,15812,15813,15814,15815,15816,15817,
8128615818,15819,15820,15821,15822,15823,15824,15825,15826,15827,15828,15829,
8128715830,15831,15832,15833,15834,15835,15836,15837,15838,15839,15840,15841,
8128815842,15843,15844,15845,15846,15847,15848,15849,15850,15851,15852,15853,
8128915854,15855,15856,15857,15858,15859,15860,15861,15862,15863,15864,15865,
8129015866,15867,15868,15869,15870,15871,15872,15873,15874,15875,15876,15877,
8129115878,15879,15880,15881,15882,15883,15884,15885,15886,15887,15888,15889,
8129215890,15891,15892,15893,15894,15895,15896,15897,15898,15899,15900,15901,
8129315902,15903,15904,15905,15906,15907,15908,15909,15910,15911,15912,15913,
8129415914,15915,15916,15917,15918,15919,15920,15921,15922,15923,15924,15925,
8129515926,15927,15928,15929,15930,15931,15932,15933,15934,15935,15936,15937,
8129615938,15939,15940,15941,15942,15943,15944,15945,15946,15947,15948,15949,
8129715950,15951,15952,15953,15954,15955,15956,15957,15958,15959,15960,15961,
8129815962,15963,15964,15965,15966,15967,15968,15969,15970,15971,15972,15973,
8129915974,15975,15976,15977,15978,15979,15980,15981,15982,15983,15984,15985,
8130015986,15987,15988,15989,15990,15991,15992,15993,15994,15995,15996,15997,
8130115998,15999,16000,16001,16002,16003,16004,16005,16006,16007,16008,16009,
8130216010,16011,16012,16013,16014,16015,16016,16017,16018,16019,16020,16021,
8130316022,16023,16024,16025,16026,16027,16028,16029,16030,16031,16032,16033,
8130416034,16035,16036,16037,16038,16039,16040,16041,16042,16043,16044,16045,
8130516046,16047,16048,16049,16050,16051,16052,16053,16054,16055,16056,16057,
8130616058,16059,16060,16061,16062,16063,16064,16065,16066,16067,16068,16069,
8130716070,16071,16072,16073,16074,16075,16076,16077,16078,16079,16080,16081,
8130816082,16083,16084,16085,16086,16087,16088,16089,16090,16091,16092,16093,
8130916094,16095,16096,16097,16098,16099,16100,16101,16102,16103,16104,16105,
8131016106,16107,16108,16109,16110,16111,16112,16113,16114,16115,16116,16117,
8131116118,16119,16120,16121,16122,16123,16124,16125,16126,16127,16128,16129,
8131216130,16131,16132,16133,16134,16135,16136,16137,16138,16139,16140,16141,
8131316142,16143,16144,16145,16146,16147,16148,16149,16150,16151,16152,16153,
8131416154,16155,16156,16157,16158,16159,16160,16161,16162,16163,16164,16165,
8131516166,16167,16168,16169,16170,16171,16172,16173,16174,16175,16176,16177,
8131616178,16179,16180,16181,16182,16183,16184,16185,16186,16187,16188,16189,
8131716190,16191,16192,16193,16194,16195,16196,16197,16198,16199,16200,16201,
8131816202,16203,16204,16205,16206,16207,16208,16209,16210,16211,16212,16213,
8131916214,16215,16216,16217,16218,16219,16220,16221,16222,16223,16224,16225,
8132016226,16227,16228,16229,16230,16231,16232,16233,16234,16235,16236,16237,
8132116238,16239,16240,16241,16242,16243,16244,16245,16246,16247,16248,16249,
8132216250,16251,16252,16253,16254,16255,16256,16257,16258,16259,16260,16261,
8132316262,16263,16264,16265,16266,16267,16268,16269,16270,16271,16272,16273,
8132416274,16275,16276,16277,16278,16279,16280,16281,16282,16283,16284,16285,
8132516286,16287,16288,16289,16290,16291,16292,16293,16294,16295,16296,16297,
8132616298,16299,16300,16301,16302,16303,16304,16305,16306,16307,16308,16309,
8132716310,16311,16312,16313,16314,16315,16316,16317,16318,16319,16320,16321,
8132816322,16323,16324,16325,16326,16327,16328,16329,16330,16331,16332,16333,
8132916334,16335,16336,16337,16338,16339,16340,16341,16342,16343,16344,16345,
8133016346,16347,16348,16349,16350,16351,16352,16353,16354,16355,16356,16357,
8133116358,16359,16360,16361,16362,16363,16364,16365,16366,16367,16368,16369,
8133216370,16371,16372,16373,16374,16375,16376,16377,16378,16379,16380,16381,
8133316382,16383,16384,16385,16386,16387,16388,16389,16390,16391,16392,16393,
8133416394,16395,16396,16397,16398,16399,16400,16401,16402,16403,16404,16405,
8133516406,16407,16408,16409,16410,16411,16412,16413,16414,16415,16416,16417,
8133616418,16419,16420,16421,16422,16423,16424,16425,16426,16427,16428,16429,
8133716430,16431,16432,16433,16434,16435,16436,16437,16438,16439,16440,16441,
8133816442,16443,16444,16445,16446,16447,16448,16449,16450,16451,16452,16453,
8133916454,16455,16456,16457,16458,16459,16460,16461,16462,16463,16464,16465,
8134016466,16467,16468,16469,16470,16471,16472,16473,16474,16475,16476,16477,
8134116478,16479,16480,16481,16482,16483,16484,16485,16486,16487,16488,16489,
8134216490,16491,16492,16493,16494,16495,16496,16497,16498,16499,16500,16501,
8134316502,16503,16504,16505,16506,16507,16508,16509,16510,16511,16512,16513,
8134416514,16515,16516,16517,16518,16519,16520,16521,16522,16523,16524,16525,
8134516526,16527,16528,16529,16530,16531,16532,16533,16534,16535,16536,16537,
8134616538,16539,16540,16541,16542,16543,16544,16545,16546,16547,16548,16549,
8134716550,16551,16552,16553,16554,16555,16556,16557,16558,16559,16560,16561,
8134816562,16563,16564,16565,16566,16567,16568,16569,16570,16571,16572,16573,
8134916574,16575,16576,16577,16578,16579,16580,16581,16582,16583,16584,16585,
8135016586,16587,16588,16589,16590,16591,16592,16593,16594,16595,16596,16597,
8135116598,16599,16600,16601,16602,16603,16604,16605,16606,16607,16608,16609,
8135216610,16611,16612,16613,16614,16615,16616,16617,16618,16619,16620,16621,
8135316622,16623,16624,16625,16626,16627,16628,16629,16630,16631,16632,16633,
8135416634,16635,16636,16637,16638,16639,16640,16641,16642,16643,16644,16645,
8135516646,16647,16648,16649,16650,16651,16652,16653,16654,16655,16656,16657,
8135616658,16659,16660,16661,16662,16663,16664,16665,16666,16667,16668,16669,
8135716670,16671,16672,16673,16674,16675,16676,16677,16678,16679,16680,16681,
8135816682,16683,16684,16685,16686,16687,16688,16689,16690,16691,16692,16693,
8135916694,16695,16696,16697,16698,16699,16700,16701,16702,16703,16704,16705,
8136016706,16707,16708,16709,16710,16711,16712,16713,16714,16715,16716,16717,
8136116718,16719,16720,16721,16722,16723,16724,16725,16726,16727,16728,16729,
8136216730,16731,16732,16733,16734,16735,16736,16737,16738,16739,16740,16741,
8136316742,16743,16744,16745,16746,16747,16748,16749,16750,16751,16752,16753,
8136416754,16755,16756,16757,16758,16759,16760,16761,16762,16763,16764,16765,
8136516766,16767,16768,16769,16770,16771,16772,16773,16774,16775,16776,16777,
8136616778,16779,16780,16781,16782,16783,16784,16785,16786,16787,16788,16789,
8136716790,16791,16792,16793,16794,16795,16796,16797,16798,16799,16800,16801,
8136816802,16803,16804,16805,16806,16807,16808,16809,16810,16811,16812,16813,
8136916814,16815,16816,16817,16818,16819,16820,16821,16822,16823,16824,16825,
8137016826,16827,16828,16829,16830,16831,16832,16833,16834,16835,16836,16837,
8137116838,16839,16840,16841,16842,16843,16844,16845,16846,16847,16848,16849,
8137216850,16851,16852,16853,16854,16855,16856,16857,16858,16859,16860,16861,
8137316862,16863,16864,16865,16866,16867,16868,16869,16870,16871,16872,16873,
8137416874,16875,16876,16877,16878,16879,16880,16881,16882,16883,16884,16885,
8137516886,16887,16888,16889,16890,16891,16892,16893,16894,16895,16896,16897,
8137616898,16899,16900,16901,16902,16903,16904,16905,16906,16907,16908,16909,
8137716910,16911,16912,16913,16914,16915,16916,16917,16918,16919,16920,16921,
8137816922,16923,16924,16925,16926,16927,16928,16929,16930,16931,16932,16933,
8137916934,16935,16936,16937,16938,16939,16940,16941,16942,16943,16944,16945,
8138016946,16947,16948,16949,16950,16951,16952,16953,16954,16955,16956,16957,
8138116958,16959,16960,16961,16962,16963,16964,16965,16966,16967,16968,16969,
8138216970,16971,16972,16973,16974,16975,16976,16977,16978,16979,16980,16981,
8138316982,16983,16984,16985,16986,16987,16988,16989,16990,16991,16992,16993,
8138416994,16995,16996,16997,16998,16999,17000,17001,17002,17003,17004,17005,
8138517006,17007,17008,17009,17010,17011,17012,17013,17014,17015,17016,17017,
8138617018,17019,17020,17021,17022,17023,17024,17025,17026,17027,17028,17029,
8138717030,17031,17032,17033,17034,17035,17036,17037,17038,17039,17040,17041,
8138817042,17043,17044,17045,17046,17047,17048,17049,17050,17051,17052,17053,
8138917054,17055,17056,17057,17058,17059,17060,17061,17062,17063,17064,17065,
8139017066,17067,17068,17069,17070,17071,17072,17073,17074,17075,17076,17077,
8139117078,17079,17080,17081,17082,17083,17084,17085,17086,17087,17088,17089,
8139217090,17091,17092,17093,17094,17095,17096,17097,17098,17099,17100,17101,
8139317102,17103,17104,17105,17106,17107,17108,17109,17110,17111,17112,17113,
8139417114,17115,17116,17117,17118,17119,17120,17121,17122,17123,17124,17125,
8139517126,17127,17128,17129,17130,17131,17132,17133,17134,17135,17136,17137,
8139617138,17139,17140,17141,17142,17143,17144,17145,17146,17147,17148,17149,
8139717150,17151,17152,17153,17154,17155,17156,17157,17158,17159,17160,17161,
8139817162,17163,17164,17165,17166,17167,17168,17169,17170,17171,17172,17173,
8139917174,17175,17176,17177,17178,17179,17180,17181,17182,17183,17184,17185,
8140017186,17187,17188,17189,17190,17191,17192,17193,17194,17195,17196,17197,
8140117198,17199,17200,17201,17202,17203,17204,17205,17206,17207,17208,17209,
8140217210,17211,17212,17213,17214,17215,17216,17217,17218,17219,17220,17221,
8140317222,17223,17224,17225,17226,17227,17228,17229,17230,17231,17232,17233,
8140417234,17235,17236,17237,17238,17239,17240,17241,17242,17243,17244,17245,
8140517246,17247,17248,17249,17250,17251,17252,17253,17254,17255,17256,17257,
8140617258,17259,17260,17261,17262,17263,17264,17265,17266,17267,17268,17269,
8140717270,17271,17272,17273,17274,17275,17276,17277,17278,17279,17280,17281,
8140817282,17283,17284,17285,17286,17287,17288,17289,17290,17291,17292,17293,
8140917294,17295,17296,17297,17298,17299,17300,17301,17302,17303,17304,17305,
8141017306,17307,17308,17309,17310,17311,17312,17313,17314,17315,17316,17317,
8141117318,17319,17320,17321,17322,17323,17324,17325,17326,17327,17328,17329,
8141217330,17331,17332,17333,17334,17335,17336,17337,17338,17339,17340,17341,
8141317342,17343,17344,17345,17346,17347,17348,17349,17350,17351,17352,17353,
8141417354,17355,17356,17357,17358,17359,17360,17361,17362,17363,17364,17365,
8141517366,17367,17368,17369,17370,17371,17372,17373,17374,17375,17376,17377,
8141617378,17379,17380,17381,17382,17383,17384,17385,17386,17387,17388,17389,
8141717390,17391,17392,17393,17394,17395,17396,17397,17398,17399,17400,17401,
8141817402,17403,17404,17405,17406,17407,17408,17409,17410,17411,17412,17413,
8141917414,17415,17416,17417,17418,17419,17420,17421,17422,17423,17424,17425,
8142017426,17427,17428,17429,17430,17431,17432,17433,17434,17435,17436,17437,
8142117438,17439,17440,17441,17442,17443,17444,17445,17446,17447,17448,17449,
8142217450,17451,17452,17453,17454,17455,17456,17457,17458,17459,17460,17461,
8142317462,17463,17464,17465,17466,17467,17468,17469,17470,17471,17472,17473,
8142417474,17475,17476,17477,17478,17479,17480,17481,17482,17483,17484,17485,
8142517486,17487,17488,17489,17490,17491,17492,17493,17494,17495,17496,17497,
8142617498,17499,17500,17501,17502,17503,17504,17505,17506,17507,17508,17509,
8142717510,17511,17512,17513,17514,17515,17516,17517,17518,17519,17520,17521,
8142817522,17523,17524,17525,17526,17527,17528,17529,17530,17531,17532,17533,
8142917534,17535,17536,17537,17538,17539,17540,17541,17542,17543,17544,17545,
8143017546,17547,17548,17549,17550,17551,17552,17553,17554,17555,17556,17557,
8143117558,17559,17560,17561,17562,17563,17564,17565,17566,17567,17568,17569,
8143217570,17571,17572,17573,17574,17575,17576,17577,17578,17579,17580,17581,
8143317582,17583,17584,17585,17586,17587,17588,17589,17590,17591,17592,17593,
8143417594,17595,17596,17597,17598,17599,17600,17601,17602,17603,17604,17605,
8143517606,17607,17608,17609,17610,17611,17612,17613,17614,17615,17616,17617,
8143617618,17619,17620,17621,17622,17623,17624,17625,17626,17627,17628,17629,
8143717630,17631,17632,17633,17634,17635,17636,17637,17638,17639,17640,17641,
8143817642,17643,17644,17645,17646,17647,17648,17649,17650,17651,17652,17653,
8143917654,17655,17656,17657,17658,17659,17660,17661,17662,17663,17664,17665,
8144017666,17667,17668,17669,17670,17671,17672,17673,17674,17675,17676,17677,
8144117678,17679,17680,17681,17682,17683,17684,17685,17686,17687,17688,17689,
8144217690,17691,17692,17693,17694,17695,17696,17697,17698,17699,17700,17701,
8144317702,17703,17704,17705,17706,17707,17708,17709,17710,17711,17712,17713,
8144417714,17715,17716,17717,17718,17719,17720,17721,17722,17723,17724,17725,
8144517726,17727,17728,17729,17730,17731,17732,17733,17734,17735,17736,17737,
8144617738,17739,17740,17741,17742,17743,17744,17745,17746,17747,17748,17749,
8144717750,17751,17752,17753,17754,17755,17756,17757,17758,17759,17760,17761,
8144817762,17763,17764,17765,17766,17767,17768,17769,17770,17771,17772,17773,
8144917774,17775,17776,17777,17778,17779,17780,17781,17782,17783,17784,17785,
8145017786,17787,17788,17789,17790,17791,17792,17793,17794,17795,17796,17797,
8145117798,17799,17800,17801,17802,17803,17804,17805,17806,17807,17808,17809,
8145217810,17811,17812,17813,17814,17815,17816,17817,17818,17819,17820,17821,
8145317822,17823,17824,17825,17826,17827,17828,17829,17830,17831,17832,17833,
8145417834,17835,17836,17837,17838,17839,17840,17841,17842,17843,17844,17845,
8145517846,17847,17848,17849,17850,17851,17852,17853,17854,17855,17856,17857,
8145617858,17859,17860,17861,17862,17863,17864,17865,17866,17867,17868,17869,
8145717870,17871,17872,17873,17874,17875,17876,17877,17878,17879,17880,17881,
8145817882,17883,17884,17885,17886,17887,17888,17889,17890,17891,17892,17893,
8145917894,17895,17896,17897,17898,17899,17900,17901,17902,17903,17904,17905,
8146017906,17907,17908,17909,17910,17911,17912,17913,17914,17915,17916,17917,
8146117918,17919,17920,17921,17922,17923,17924,17925,17926,17927,17928,17929,
8146217930,17931,17932,17933,17934,17935,17936,17937,17938,17939,17940,17941,
8146317942,17943,17944,17945,17946,17947,17948,17949,17950,17951,17952,17953,
8146417954,17955,17956,17957,17958,17959,17960,17961,17962,17963,17964,17965,
8146517966,17967,17968,17969,17970,17971,17972,17973,17974,17975,17976,17977,
8146617978,17979,17980,17981,17982,17983,17984,17985,17986,17987,17988,17989,
8146717990,17991,17992,17993,17994,17995,17996,17997,17998,17999,18000,18001,
8146818002,18003,18004,18005,18006,18007,18008,18009,18010,18011,18012,18013,
8146918014,18015,18016,18017,18018,18019,18020,18021,18022,18023,18024,18025,
8147018026,18027,18028,18029,18030,18031,18032,18033,18034,18035,18036,18037,
8147118038,18039,18040,18041,18042,18043,18044,18045,18046,18047,18048,18049,
8147218050,18051,18052,18053,18054,18055,18056,18057,18058,18059,18060,18061,
8147318062,18063,18064,18065,18066,18067,18068,18069,18070,18071,18072,18073,
8147418074,18075,18076,18077,18078,18079,18080,18081,18082,18083,18084,18085,
8147518086,18087,18088,18089,18090,18091,18092,18093,18094,18095,18096,18097,
8147618098,18099,18100,18101,18102,18103,18104,18105,18106,18107,18108,18109,
8147718110,18111,18112,18113,18114,18115,18116,18117,18118,18119,18120,18121,
8147818122,18123,18124,18125,18126,18127,18128,18129,18130,18131,18132,18133,
8147918134,18135,18136,18137,18138,18139,18140,18141,18142,18143,18144,18145,
8148018146,18147,18148,18149,18150,18151,18152,18153,18154,18155,18156,18157,
8148118158,18159,18160,18161,18162,18163,18164,18165,18166,18167,18168,18169,
8148218170,18171,18172,18173,18174,18175,18176,18177,18178,18179,18180,18181,
8148318182,18183,18184,18185,18186,18187,18188,18189,18190,18191,18192,18193,
8148418194,18195,18196,18197,18198,18199,18200,18201,18202,18203,18204,18205,
8148518206,18207,18208,18209,18210,18211,18212,18213,18214,18215,18216,18217,
8148618218,18219,18220,18221,18222,18223,18224,18225,18226,18227,18228,18229,
8148718230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,
8148818242,18243,18244,18245,18246,18247,18248,18249,18250,18251,18252,18253,
8148918254,18255,18256,18257,18258,18259,18260,18261,18262,18263,18264,18265,
8149018266,18267,18268,18269,18270,18271,18272,18273,18274,18275,18276,18277,
8149118278,18279,18280,18281,18282,18283,18284,18285,18286,18287,18288,18289,
8149218290,18291,18292,18293,18294,18295,18296,18297,18298,18299,18300,18301,
8149318302,18303,18304,18305,18306,18307,18308,18309,18310,18311,18312,18313,
8149418314,18315,18316,18317,18318,18319,18320,18321,18322,18323,18324,18325,
8149518326,18327,18328,18329,18330,18331,18332,18333,18334,18335,18336,18337,
8149618338,18339,18340,18341,18342,18343,18344,18345,18346,18347,18348,18349,
8149718350,18351,18352,18353,18354,18355,18356,18357,18358,18359,18360,18361,
8149818362,18363,18364,18365,18366,18367,18368,18369,18370,18371,18372,18373,
8149918374,18375,18376,18377,18378,18379,18380,18381,18382,18383,18384,18385,
8150018386,18387,18388,18389,18390,18391,18392,18393,18394,18395,18396,18397,
8150118398,18399,18400,18401,18402,18403,18404,18405,18406,18407,18408,18409,
8150218410,18411,18412,18413,18414,18415,18416,18417,18418,18419,18420,18421,
8150318422,18423,18424,18425,18426,18427,18428,18429,18430,18431,18432,18433,
8150418434,18435,18436,18437,18438,18439,18440,18441,18442,18443,18444,18445,
8150518446,18447,18448,18449,18450,18451,18452,18453,18454,18455,18456,18457,
8150618458,18459,18460,18461,18462,18463,18464,18465,18466,18467,18468,18469,
8150718470,18471,18472,18473,18474,18475,18476,18477,18478,18479,18480,18481,
8150818482,18483,18484,18485,18486,18487,18488,18489,18490,18491,18492,18493,
8150918494,18495,18496,18497,18498,18499,18500,18501,18502,18503,18504,18505,
8151018506,18507,18508,18509,18510,18511,18512,18513,18514,18515,18516,18517,
8151118518,18519,18520,18521,18522,18523,18524,18525,18526,18527,18528,18529,
8151218530,18531,18532,18533,18534,18535,18536,18537,18538,18539,18540,18541,
8151318542,18543,18544,18545,18546,18547,18548,18549,18550,18551,18552,18553,
8151418554,18555,18556,18557,18558,18559,18560,18561,18562,18563,18564,18565,
8151518566,18567,18568,18569,18570,18571,18572,18573,18574,18575,18576,18577,
8151618578,18579,18580,18581,18582,18583,18584,18585,18586,18587,18588,18589,
8151718590,18591,18592,18593,18594,18595,18596,18597,18598,18599,18600,18601,
8151818602,18603,18604,18605,18606,18607,18608,18609,18610,18611,18612,18613,
8151918614,18615,18616,18617,18618,18619,18620,18621,18622,18623,18624,18625,
8152018626,18627,18628,18629,18630,18631,18632,18633,18634,18635,18636,18637,
8152118638,18639,18640,18641,18642,18643,18644,18645,18646,18647,18648,18649,
8152218650,18651,18652,18653,18654,18655,18656,18657,18658,18659,18660,18661,
8152318662,18663,18664,18665,18666,18667,18668,18669,18670,18671,18672,18673,
8152418674,18675,18676,18677,18678,18679,18680,18681,18682,18683,18684,18685,
8152518686,18687,18688,18689,18690,18691,18692,18693,18694,18695,18696,18697,
8152618698,18699,18700,18701,18702,18703,18704,18705,18706,18707,18708,18709,
8152718710,18711,18712,18713,18714,18715,18716,18717,18718,18719,18720,18721,
8152818722,18723,18724,18725,18726,18727,18728,18729,18730,18731,18732,18733,
8152918734,18735,18736,18737,18738,18739,18740,18741,18742,18743,18744,18745,
8153018746,18747,18748,18749,18750,18751,18752,18753,18754,18755,18756,18757,
8153118758,18759,18760,18761,18762,18763,18764,18765,18766,18767,18768,18769,
8153218770,18771,18772,18773,18774,18775,18776,18777,18778,18779,18780,18781,
8153318782,18783,18784,18785,18786,18787,18788,18789,18790,18791,18792,18793,
8153418794,18795,18796,18797,18798,18799,18800,18801,18802,18803,18804,18805,
8153518806,18807,18808,18809,18810,18811,18812,18813,18814,18815,18816,18817,
8153618818,18819,18820,18821,18822,18823,18824,18825,18826,18827,18828,18829,
8153718830,18831,18832,18833,18834,18835,18836,18837,18838,18839,18840,18841,
8153818842,18843,18844,18845,18846,18847,18848,18849,18850,18851,18852,18853,
8153918854,18855,18856,18857,18858,18859,18860,18861,18862,18863,18864,18865,
8154018866,18867,18868,18869,18870,18871,18872,18873,18874,18875,18876,18877,
8154118878,18879,18880,18881,18882,18883,18884,18885,18886,18887,18888,18889,
8154218890,18891,18892,18893,18894,18895,18896,18897,18898,18899,18900,18901,
8154318902,18903,18904,18905,18906,18907,18908,18909,18910,18911,18912,18913,
8154418914,18915,18916,18917,18918,18919,18920,18921,18922,18923,18924,18925,
8154518926,18927,18928,18929,18930,18931,18932,18933,18934,18935,18936,18937,
8154618938,18939,18940,18941,18942,18943,18944,18945,18946,18947,18948,18949,
8154718950,18951,18952,18953,18954,18955,18956,18957,18958,18959,18960,18961,
8154818962,18963,18964,18965,18966,18967,18968,18969,18970,18971,18972,18973,
8154918974,18975,18976,18977,18978,18979,18980,18981,18982,18983,18984,18985,
8155018986,18987,18988,18989,18990,18991,18992,18993,18994,18995,18996,18997,
8155118998,18999,19000,19001,19002,19003,19004,19005,19006,19007,19008,19009,
8155219010,19011,19012,19013,19014,19015,19016,19017,19018,19019,19020,19021,
8155319022,19023,19024,19025,19026,19027,19028,19029,19030,19031,19032,19033,
8155419034,19035,19036,19037,19038,19039,19040,19041,19042,19043,19044,19045,
8155519046,19047,19048,19049,19050,19051,19052,19053,19054,19055,19056,19057,
8155619058,19059,19060,19061,19062,19063,19064,19065,19066,19067,19068,19069,
8155719070,19071,19072,19073,19074,19075,19076,19077,19078,19079,19080,19081,
8155819082,19083,19084,19085,19086,19087,19088,19089,19090,19091,19092,19093,
8155919094,19095,19096,19097,19098,19099,19100,19101,19102,19103,19104,19105,
8156019106,19107,19108,19109,19110,19111,19112,19113,19114,19115,19116,19117,
8156119118,19119,19120,19121,19122,19123,19124,19125,19126,19127,19128,19129,
8156219130,19131,19132,19133,19134,19135,19136,19137,19138,19139,19140,19141,
8156319142,19143,19144,19145,19146,19147,19148,19149,19150,19151,19152,19153,
8156419154,19155,19156,19157,19158,19159,19160,19161,19162,19163,19164,19165,
8156519166,19167,19168,19169,19170,19171,19172,19173,19174,19175,19176,19177,
8156619178,19179,19180,19181,19182,19183,19184,19185,19186,19187,19188,19189,
8156719190,19191,19192,19193,19194,19195,19196,19197,19198,19199,19200,19201,
8156819202,19203,19204,19205,19206,19207,19208,19209,19210,19211,19212,19213,
8156919214,19215,19216,19217,19218,19219,19220,19221,19222,19223,19224,19225,
8157019226,19227,19228,19229,19230,19231,19232,19233,19234,19235,19236,19237,
8157119238,19239,19240,19241,19242,19243,19244,19245,19246,19247,19248,19249,
8157219250,19251,19252,19253,19254,19255,19256,19257,19258,19259,19260,19261,
8157319262,19263,19264,19265,19266,19267,19268,19269,19270,19271,19272,19273,
8157419274,19275,19276,19277,19278,19279,19280,19281,19282,19283,19284,19285,
8157519286,19287,19288,19289,19290,19291,19292,19293,19294,19295,19296,19297,
8157619298,19299,19300,19301,19302,19303,19304,19305,19306,19307,19308,19309,
8157719310,19311,19312,19313,19314,19315,19316,19317,19318,19319,19320,19321,
8157819322,19323,19324,19325,19326,19327,19328,19329,19330,19331,19332,19333,
8157919334,19335,19336,19337,19338,19339,19340,19341,19342,19343,19344,19345,
8158019346,19347,19348,19349,19350,19351,19352,19353,19354,19355,19356,19357,
8158119358,19359,19360,19361,19362,19363,19364,19365,19366,19367,19368,19369,
8158219370,19371,19372,19373,19374,19375,19376,19377,19378,19379,19380,19381,
8158319382,19383,19384,19385,19386,19387,19388,19389,19390,19391,19392,19393,
8158419394,19395,19396,19397,19398,19399,19400,19401,19402,19403,19404,19405,
8158519406,19407,19408,19409,19410,19411,19412,19413,19414,19415,19416,19417,
8158619418,19419,19420,19421,19422,19423,19424,19425,19426,19427,19428,19429,
8158719430,19431,19432,19433,19434,19435,19436,19437,19438,19439,19440,19441,
8158819442,19443,19444,19445,19446,19447,19448,19449,19450,19451,19452,19453,
8158919454,19455,19456,19457,19458,19459,19460,19461,19462,19463,19464,19465,
8159019466,19467,19468,19469,19470,19471,19472,19473,19474,19475,19476,19477,
8159119478,19479,19480,19481,19482,19483,19484,19485,19486,19487,19488,19489,
8159219490,19491,19492,19493,19494,19495,19496,19497,19498,19499,19500,19501,
8159319502,19503,19504,19505,19506,19507,19508,19509,19510,19511,19512,19513,
8159419514,19515,19516,19517,19518,19519,19520,19521,19522,19523,19524,19525,
8159519526,19527,19528,19529,19530,19531,19532,19533,19534,19535,19536,19537,
8159619538,19539,19540,19541,19542,19543,19544,19545,19546,19547,19548,19549,
8159719550,19551,19552,19553,19554,19555,19556,19557,19558,19559,19560,19561,
8159819562,19563,19564,19565,19566,19567,19568,19569,19570,19571,19572,19573,
8159919574,19575,19576,19577,19578,19579,19580,19581,19582,19583,19584,19585,
8160019586,19587,19588,19589,19590,19591,19592,19593,19594,19595,19596,19597,
8160119598,19599,19600,19601,19602,19603,19604,19605,19606,19607,19608,19609,
8160219610,19611,19612,19613,19614,19615,19616,19617,19618,19619,19620,19621,
8160319622,19623,19624,19625,19626,19627,19628,19629,19630,19631,19632,19633,
8160419634,19635,19636,19637,19638,19639,19640,19641,19642,19643,19644,19645,
8160519646,19647,19648,19649,19650,19651,19652,19653,19654,19655,19656,19657,
8160619658,19659,19660,19661,19662,19663,19664,19665,19666,19667,19668,19669,
8160719670,19671,19672,19673,19674,19675,19676,19677,19678,19679,19680,19681,
8160819682,19683,19684,19685,19686,19687,19688,19689,19690,19691,19692,19693,
8160919694,19695,19696,19697,19698,19699,19700,19701,19702,19703,19704,19705,
8161019706,19707,19708,19709,19710,19711,19712,19713,19714,19715,19716,19717,
8161119718,19719,19720,19721,19722,19723,19724,19725,19726,19727,19728,19729,
8161219730,19731,19732,19733,19734,19735,19736,19737,19738,19739,19740,19741,
8161319742,19743,19744,19745,19746,19747,19748,19749,19750,19751,19752,19753,
8161419754,19755,19756,19757,19758,19759,19760,19761,19762,19763,19764,19765,
8161519766,19767,19768,19769,19770,19771,19772,19773,19774,19775,19776,19777,
8161619778,19779,19780,19781,19782,19783,19784,19785,19786,19787,19788,19789,
8161719790,19791,19792,19793,19794,19795,19796,19797,19798,19799,19800,19801,
8161819802,19803,19804,19805,19806,19807,19808,19809,19810,19811,19812,19813,
8161919814,19815,19816,19817,19818,19819,19820,19821,19822,19823,19824,19825,
8162019826,19827,19828,19829,19830,19831,19832,19833,19834,19835,19836,19837,
8162119838,19839,19840,19841,19842,19843,19844,19845,19846,19847,19848,19849,
8162219850,19851,19852,19853,19854,19855,19856,19857,19858,19859,19860,19861,
8162319862,19863,19864,19865,19866,19867,19868,19869,19870,19871,19872,19873,
8162419874,19875,19876,19877,19878,19879,19880,19881,19882,19883,19884,19885,
8162519886,19887,19888,19889,19890,19891,19892,19893,19894,19895,19896,19897,
8162619898,19899,19900,19901,19902,19903,19904,19905,19906,19907,19908,19909,
8162719910,19911,19912,19913,19914,19915,19916,19917,19918,19919,19920,19921,
8162819922,19923,19924,19925,19926,19927,19928,19929,19930,19931,19932,19933,
8162919934,19935,19936,19937,19938,19939,19940,19941,19942,19943,19944,19945,
8163019946,19947,19948,19949,19950,19951,19952,19953,19954,19955,19956,19957,
8163119958,19959,19960,19961,19962,19963,19964,19965,19966,19967,19968,19969,
8163219970,19971,19972,19973,19974,19975,19976,19977,19978,19979,19980,19981,
8163319982,19983,19984,19985,19986,19987,19988,19989,19990,19991,19992,19993,
8163419994,19995,19996,19997,19998,19999,20000,20001,20002,20003,20004,20005,
8163520006,20007,20008,20009,20010,20011,20012,20013,20014,20015,20016,20017,
8163620018,20019,20020,20021,20022,20023,20024,20025,20026,20027,20028,20029,
8163720030,20031,20032,20033,20034,20035,20036,20037,20038,20039,20040,20041,
8163820042,20043,20044,20045,20046,20047,20048,20049,20050,20051,20052,20053,
8163920054,20055,20056,20057,20058,20059,20060,20061,20062,20063,20064,20065,
8164020066,20067,20068,20069,20070,20071,20072,20073,20074,20075,20076,20077,
8164120078,20079,20080,20081,20082,20083,20084,20085,20086,20087,20088,20089,
8164220090,20091,20092,20093,20094,20095,20096,20097,20098,20099,20100,20101,
8164320102,20103,20104,20105,20106,20107,20108,20109,20110,20111,20112,20113,
8164420114,20115,20116,20117,20118,20119,20120,20121,20122,20123,20124,20125,
8164520126,20127,20128,20129,20130,20131,20132,20133,20134,20135,20136,20137,
8164620138,20139,20140,20141,20142,20143,20144,20145,20146,20147,20148,20149,
8164720150,20151,20152,20153,20154,20155,20156,20157,20158,20159,20160,20161,
8164820162,20163,20164,20165,20166,20167,20168,20169,20170,20171,20172,20173,
8164920174,20175,20176,20177,20178,20179,20180,20181,20182,20183,20184,20185,
8165020186,20187,20188,20189,20190,20191,20192,20193,20194,20195,20196,20197,
8165120198,20199,20200,20201,20202,20203,20204,20205,20206,20207,20208,20209,
8165220210,20211,20212,20213,20214,20215,20216,20217,20218,20219,20220,20221,
8165320222,20223,20224,20225,20226,20227,20228,20229,20230,20231,20232,20233,
8165420234,20235,20236,20237,20238,20239,20240,20241,20242,20243,20244,20245,
8165520246,20247,20248,20249,20250,20251,20252,20253,20254,20255,20256,20257,
8165620258,20259,20260,20261,20262,20263,20264,20265,20266,20267,20268,20269,
8165720270,20271,20272,20273,20274,20275,20276,20277,20278,20279,20280,20281,
8165820282,20283,20284,20285,20286,20287,20288,20289,20290,20291,20292,20293,
8165920294,20295,20296,20297,20298,20299,20300,20301,20302,20303,20304,20305,
8166020306,20307,20308,20309,20310,20311,20312,20313,20314,20315,20316,20317,
8166120318,20319,20320,20321,20322,20323,20324,20325,20326,20327,20328,20329,
8166220330,20331,20332,20333,20334,20335,20336,20337,20338,20339,20340,20341,
8166320342,20343,20344,20345,20346,20347,20348,20349,20350,20351,20352,20353,
8166420354,20355,20356,20357,20358,20359,20360,20361,20362,20363,20364,20365,
8166520366,20367,20368,20369,20370,20371,20372,20373,20374,20375,20376,20377,
8166620378,20379,20380,20381,20382,20383,20384,20385,20386,20387,20388,20389,
8166720390,20391,20392,20393,20394,20395,20396,20397,20398,20399,20400,20401,
8166820402,20403,20404,20405,20406,20407,20408,20409,20410,20411,20412,20413,
8166920414,20415,20416,20417,20418,20419,20420,20421,20422,20423,20424,20425,
8167020426,20427,20428,20429,20430,20431,20432,20433,20434,20435,20436,20437,
8167120438,20439,20440,20441,20442,20443,20444,20445,20446,20447,20448,20449,
8167220450,20451,20452,20453,20454,20455,20456,20457,20458,20459,20460,20461,
8167320462,20463,20464,20465,20466,20467,20468,20469,20470,20471,20472,20473,
8167420474,20475,20476,20477,20478,20479,20480,20481,20482,20483,20484,20485,
8167520486,20487,20488,20489,20490,20491,20492,20493,20494,20495,20496,20497,
8167620498,20499,20500,20501,20502,20503,20504,20505,20506,20507,20508,20509,
8167720510,20511,20512,20513,20514,20515,20516,20517,20518,20519,20520,20521,
8167820522,20523,20524,20525,20526,20527,20528,20529,20530,20531,20532,20533,
8167920534,20535,20536,20537,20538,20539,20540,20541,20542,20543,20544,20545,
8168020546,20547,20548,20549,20550,20551,20552,20553,20554,20555,20556,20557,
8168120558,20559,20560,20561,20562,20563,20564,20565,20566,20567,20568,20569,
8168220570,20571,20572,20573,20574,20575,20576,20577,20578,20579,20580,20581,
8168320582,20583,20584,20585,20586,20587,20588,20589,20590,20591,20592,20593,
8168420594,20595,20596,20597,20598,20599,20600,20601,20602,20603,20604,20605,
8168520606,20607,20608,20609,20610,20611,20612,20613,20614,20615,20616,20617,
8168620618,20619,20620,20621,20622,20623,20624,20625,20626,20627,20628,20629,
8168720630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,
8168820642,20643,20644,20645,20646,20647,20648,20649,20650,20651,20652,20653,
8168920654,20655,20656,20657,20658,20659,20660,20661,20662,20663,20664,20665,
8169020666,20667,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,
8169120678,20679,20680,20681,20682,20683,20684,20685,20686,20687,20688,20689,
8169220690,20691,20692,20693,20694,20695,20696,20697,20698,20699,20700,20701,
8169320702,20703,20704,20705,20706,20707,20708,20709,20710,20711,20712,20713,
8169420714,20715,20716,20717,20718,20719,20720,20721,20722,20723,20724,20725,
8169520726,20727,20728,20729,20730,20731,20732,20733,20734,20735,20736,20737,
8169620738,20739,20740,20741,20742,20743,20744,20745,20746,20747,20748,20749,
8169720750,20751,20752,20753,20754,20755,20756,20757,20758,20759,20760,20761,
8169820762,20763,20764,20765,20766,20767,20768,20769,20770,20771,20772,20773,
8169920774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,
8170020786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,
8170120798,20799,20800,20801,20802,20803,20804,20805,20806,20807,20808,20809,
8170220810,20811,20812,20813,20814,20815,20816,20817,20818,20819,20820,20821,
8170320822,20823,20824,20825,20826,20827,20828,20829,20830,20831,20832,20833,
8170420834,20835,20836,20837,20838,20839,20840,20841,20842,20843,20844,20845,
8170520846,20847,20848,20849,20850,20851,20852,20853,20854,20855,20856,20857,
8170620858,20859,20860,20861,20862,20863,20864,20865,20866,20867,20868,20869,
8170720870,20871,20872,20873,20874,20875,20876,20877,20878,20879,20880,20881,
8170820882,20883,20884,20885,20886,20887,20888,20889,20890,20891,20892,20893,
8170920894,20895,20896,20897,20898,20899,20900,20901,20902,20903,20904,20905,
8171020906,20907,20908,20909,20910,20911,20912,20913,20914,20915,20916,20917,
8171120918,20919,20920,20921,20922,20923,20924,20925,20926,20927,20928,20929,
8171220930,20931,20932,20933,20934,20935,20936,20937,20938,20939,20940,20941,
8171320942,20943,20944,20945,20946,20947,20948,20949,20950,20951,20952,20953,
8171420954,20955,20956,20957,20958,20959,20960,20961,20962,20963,20964,20965,
8171520966,20967,20968,20969,20970,20971,20972,20973,20974,20975,20976,20977,
8171620978,20979,20980,20981,20982,20983,20984,20985,20986,20987,20988,20989,
8171720990,20991,20992,20993,20994,20995,20996,20997,20998,20999,21000,21001,
8171821002,21003,21004,21005,21006,21007,21008,21009,21010,21011,21012,21013,
8171921014,21015,21016,21017,21018,21019,21020,21021,21022,21023,21024,21025,
8172021026,21027,21028,21029,21030,21031,21032,21033,21034,21035,21036,21037,
8172121038,21039,21040,21041,21042,21043,21044,21045,21046,21047,21048,21049,
8172221050,21051,21052,21053,21054,21055,21056,21057,21058,21059,21060,21061,
8172321062,21063,21064,21065,21066,21067,21068,21069,21070,21071,21072,21073,
8172421074,21075,21076,21077,21078,21079,21080,21081,21082,21083,21084,21085,
8172521086,21087,21088,21089,21090,21091,21092,21093,21094,21095,21096,21097,
8172621098,21099,21100,21101,21102,21103,21104,21105,21106,21107,21108,21109,
8172721110,21111,21112,21113,21114,21115,21116,21117,21118,21119,21120,21121,
8172821122,21123,21124,21125,21126,21127,21128,21129,21130,21131,21132,21133,
8172921134,21135,21136,21137,21138,21139,21140,21141,21142,21143,21144,21145,
8173021146,21147,21148,21149,21150,21151,21152,21153,21154,21155,21156,21157,
8173121158,21159,21160,21161,21162,21163,21164,21165,21166,21167,21168,21169,
8173221170,21171,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,
8173321182,21183,21184,21185,21186,21187,21188,21189,21190,21191,21192,21193,
8173421194,21195,21196,21197,21198,21199,21200,21201,21202,21203,21204,21205,
8173521206,21207,21208,21209,21210,21211,21212,21213,21214,21215,21216,21217,
8173621218,21219,21220,21221,21222,21223,21224,21225,21226,21227,21228,21229,
8173721230,21231,21232,21233,21234,21235,21236,21237,21238,21239,21240,21241,
8173821242,21243,21244,21245,21246,21247,21248,21249,21250,21251,21252,21253,
8173921254,21255,21256,21257,21258,21259,21260,21261,21262,21263,21264,21265,
8174021266,21267,21268,21269,21270,21271,21272,21273,21274,21275,21276,21277,
8174121278,21279,21280,21281,21282,21283,21284,21285,21286,21287,21288,21289,
8174221290,21291,21292,21293,21294,21295,21296,21297,21298,21299,21300,21301,
8174321302,21303,21304,21305,21306,21307,21308,21309,21310,21311,21312,21313,
8174421314,21315,21316,21317,21318,21319,21320,21321,21322,21323,21324,21325,
8174521326,21327,21328,21329,21330,21331,21332,21333,21334,21335,21336,21337,
8174621338,21339,21340,21341,21342,21343,21344,21345,21346,21347,21348,21349,
8174721350,21351,21352,21353,21354,21355,21356,21357,21358,21359,21360,21361,
8174821362,21363,21364,21365,21366,21367,21368,21369,21370,21371,21372,21373,
8174921374,21375,21376,21377,21378,21379,21380,21381,21382,21383,21384,21385,
8175021386,21387,21388,21389,21390,21391,21392,21393,21394,21395,21396,21397,
8175121398,21399,21400,21401,21402,21403,21404,21405,21406,21407,21408,21409,
8175221410,21411,21412,21413,21414,21415,21416,21417,21418,21419,21420,21421,
8175321422,21423,21424,21425,21426,21427,21428,21429,21430,21431,21432,21433,
8175421434,21435,21436,21437,21438,21439,21440,21441,21442,21443,21444,21445,
8175521446,21447,21448,21449,21450,21451,21452,21453,21454,21455,21456,21457,
8175621458,21459,21460,21461,21462,21463,21464,21465,21466,21467,21468,21469,
8175721470,21471,21472,21473,21474,21475,21476,21477,21478,21479,21480,21481,
8175821482,21483,21484,21485,21486,21487,21488,21489,21490,21491,21492,21493,
8175921494,21495,21496,21497,21498,21499,21500,21501,21502,21503,21504,21505,
8176021506,21507,21508,21509,21510,21511,21512,21513,21514,21515,21516,21517,
8176121518,21519,21520,21521,21522,21523,21524,21525,21526,21527,21528,21529,
8176221530,21531,21532,21533,21534,21535,21536,21537,21538,21539,21540,21541,
8176321542,21543,21544,21545,21546,21547,21548,21549,21550,21551,21552,21553,
8176421554,21555,21556,21557,21558,21559,21560,21561,21562,21563,21564,21565,
8176521566,21567,21568,21569,21570,21571,21572,21573,21574,21575,21576,21577,
8176621578,21579,21580,21581,21582,21583,21584,21585,21586,21587,21588,21589,
8176721590,21591,21592,21593,21594,21595,21596,21597,21598,21599,21600,21601,
8176821602,21603,21604,21605,21606,21607,21608,21609,21610,21611,21612,21613,
8176921614,21615,21616,21617,21618,21619,21620,21621,21622,21623,21624,21625,
8177021626,21627,21628,21629,21630,21631,21632,21633,21634,21635,21636,21637,
8177121638,21639,21640,21641,21642,21643,21644,21645,21646,21647,21648,21649,
8177221650,21651,21652,21653,21654,21655,21656,21657,21658,21659,21660,21661,
8177321662,21663,21664,21665,21666,21667,21668,21669,21670,21671,21672,21673,
8177421674,21675,21676,21677,21678,21679,21680,21681,21682,21683,21684,21685,
8177521686,21687,21688,21689,21690,21691,21692,21693,21694,21695,21696,21697,
8177621698,21699,21700,21701,21702,21703,21704,21705,21706,21707,21708,21709,
8177721710,21711,21712,21713,21714,21715,21716,21717,21718,21719,21720,21721,
8177821722,21723,21724,21725,21726,21727,21728,21729,21730,21731,21732,21733,
8177921734,21735,21736,21737,21738,21739,21740,21741,21742,21743,21744,21745,
8178021746,21747,21748,21749,21750,21751,21752,21753,21754,21755,21756,21757,
8178121758,21759,21760,21761,21762,21763,21764,21765,21766,21767,21768,21769,
8178221770,21771,21772,21773,21774,21775,21776,21777,21778,21779,21780,21781,
8178321782,21783,21784,21785,21786,21787,21788,21789,21790,21791,21792,21793,
8178421794,21795,21796,21797,21798,21799,21800,21801,21802,21803,21804,21805,
8178521806,21807,21808,21809,21810,21811,21812,21813,21814,21815,21816,21817,
8178621818,21819,21820,21821,21822,21823,21824,21825,21826,21827,21828,21829,
8178721830,21831,21832,21833,21834,21835,21836,21837,21838,21839,21840,21841,
8178821842,21843,21844,21845,21846,21847,21848,21849,21850,21851,21852,21853,
8178921854,21855,21856,21857,21858,21859,21860,21861,21862,21863,21864,21865,
8179021866,21867,21868,21869,21870,21871,21872,21873,21874,21875,21876,21877,
8179121878,21879,21880,21881,21882,21883,21884,21885,21886,21887,21888,21889,
8179221890,21891,21892,21893,21894,21895,21896,21897,21898,21899,21900,21901,
8179321902,21903,21904,21905,21906,21907,21908,21909,21910,21911,21912,21913,
8179421914,21915,21916,21917,21918,21919,21920,21921,21922,21923,21924,21925,
8179521926,21927,21928,21929,21930,21931,21932,21933,21934,21935,21936,21937,
8179621938,21939,21940,21941,21942,21943,21944,21945,21946,21947,21948,21949,
8179721950,21951,21952,21953,21954,21955,21956,21957,21958,21959,21960,21961,
8179821962,21963,21964,21965,21966,21967,21968,21969,21970,21971,21972,21973,
8179921974,21975,21976,21977,21978,21979,21980,21981,21982,21983,21984,21985,
8180021986,21987,21988,21989,21990,21991,21992,21993,21994,21995,21996,21997,
8180121998,21999,22000,22001,22002,22003,22004,22005,22006,22007,22008,22009,
8180222010,22011,22012,22013,22014,22015,22016,22017,22018,22019,22020,22021,
8180322022,22023,22024,22025,22026,22027,22028,22029,22030,22031,22032,22033,
8180422034,22035,22036,22037,22038,22039,22040,22041,22042,22043,22044,22045,
8180522046,22047,22048,22049,22050,22051,22052,22053,22054,22055,22056,22057,
8180622058,22059,22060,22061,22062,22063,22064,22065,22066,22067,22068,22069,
8180722070,22071,22072,22073,22074,22075,22076,22077,22078,22079,22080,22081,
8180822082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22092,22093,
8180922094,22095,22096,22097,22098,22099,22100,22101,22102,22103,22104,22105,
8181022106,22107,22108,22109,22110,22111,22112,22113,22114,22115,22116,22117,
8181122118,22119,22120,22121,22122,22123,22124,22125,22126,22127,22128,22129,
8181222130,22131,22132,22133,22134,22135,22136,22137,22138,22139,22140,22141,
8181322142,22143,22144,22145,22146,22147,22148,22149,22150,22151,22152,22153,
8181422154,22155,22156,22157,22158,22159,22160,22161,22162,22163,22164,22165,
8181522166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,
8181622178,22179,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,
8181722190,22191,22192,22193,22194,22195,22196,22197,22198,22199,22200,22201,
8181822202,22203,22204,22205,22206,22207,22208,22209,22210,22211,22212,22213,
8181922214,22215,22216,22217,22218,22219,22220,22221,22222,22223,22224,22225,
8182022226,22227,22228,22229,22230,22231,22232,22233,22234,22235,22236,22237,
8182122238,22239,22240,22241,22242,22243,22244,22245,22246,22247,22248,22249,
8182222250,22251,22252,22253,22254,22255,22256,22257,22258,22259,22260,22261,
8182322262,22263,22264,22265,22266,22267,22268,22269,22270,22271,22272,22273,
8182422274,22275,22276,22277,22278,22279,22280,22281,22282,22283,22284,22285,
8182522286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,
8182622298,22299,22300,22301,22302,22303,22304,22305,22306,22307,22308,22309,
8182722310,22311,22312,22313,22314,22315,22316,22317,22318,22319,22320,22321,
8182822322,22323,22324,22325,22326,22327,22328,22329,22330,22331,22332,22333,
8182922334,22335,22336,22337,22338,22339,22340,22341,22342,22343,22344,22345,
8183022346,22347,22348,22349,22350,22351,22352,22353,22354,22355,22356,22357,
8183122358,22359,22360,22361,22362,22363,22364,22365,22366,22367,22368,22369,
8183222370,22371,22372,22373,22374,22375,22376,22377,22378,22379,22380,22381,
8183322382,22383,22384,22385,22386,22387,22388,22389,22390,22391,22392,22393,
8183422394,22395,22396,22397,22398,22399,22400,22401,22402,22403,22404,22405,
8183522406,22407,22408,22409,22410,22411,22412,22413,22414,22415,22416,22417,
8183622418,22419,22420,22421,22422,22423,22424,22425,22426,22427,22428,22429,
8183722430,22431,22432,22433,22434,22435,22436,22437,22438,22439,22440,22441,
8183822442,22443,22444,22445,22446,22447,22448,22449,22450,22451,22452,22453,
8183922454,22455,22456,22457,22458,22459,22460,22461,22462,22463,22464,22465,
8184022466,22467,22468,22469,22470,22471,22472,22473,22474,22475,22476,22477,
8184122478,22479,22480,22481,22482,22483,22484,22485,22486,22487,22488,22489,
8184222490,22491,22492,22493,22494,22495,22496,22497,22498,22499,22500,22501,
8184322502,22503,22504,22505,22506,22507,22508,22509,22510,22511,22512,22513,
8184422514,22515,22516,22517,22518,22519,22520,22521,22522,22523,22524,22525,
8184522526,22527,22528,22529,22530,22531,22532,22533,22534,22535,22536,22537,
8184622538,22539,22540,22541,22542,22543,22544,22545,22546,22547,22548,22549,
8184722550,22551,22552,22553,22554,22555,22556,22557,22558,22559,22560,22561,
8184822562,22563,22564,22565,22566,22567,22568,22569,22570,22571,22572,22573,
8184922574,22575,22576,22577,22578,22579,22580,22581,22582,22583,22584,22585,
8185022586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22596,22597,
8185122598,22599,22600,22601,22602,22603,22604,22605,22606,22607,22608,22609,
8185222610,22611,22612,22613,22614,22615,22616,22617,22618,22619,22620,22621,
8185322622,22623,22624,22625,22626,22627,22628,22629,22630,22631,22632,22633,
8185422634,22635,22636,22637,22638,22639,22640,22641,22642,22643,22644,22645,
8185522646,22647,22648,22649,22650,22651,22652,22653,22654,22655,22656,22657,
8185622658,22659,22660,22661,22662,22663,22664,22665,22666,22667,22668,22669,
8185722670,22671,22672,22673,22674,22675,22676,22677,22678,22679,22680,22681,
8185822682,22683,22684,22685,22686,22687,22688,22689,22690,22691,22692,22693,
8185922694,22695,22696,22697,22698,22699,22700,22701,22702,22703,22704,22705,
8186022706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22716,22717,
8186122718,22719,22720,22721,22722,22723,22724,22725,22726,22727,22728,22729,
8186222730,22731,22732,22733,22734,22735,22736,22737,22738,22739,22740,22741,
8186322742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,
8186422754,22755,22756,22757,22758,22759,22760,22761,22762,22763,22764,22765,
8186522766,22767,22768,22769,22770,22771,22772,22773,22774,22775,22776,22777,
8186622778,22779,22780,22781,22782,22783,22784,22785,22786,22787,22788,22789,
8186722790,22791,22792,22793,22794,22795,22796,22797,22798,22799,22800,22801,
8186822802,22803,22804,22805,22806,22807,22808,22809,22810,22811,22812,22813,
8186922814,22815,22816,22817,22818,22819,22820,22821,22822,22823,22824,22825,
8187022826,22827,22828,22829,22830,22831,22832,22833,22834,22835,22836,22837,
8187122838,22839,22840,22841,22842,22843,22844,22845,22846,22847,22848,22849,
8187222850,22851,22852,22853,22854,22855,22856,22857,22858,22859,22860,22861,
8187322862,22863,22864,22865,22866,22867,22868,22869,22870,22871,22872,22873,
8187422874,22875,22876,22877,22878,22879,22880,22881,22882,22883,22884,22885,
8187522886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,
8187622898,22899,22900,22901,22902,22903,22904,22905,22906,22907,22908,22909,
8187722910,22911,22912,22913,22914,22915,22916,22917,22918,22919,22920,22921,
8187822922,22923,22924,22925,22926,22927,22928,22929,22930,22931,22932,22933,
8187922934,22935,22936,22937,22938,22939,22940,22941,22942,22943,22944,22945,
8188022946,22947,22948,22949,22950,22951,22952,22953,22954,22955,22956,22957,
8188122958,22959,22960,22961,22962,22963,22964,22965,22966,22967,22968,22969,
8188222970,22971,22972,22973,22974,22975,22976,22977,22978,22979,22980,22981,
8188322982,22983,22984,22985,22986,22987,22988,22989,22990,22991,22992,22993,
8188422994,22995,22996,22997,22998,22999,23000,23001,23002,23003,23004,23005,
8188523006,23007,23008,23009,23010,23011,23012,23013,23014,23015,23016,23017,
8188623018,23019,23020,23021,23022,23023,23024,23025,23026,23027,23028,23029,
8188723030,23031,23032,23033,23034,23035,23036,23037,23038,23039,23040,23041,
8188823042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,
8188923054,23055,23056,23057,23058,23059,23060,23061,23062,23063,23064,23065,
8189023066,23067,23068,23069,23070,23071,23072,23073,23074,23075,23076,23077,
8189123078,23079,23080,23081,23082,23083,23084,23085,23086,23087,23088,23089,
8189223090,23091,23092,23093,23094,23095,23096,23097,23098,23099,23100,23101,
8189323102,23103,23104,23105,23106,23107,23108,23109,23110,23111,23112,23113,
8189423114,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23125,
8189523126,23127,23128,23129,23130,23131,23132,23133,23134,23135,23136,23137,
8189623138,23139,23140,23141,23142,23143,23144,23145,23146,23147,23148,23149,
8189723150,23151,23152,23153,23154,23155,23156,23157,23158,23159,23160,23161,
8189823162,23163,23164,23165,23166,23167,23168,23169,23170,23171,23172,23173,
8189923174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,
8190023186,23187,23188,23189,23190,23191,23192,23193,23194,23195,23196,23197,
8190123198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,
8190223210,23211,23212,23213,23214,23215,23216,23217,23218,23219,23220,23221,
8190323222,23223,23224,23225,23226,23227,23228,23229,23230,23231,23232,23233,
8190423234,23235,23236,23237,23238,23239,23240,23241,23242,23243,23244,23245,
8190523246,23247,23248,23249,23250,23251,23252,23253,23254,23255,23256,23257,
8190623258,23259,23260,23261,23262,23263,23264,23265,23266,23267,23268,23269,
8190723270,23271,23272,23273,23274,23275,23276,23277,23278,23279,23280,23281,
8190823282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,
8190923294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23305,
8191023306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,
8191123318,23319,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,
8191223330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,
8191323342,23343,23344,23345,23346,23347,23348,23349,23350,23351,23352,23353,
8191423354,23355,23356,23357,23358,23359,23360,23361,23362,23363,23364,23365,
8191523366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23376,23377,
8191623378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23389,
8191723390,23391,23392,23393,23394,23395,23396,23397,23398,23399,23400,23401,
8191823402,23403,23404,23405,23406,23407,23408,23409,23410,23411,23412,23413,
8191923414,23415,23416,23417,23418,23419,23420,23421,23422,23423,23424,23425,
8192023426,23427,23428,23429,23430,23431,23432,23433,23434,23435,23436,23437,
8192123438,23439,23440,23441,23442,23443,23444,23445,23446,23447,23448,23449,
8192223450,23451,23452,23453,23454,23455,23456,23457,23458,23459,23460,23461,
8192323462,23463,23464,23465,23466,23467,23468,23469,23470,23471,23472,23473,
8192423474,23475,23476,23477,23478,23479,23480,23481,23482,23483,23484,23485,
8192523486,23487,23488,23489,23490,23491,23492,23493,23494,23495,23496,23497,
8192623498,23499,23500,23501,23502,23503,23504,23505,23506,23507,23508,23509,
8192723510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,
8192823522,23523,23524,23525,23526,23527,23528,23529,23530,23531,23532,23533,
8192923534,23535,23536,23537,23538,23539,23540,23541,23542,23543,23544,23545,
8193023546,23547,23548,23549,23550,23551,23552,23553,23554,23555,23556,23557,
8193123558,23559,23560,23561,23562,23563,23564,23565,23566,23567,23568,23569,
8193223570,23571,23572,23573,23574,23575,23576,23577,23578,23579,23580,23581,
8193323582,23583,23584,23585,23586,23587,23588,23589,23590,23591,23592,23593,
8193423594,23595,23596,23597,23598,23599,23600,23601,23602,23603,23604,23605,
8193523606,23607,23608,23609,23610,23611,23612,23613,23614,23615,23616,23617,
8193623618,23619,23620,23621,23622,23623,23624,23625,23626,23627,23628,23629,
8193723630,23631,23632,23633,23634,23635,23636,23637,23638,23639,23640,23641,
8193823642,23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,
8193923654,23655,23656,23657,23658,23659,23660,23661,23662,23663,23664,23665,
8194023666,23667,23668,23669,23670,23671,23672,23673,23674,23675,23676,23677,
8194123678,23679,23680,23681,23682,23683,23684,23685,23686,23687,23688,23689,
8194223690,23691,23692,23693,23694,23695,23696,23697,23698,23699,23700,23701,
8194323702,23703,23704,23705,23706,23707,23708,23709,23710,23711,23712,23713,
8194423714,23715,23716,23717,23718,23719,23720,23721,23722,23723,23724,23725,
8194523726,23727,23728,23729,23730,23731,23732,23733,23734,23735,23736,23737,
8194623738,23739,23740,23741,23742,23743,23744,23745,23746,23747,23748,23749,
8194723750,23751,23752,23753,23754,23755,23756,23757,23758,23759,23760,23761,
8194823762,23763,23764,23765,23766,23767,23768,23769,23770,23771,23772,23773,
8194923774,23775,23776,23777,23778,23779,23780,23781,23782,23783,23784,23785,
8195023786,23787,23788,23789,23790,23791,23792,23793,23794,23795,23796,23797,
8195123798,23799,23800,23801,23802,23803,23804,23805,23806,23807,23808,23809,
8195223810,23811,23812,23813,23814,23815,23816,23817,23818,23819,23820,23821,
8195323822,23823,23824,23825,23826,23827,23828,23829,23830,23831,23832,23833,
8195423834,23835,23836,23837,23838,23839,23840,23841,23842,23843,23844,23845,
8195523846,23847,23848,23849,23850,23851,23852,23853,23854,23855,23856,23857,
8195623858,23859,23860,23861,23862,23863,23864,23865,23866,23867,23868,23869,
8195723870,23871,23872,23873,23874,23875,23876,23877,23878,23879,23880,23881,
8195823882,23883,23884,23885,23886,23887,23888,23889,23890,23891,23892,23893,
8195923894,23895,23896,23897,23898,23899,23900,23901,23902,23903,23904,23905,
8196023906,23907,23908,23909,23910,23911,23912,23913,23914,23915,23916,23917,
8196123918,23919,23920,23921,23922,23923,23924,23925,23926,23927,23928,23929,
8196223930,23931,23932,23933,23934,23935,23936,23937,23938,23939,23940,23941,
8196323942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,
8196423954,23955,23956,23957,23958,23959,23960,23961,23962,23963,23964,23965,
8196523966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,
8196623978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,
8196723990,23991,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,
8196824002,24003,24004,24005,24006,24007,24008,24009,24010,24011,24012,24013,
8196924014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,
8197024026,24027,24028,24029,24030,24031,24032,24033,24034,24035,24036,24037,
8197124038,24039,24040,24041,24042,24043,24044,24045,24046,24047,24048,24049,
8197224050,24051,24052,24053,24054,24055,24056,24057,24058,24059,24060,24061,
8197324062,24063,24064,24065,24066,24067,24068,24069,24070,24071,24072,24073,
8197424074,24075,24076,24077,24078,24079,24080,24081,24082,24083,24084,24085,
8197524086,24087,24088,24089,24090,24091,24092,24093,24094,24095,24096,24097,
8197624098,24099,24100,24101,24102,24103,24104,24105,24106,24107,24108,24109,
8197724110,24111,24112,24113,24114,24115,24116,24117,24118,24119,24120,24121,
8197824122,24123,24124,24125,24126,24127,24128,24129,24130,24131,24132,24133,
8197924134,24135,24136,24137,24138,24139,24140,24141,24142,24143,24144,24145,
8198024146,24147,24148,24149,24150,24151,24152,24153,24154,24155,24156,24157,
8198124158,24159,24160,24161,24162,24163,24164,24165,24166,24167,24168,24169,
8198224170,24171,24172,24173,24174,24175,24176,24177,24178,24179,24180,24181,
8198324182,24183,24184,24185,24186,24187,24188,24189,24190,24191,24192,24193,
8198424194,24195,24196,24197,24198,24199,24200,24201,24202,24203,24204,24205,
8198524206,24207,24208,24209,24210,24211,24212,24213,24214,24215,24216,24217,
8198624218,24219,24220,24221,24222,24223,24224,24225,24226,24227,24228,24229,
8198724230,24231,24232,24233,24234,24235,24236,24237,24238,24239,24240,24241,
8198824242,24243,24244,24245,24246,24247,24248,24249,24250,24251,24252,24253,
8198924254,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24265,
8199024266,24267,24268,24269,24270,24271,24272,24273,24274,24275,24276,24277,
8199124278,24279,24280,24281,24282,24283,24284,24285,24286,24287,24288,24289,
8199224290,24291,24292,24293,24294,24295,24296,24297,24298,24299,24300,24301,
8199324302,24303,24304,24305,24306,24307,24308,24309,24310,24311,24312,24313,
8199424314,24315,24316,24317,24318,24319,24320,24321,24322,24323,24324,24325,
8199524326,24327,24328,24329,24330,24331,24332,24333,24334,24335,24336,24337,
8199624338,24339,24340,24341,24342,24343,24344,24345,24346,24347,24348,24349,
8199724350,24351,24352,24353,24354,24355,24356,24357,24358,24359,24360,24361,
8199824362,24363,24364,24365,24366,24367,24368,24369,24370,24371,24372,24373,
8199924374,24375,24376,24377,24378,24379,24380,24381,24382,24383,24384,24385,
8200024386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,
8200124398,24399,24400,24401,24402,24403,24404,24405,24406,24407,24408,24409,
8200224410,24411,24412,24413,24414,24415,24416,24417,24418,24419,24420,24421,
8200324422,24423,24424,24425,24426,24427,24428,24429,24430,24431,24432,24433,
8200424434,24435,24436,24437,24438,24439,24440,24441,24442,24443,24444,24445,
8200524446,24447,24448,24449,24450,24451,24452,24453,24454,24455,24456,24457,
8200624458,24459,24460,24461,24462,24463,24464,24465,24466,24467,24468,24469,
8200724470,24471,24472,24473,24474,24475,24476,24477,24478,24479,24480,24481,
8200824482,24483,24484,24485,24486,24487,24488,24489,24490,24491,24492,24493,
8200924494,24495,24496,24497,24498,24499,24500,24501,24502,24503,24504,24505,
8201024506,24507,24508,24509,24510,24511,24512,24513,24514,24515,24516,24517,
8201124518,24519,24520,24521,24522,24523,24524,24525,24526,24527,24528,24529,
8201224530,24531,24532,24533,24534,24535,24536,24537,24538,24539,24540,24541,
8201324542,24543,24544,24545,24546,24547,24548,24549,24550,24551,24552,24553,
8201424554,24555,24556,24557,24558,24559,24560,24561,24562,24563,24564,24565,
8201524566,24567,24568,24569,24570,24571,24572,24573,24574,24575,24576,24577,
8201624578,24579,24580,24581,24582,24583,24584,24585,24586,24587,24588,24589,
8201724590,24591,24592,24593,24594,24595,24596,24597,24598,24599,24600,24601,
8201824602,24603,24604,24605,24606,24607,24608,24609,24610,24611,24612,24613,
8201924614,24615,24616,24617,24618,24619,24620,24621,24622,24623,24624,24625,
8202024626,24627,24628,24629,24630,24631,24632,24633,24634,24635,24636,24637,
8202124638,24639,24640,24641,24642,24643,24644,24645,24646,24647,24648,24649,
8202224650,24651,24652,24653,24654,24655,24656,24657,24658,24659,24660,24661,
8202324662,24663,24664,24665,24666,24667,24668,24669,24670,24671,24672,24673,
8202424674,24675,24676,24677,24678,24679,24680,24681,24682,24683,24684,24685,
8202524686,24687,24688,24689,24690,24691,24692,24693,24694,24695,24696,24697,
8202624698,24699,24700,24701,24702,24703,24704,24705,24706,24707,24708,24709,
8202724710,24711,24712,24713,24714,24715,24716,24717,24718,24719,24720,24721,
8202824722,24723,24724,24725,24726,24727,24728,24729,24730,24731,24732,24733,
8202924734,24735,24736,24737,24738,24739,24740,24741,24742,24743,24744,24745,
8203024746,24747,24748,24749,24750,24751,24752,24753,24754,24755,24756,24757,
8203124758,24759,24760,24761,24762,24763,24764,24765,24766,24767,24768,24769,
8203224770,24771,24772,24773,24774,24775,24776,24777,24778,24779,24780,24781,
8203324782,24783,24784,24785,24786,24787,24788,24789,24790,24791,24792,24793,
8203424794,24795,24796,24797,24798,24799,24800,24801,24802,24803,24804,24805,
8203524806,24807,24808,24809,24810,24811,24812,24813,24814,24815,24816,24817,
8203624818,24819,24820,24821,24822,24823,24824,24825,24826,24827,24828,24829,
8203724830,24831,24832,24833,24834,24835,24836,24837,24838,24839,24840,24841,
8203824842,24843,24844,24845,24846,24847,24848,24849,24850,24851,24852,24853,
8203924854,24855,24856,24857,24858,24859,24860,24861,24862,24863,24864,24865,
8204024866,24867,24868,24869,24870,24871,24872,24873,24874,24875,24876,24877,
8204124878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,
8204224890,24891,24892,24893,24894,24895,24896,24897,24898,24899,24900,24901,
8204324902,24903,24904,24905,24906,24907,24908,24909,24910,24911,24912,24913,
8204424914,24915,24916,24917,24918,24919,24920,24921,24922,24923,24924,24925,
8204524926,24927,24928,24929,24930,24931,24932,24933,24934,24935,24936,24937,
8204624938,24939,24940,24941,24942,24943,24944,24945,24946,24947,24948,24949,
8204724950,24951,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,
8204824962,24963,24964,24965,24966,24967,24968,24969,24970,24971,24972,24973,
8204924974,24975,24976,24977,24978,24979,24980,24981,24982,24983,24984,24985,
8205024986,24987,24988,24989,24990,24991,24992,24993,24994,24995,24996,24997,
8205124998,24999,25000,25001,25002,25003,25004,25005,25006,25007,25008,25009,
8205225010,25011,25012,25013,25014,25015,25016,25017,25018,25019,25020,25021,
8205325022,25023,25024,25025,25026,25027,25028,25029,25030,25031,25032,25033,
8205425034,25035,25036,25037,25038,25039,25040,25041,25042,25043,25044,25045,
8205525046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,
8205625058,25059,25060,25061,25062,25063,25064,25065,25066,25067,25068,25069,
8205725070,25071,25072,25073,25074,25075,25076,25077,25078,25079,25080,25081,
8205825082,25083,25084,25085,25086,25087,25088,25089,25090,25091,25092,25093,
8205925094,25095,25096,25097,25098,25099,25100,25101,25102,25103,25104,25105,
8206025106,25107,25108,25109,25110,25111,25112,25113,25114,25115,25116,25117,
8206125118,25119,25120,25121,25122,25123,25124,25125,25126,25127,25128,25129,
8206225130,25131,25132,25133,25134,25135,25136,25137,25138,25139,25140,25141,
8206325142,25143,25144,25145,25146,25147,25148,25149,25150,25151,25152,25153,
8206425154,25155,25156,25157,25158,25159,25160,25161,25162,25163,25164,25165,
8206525166,25167,25168,25169,25170,25171,25172,25173,25174,25175,25176,25177,
8206625178,25179,25180,25181,25182,25183,25184,25185,25186,25187,25188,25189,
8206725190,25191,25192,25193,25194,25195,25196,25197,25198,25199,25200,25201,
8206825202,25203,25204,25205,25206,25207,25208,25209,25210,25211,25212,25213,
8206925214,25215,25216,25217,25218,25219,25220,25221,25222,25223,25224,25225,
8207025226,25227,25228,25229,25230,25231,25232,25233,25234,25235,25236,25237,
8207125238,25239,25240,25241,25242,25243,25244,25245,25246,25247,25248,25249,
8207225250,25251,25252,25253,25254,25255,25256,25257,25258,25259,25260,25261,
8207325262,25263,25264,25265,25266,25267,25268,25269,25270,25271,25272,25273,
8207425274,25275,25276,25277,25278,25279,25280,25281,25282,25283,25284,25285,
8207525286,25287,25288,25289,25290,25291,25292,25293,25294,25295,25296,25297,
8207625298,25299,25300,25301,25302,25303,25304,25305,25306,25307,25308,25309,
8207725310,25311,25312,25313,25314,25315,25316,25317,25318,25319,25320,25321,
8207825322,25323,25324,25325,25326,25327,25328,25329,25330,25331,25332,25333,
8207925334,25335,25336,25337,25338,25339,25340,25341,25342,25343,25344,25345,
8208025346,25347,25348,25349,25350,25351,25352,25353,25354,25355,25356,25357,
8208125358,25359,25360,25361,25362,25363,25364,25365,25366,25367,25368,25369,
8208225370,25371,25372,25373,25374,25375,25376,25377,25378,25379,25380,25381,
8208325382,25383,25384,25385,25386,25387,25388,25389,25390,25391,25392,25393,
8208425394,25395,25396,25397,25398,25399,25400,25401,25402,25403,25404,25405,
8208525406,25407,25408,25409,25410,25411,25412,25413,25414,25415,25416,25417,
8208625418,25419,25420,25421,25422,25423,25424,25425,25426,25427,25428,25429,
8208725430,25431,25432,25433,25434,25435,25436,25437,25438,25439,25440,25441,
8208825442,25443,25444,25445,25446,25447,25448,25449,25450,25451,25452,25453,
8208925454,25455,25456,25457,25458,25459,25460,25461,25462,25463,25464,25465,
8209025466,25467,25468,25469,25470,25471,25472,25473,25474,25475,25476,25477,
8209125478,25479,25480,25481,25482,25483,25484,25485,25486,25487,25488,25489,
8209225490,25491,25492,25493,25494,25495,25496,25497,25498,25499,25500,25501,
8209325502,25503,25504,25505,25506,25507,25508,25509,25510,25511,25512,25513,
8209425514,25515,25516,25517,25518,25519,25520,25521,25522,25523,25524,25525,
8209525526,25527,25528,25529,25530,25531,25532,25533,25534,25535,25536,25537,
8209625538,25539,25540,25541,25542,25543,25544,25545,25546,25547,25548,25549,
8209725550,25551,25552,25553,25554,25555,25556,25557,25558,25559,25560,25561,
8209825562,25563,25564,25565,25566,25567,25568,25569,25570,25571,25572,25573,
8209925574,25575,25576,25577,25578,25579,25580,25581,25582,25583,25584,25585,
8210025586,25587,25588,25589,25590,25591,25592,25593,25594,25595,25596,25597,
8210125598,25599,25600,25601,25602,25603,25604,25605,25606,25607,25608,25609,
8210225610,25611,25612,25613,25614,25615,25616,25617,25618,25619,25620,25621,
8210325622,25623,25624,25625,25626,25627,25628,25629,25630,25631,25632,25633,
8210425634,25635,25636,25637,25638,25639,25640,25641,25642,25643,25644,25645,
8210525646,25647,25648,25649,25650,25651,25652,25653,25654,25655,25656,25657,
8210625658,25659,25660,25661,25662,25663,25664,25665,25666,25667,25668,25669,
8210725670,25671,25672,25673,25674,25675,25676,25677,25678,25679,25680,25681,
8210825682,25683,25684,25685,25686,25687,25688,25689,25690,25691,25692,25693,
8210925694,25695,25696,25697,25698,25699,25700,25701,25702,25703,25704,25705,
8211025706,25707,25708,25709,25710,25711,25712,25713,25714,25715,25716,25717,
8211125718,25719,25720,25721,25722,25723,25724,25725,25726,25727,25728,25729,
8211225730,25731,25732,25733,25734,25735,25736,25737,25738,25739,25740,25741,
8211325742,25743,25744,25745,25746,25747,25748,25749,25750,25751,25752,25753,
8211425754,25755,25756,25757,25758,25759,25760,25761,25762,25763,25764,25765,
8211525766,25767,25768,25769,25770,25771,25772,25773,25774,25775,25776,25777,
8211625778,25779,25780,25781,25782,25783,25784,25785,25786,25787,25788,25789,
8211725790,25791,25792,25793,25794,25795,25796,25797,25798,25799,25800,25801,
8211825802,25803,25804,25805,25806,25807,25808,25809,25810,25811,25812,25813,
8211925814,25815,25816,25817,25818,25819,25820,25821,25822,25823,25824,25825,
8212025826,25827,25828,25829,25830,25831,25832,25833,25834,25835,25836,25837,
8212125838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,
8212225850,25851,25852,25853,25854,25855,25856,25857,25858,25859,25860,25861,
8212325862,25863,25864,25865,25866,25867,25868,25869,25870,25871,25872,25873,
8212425874,25875,25876,25877,25878,25879,25880,25881,25882,25883,25884,25885,
8212525886,25887,25888,25889,25890,25891,25892,25893,25894,25895,25896,25897,
8212625898,25899,25900,25901,25902,25903,25904,25905,25906,25907,25908,25909,
8212725910,25911,25912,25913,25914,25915,25916,25917,25918,25919,25920,25921,
8212825922,25923,25924,25925,25926,25927,25928,25929,25930,25931,25932,25933,
8212925934,25935,25936,25937,25938,25939,25940,25941,25942,25943,25944,25945,
8213025946,25947,25948,25949,25950,25951,25952,25953,25954,25955,25956,25957,
8213125958,25959,25960,25961,25962,25963,25964,25965,25966,25967,25968,25969,
8213225970,25971,25972,25973,25974,25975,25976,25977,25978,25979,25980,25981,
8213325982,25983,25984,25985,25986,25987,25988,25989,25990,25991,25992,25993,
8213425994,25995,25996,25997,25998,25999,26000,26001,26002,26003,26004,26005,
8213526006,26007,26008,26009,26010,26011,26012,26013,26014,26015,26016,26017,
8213626018,26019,26020,26021,26022,26023,26024,26025,26026,26027,26028,26029,
8213726030,26031,26032,26033,26034,26035,26036,26037,26038,26039,26040,26041,
8213826042,26043,26044,26045,26046,26047,26048,26049,26050,26051,26052,26053,
8213926054,26055,26056,26057,26058,26059,26060,26061,26062,26063,26064,26065,
8214026066,26067,26068,26069,26070,26071,26072,26073,26074,26075,26076,26077,
8214126078,26079,26080,26081,26082,26083,26084,26085,26086,26087,26088,26089,
8214226090,26091,26092,26093,26094,26095,26096,26097,26098,26099,26100,26101,
8214326102,26103,26104,26105,26106,26107,26108,26109,26110,26111,26112,26113,
8214426114,26115,26116,26117,26118,26119,26120,26121,26122,26123,26124,26125,
8214526126,26127,26128,26129,26130,26131,26132,26133,26134,26135,26136,26137,
8214626138,26139,26140,26141,26142,26143,26144,26145,26146,26147,26148,26149,
8214726150,26151,26152,26153,26154,26155,26156,26157,26158,26159,26160,26161,
8214826162,26163,26164,26165,26166,26167,26168,26169,26170,26171,26172,26173,
8214926174,26175,26176,26177,26178,26179,26180,26181,26182,26183,26184,26185,
8215026186,26187,26188,26189,26190,26191,26192,26193,26194,26195,26196,26197,
8215126198,26199,26200,26201,26202,26203,26204,26205,26206,26207,26208,26209,
8215226210,26211,26212,26213,26214,26215,26216,26217,26218,26219,26220,26221,
8215326222,26223,26224,26225,26226,26227,26228,26229,26230,26231,26232,26233,
8215426234,26235,26236,26237,26238,26239,26240,26241,26242,26243,26244,26245,
8215526246,26247,26248,26249,26250,26251,26252,26253,26254,26255,26256,26257,
8215626258,26259,26260,26261,26262,26263,26264,26265,26266,26267,26268,26269,
8215726270,26271,26272,26273,26274,26275,26276,26277,26278,26279,26280,26281,
8215826282,26283,26284,26285,26286,26287,26288,26289,26290,26291,26292,26293,
8215926294,26295,26296,26297,26298,26299,26300,26301,26302,26303,26304,26305,
8216026306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,
8216126318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26329,
8216226330,26331,26332,26333,26334,26335,26336,26337,26338,26339,26340,26341,
8216326342,26343,26344,26345,26346,26347,26348,26349,26350,26351,26352,26353,
8216426354,26355,26356,26357,26358,26359,26360,26361,26362,26363,26364,26365,
8216526366,26367,26368,26369,26370,26371,26372,26373,26374,26375,26376,26377,
8216626378,26379,26380,26381,26382,26383,26384,26385,26386,26387,26388,26389,
8216726390,26391,26392,26393,26394,26395,26396,26397,26398,26399,26400,26401,
8216826402,26403,26404,26405,26406,26407,26408,26409,26410,26411,26412,26413,
8216926414,26415,26416,26417,26418,26419,26420,26421,26422,26423,26424,26425,
8217026426,26427,26428,26429,26430,26431,26432,26433,26434,26435,26436,26437,
8217126438,26439,26440,26441,26442,26443,26444,26445,26446,26447,26448,26449,
8217226450,26451,26452,26453,26454,26455,26456,26457,26458,26459,26460,26461,
8217326462,26463,26464,26465,26466,26467,26468,26469,26470,26471,26472,26473,
8217426474,26475,26476,26477,26478,26479,26480,26481,26482,26483,26484,26485,
8217526486,26487,26488,26489,26490,26491,26492,26493,26494,26495,26496,26497,
8217626498,26499,26500,26501,26502,26503,26504,26505,26506,26507,26508,26509,
8217726510,26511,26512,26513,26514,26515,26516,26517,26518,26519,26520,26521,
8217826522,26523,26524,26525,26526,26527,26528,26529,26530,26531,26532,26533,
8217926534,26535,26536,26537,26538,26539,26540,26541,26542,26543,26544,26545,
8218026546,26547,26548,26549,26550,26551,26552,26553,26554,26555,26556,26557,
8218126558,26559,26560,26561,26562,26563,26564,26565,26566,26567,26568,26569,
8218226570,26571,26572,26573,26574,26575,26576,26577,26578,26579,26580,26581,
8218326582,26583,26584,26585,26586,26587,26588,26589,26590,26591,26592,26593,
8218426594,26595,26596,26597,26598,26599,26600,26601,26602,26603,26604,26605,
8218526606,26607,26608,26609,26610,26611,26612,26613,26614,26615,26616,26617,
8218626618,26619,26620,26621,26622,26623,26624,26625,26626,26627,26628,26629,
8218726630,26631,26632,26633,26634,26635,26636,26637,26638,26639,26640,26641,
8218826642,26643,26644,26645,26646,26647,26648,26649,26650,26651,26652,26653,
8218926654,26655,26656,26657,26658,26659,26660,26661,26662,26663,26664,26665,
8219026666,26667,26668,26669,26670,26671,26672,26673,26674,26675,26676,26677,
8219126678,26679,26680,26681,26682,26683,26684,26685,26686,26687,26688,26689,
8219226690,26691,26692,26693,26694,26695,26696,26697,26698,26699,26700,26701,
8219326702,26703,26704,26705,26706,26707,26708,26709,26710,26711,26712,26713,
8219426714,26715,26716,26717,26718,26719,26720,26721,26722,26723,26724,26725,
8219526726,26727,26728,26729,26730,26731,26732,26733,26734,26735,26736,26737,
8219626738,26739,26740,26741,26742,26743,26744,26745,26746,26747,26748,26749,
8219726750,26751,26752,26753,26754,26755,26756,26757,26758,26759,26760,26761,
8219826762,26763,26764,26765,26766,26767,26768,26769,26770,26771,26772,26773,
8219926774,26775,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,
8220026786,26787,26788,26789,26790,26791,26792,26793,26794,26795,26796,26797,
8220126798,26799,26800,26801,26802,26803,26804,26805,26806,26807,26808,26809,
8220226810,26811,26812,26813,26814,26815,26816,26817,26818,26819,26820,26821,
8220326822,26823,26824,26825,26826,26827,26828,26829,26830,26831,26832,26833,
8220426834,26835,26836,26837,26838,26839,26840,26841,26842,26843,26844,26845,
8220526846,26847,26848,26849,26850,26851,26852,26853,26854,26855,26856,26857,
8220626858,26859,26860,26861,26862,26863,26864,26865,26866,26867,26868,26869,
8220726870,26871,26872,26873,26874,26875,26876,26877,26878,26879,26880,26881,
8220826882,26883,26884,26885,26886,26887,26888,26889,26890,26891,26892,26893,
8220926894,26895,26896,26897,26898,26899,26900,26901,26902,26903,26904,26905,
8221026906,26907,26908,26909,26910,26911,26912,26913,26914,26915,26916,26917,
8221126918,26919,26920,26921,26922,26923,26924,26925,26926,26927,26928,26929,
8221226930,26931,26932,26933,26934,26935,26936,26937,26938,26939,26940,26941,
8221326942,26943,26944,26945,26946,26947,26948,26949,26950,26951,26952,26953,
8221426954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26964,26965,
8221526966,26967,26968,26969,26970,26971,26972,26973,26974,26975,26976,26977,
8221626978,26979,26980,26981,26982,26983,26984,26985,26986,26987,26988,26989,
8221726990,26991,26992,26993,26994,26995,26996,26997,26998,26999,27000,27001,
8221827002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,
8221927014,27015,27016,27017,27018,27019,27020,27021,27022,27023,27024,27025,
8222027026,27027,27028,27029,27030,27031,27032,27033,27034,27035,27036,27037,
8222127038,27039,27040,27041,27042,27043,27044,27045,27046,27047,27048,27049,
8222227050,27051,27052,27053,27054,27055,27056,27057,27058,27059,27060,27061,
8222327062,27063,27064,27065,27066,27067,27068,27069,27070,27071,27072,27073,
8222427074,27075,27076,27077,27078,27079,27080,27081,27082,27083,27084,27085,
8222527086,27087,27088,27089,27090,27091,27092,27093,27094,27095,27096,27097,
8222627098,27099,27100,27101,27102,27103,27104,27105,27106,27107,27108,27109,
8222727110,27111,27112,27113,27114,27115,27116,27117,27118,27119,27120,27121,
8222827122,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27133,
8222927134,27135,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,
8223027146,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,
8223127158,27159,27160,27161,27162,27163,27164,27165,27166,27167,27168,27169,
8223227170,27171,27172,27173,27174,27175,27176,27177,27178,27179,27180,27181,
8223327182,27183,27184,27185,27186,27187,27188,27189,27190,27191,27192,27193,
8223427194,27195,27196,27197,27198,27199,27200,27201,27202,27203,27204,27205,
8223527206,27207,27208,27209,27210,27211,27212,27213,27214,27215,27216,27217,
8223627218,27219,27220,27221,27222,27223,27224,27225,27226,27227,27228,27229,
8223727230,27231,27232,27233,27234,27235,27236,27237,27238,27239,27240,27241,
8223827242,27243,27244,27245,27246,27247,27248,27249,27250,27251,27252,27253,
8223927254,27255,27256,27257,27258,27259,27260,27261,27262,27263,27264,27265,
8224027266,27267,27268,27269,27270,27271,27272,27273,27274,27275,27276,27277,
8224127278,27279,27280,27281,27282,27283,27284,27285,27286,27287,27288,27289,
8224227290,27291,27292,27293,27294,27295,27296,27297,27298,27299,27300,27301,
8224327302,27303,27304,27305,27306,27307,27308,27309,27310,27311,27312,27313,
8224427314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,
8224527326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,
8224627338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,
8224727350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,
8224827362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,
8224927374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,
8225027386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,
8225127398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,
8225227410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,
8225327422,27423,27424,27425,27426,27427,27428,27429,27430,27431,27432,27433,
8225427434,27435,27436,27437,27438,27439,27440,27441,27442,27443,27444,27445,
8225527446,27447,27448,27449,27450,27451,27452,27453,27454,27455,27456,27457,
8225627458,27459,27460,27461,27462,27463,27464,27465,27466,27467,27468,27469,
8225727470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27481,
8225827482,27483,27484,27485,27486,27487,27488,27489,27490,27491,27492,27493,
8225927494,27495,27496,27497,27498,27499,27500,27501,27502,27503,27504,27505,
8226027506,27507,27508,27509,27510,27511,27512,27513,27514,27515,27516,27517,
8226127518,27519,27520,27521,27522,27523,27524,27525,27526,27527,27528,27529,
8226227530,27531,27532,27533,27534,27535,27536,27537,27538,27539,27540,27541,
8226327542,27543,27544,27545,27546,27547,27548,27549,27550,27551,27552,27553,
8226427554,27555,27556,27557,27558,27559,27560,27561,27562,27563,27564,27565,
8226527566,27567,27568,27569,27570,27571,27572,27573,27574,27575,27576,27577,
8226627578,27579,27580,27581,27582,27583,27584,27585,27586,27587,27588,27589,
8226727590,27591,27592,27593,27594,27595,27596,27597,27598,27599,27600,27601,
8226827602,27603,27604,27605,27606,27607,27608,27609,27610,27611,27612,27613,
8226927614,27615,27616,27617,27618,27619,27620,27621,27622,27623,27624,27625,
8227027626,27627,27628,27629,27630,27631,27632,27633,27634,27635,27636,27637,
8227127638,27639,27640,27641,27642,27643,27644,27645,27646,27647,27648,27649,
8227227650,27651,27652,27653,27654,27655,27656,27657,27658,27659,27660,27661,
8227327662,27663,27664,27665,27666,27667,27668,27669,27670,27671,27672,27673,
8227427674,27675,27676,27677,27678,27679,27680,27681,27682,27683,27684,27685,
8227527686,27687,27688,27689,27690,27691,27692,27693,27694,27695,27696,27697,
8227627698,27699,27700,27701,27702,27703,27704,27705,27706,27707,27708,27709,
8227727710,27711,27712,27713,27714,27715,27716,27717,27718,27719,27720,27721,
8227827722,27723,27724,27725,27726,27727,27728,27729,27730,27731,27732,27733,
8227927734,27735,27736,27737,27738,27739,27740,27741,27742,27743,27744,27745,
8228027746,27747,27748,27749,27750,27751,27752,27753,27754,27755,27756,27757,
8228127758,27759,27760,27761,27762,27763,27764,27765,27766,27767,27768,27769,
8228227770,27771,27772,27773,27774,27775,27776,27777,27778,27779,27780,27781,
8228327782,27783,27784,27785,27786,27787,27788,27789,27790,27791,27792,27793,
8228427794,27795,27796,27797,27798,27799,27800,27801,27802,27803,27804,27805,
8228527806,27807,27808,27809,27810,27811,27812,27813,27814,27815,27816,27817,
8228627818,27819,27820,27821,27822,27823,27824,27825,27826,27827,27828,27829,
8228727830,27831,27832,27833,27834,27835,27836,27837,27838,27839,27840,27841,
8228827842,27843,27844,27845,27846,27847,27848,27849,27850,27851,27852,27853,
8228927854,27855,27856,27857,27858,27859,27860,27861,27862,27863,27864,27865,
8229027866,27867,27868,27869,27870,27871,27872,27873,27874,27875,27876,27877,
8229127878,27879,27880,27881,27882,27883,27884,27885,27886,27887,27888,27889,
8229227890,27891,27892,27893,27894,27895,27896,27897,27898,27899,27900,27901,
8229327902,27903,27904,27905,27906,27907,27908,27909,27910,27911,27912,27913,
8229427914,27915,27916,27917,27918,27919,27920,27921,27922,27923,27924,27925,
8229527926,27927,27928,27929,27930,27931,27932,27933,27934,27935,27936,27937,
8229627938,27939,27940,27941,27942,27943,27944,27945,27946,27947,27948,27949,
8229727950,27951,27952,27953,27954,27955,27956,27957,27958,27959,27960,27961,
8229827962,27963,27964,27965,27966,27967,27968,27969,27970,27971,27972,27973,
8229927974,27975,27976,27977,27978,27979,27980,27981,27982,27983,27984,27985,
8230027986,27987,27988,27989,27990,27991,27992,27993,27994,27995,27996,27997,
8230127998,27999,28000,28001,28002,28003,28004,28005,28006,28007,28008,28009,
8230228010,28011,28012,28013,28014,28015,28016,28017,28018,28019,28020,28021,
8230328022,28023,28024,28025,28026,28027,28028,28029,28030,28031,28032,28033,
8230428034,28035,28036,28037,28038,28039,28040,28041,28042,28043,28044,28045,
8230528046,28047,28048,28049,28050,28051,28052,28053,28054,28055,28056,28057,
8230628058,28059,28060,28061,28062,28063,28064,28065,28066,28067,28068,28069,
8230728070,28071,28072,28073,28074,28075,28076,28077,28078,28079,28080,28081,
8230828082,28083,28084,28085,28086,28087,28088,28089,28090,28091,28092,28093,
8230928094,28095,28096,28097,28098,28099,28100,28101,28102,28103,28104,28105,
8231028106,28107,28108,28109,28110,28111,28112,28113,28114,28115,28116,28117,
8231128118,28119,28120,28121,28122,28123,28124,28125,28126,28127,28128,28129,
8231228130,28131,28132,28133,28134,28135,28136,28137,28138,28139,28140,28141,
8231328142,28143,28144,28145,28146,28147,28148,28149,28150,28151,28152,28153,
8231428154,28155,28156,28157,28158,28159,28160,28161,28162,28163,28164,28165,
8231528166,28167,28168,28169,28170,28171,28172,28173,28174,28175,28176,28177,
8231628178,28179,28180,28181,28182,28183,28184,28185,28186,28187,28188,28189,
8231728190,28191,28192,28193,28194,28195,28196,28197,28198,28199,28200,28201,
8231828202,28203,28204,28205,28206,28207,28208,28209,28210,28211,28212,28213,
8231928214,28215,28216,28217,28218,28219,28220,28221,28222,28223,28224,28225,
8232028226,28227,28228,28229,28230,28231,28232,28233,28234,28235,28236,28237,
8232128238,28239,28240,28241,28242,28243,28244,28245,28246,28247,28248,28249,
8232228250,28251,28252,28253,28254,28255,28256,28257,28258,28259,28260,28261,
8232328262,28263,28264,28265,28266,28267,28268,28269,28270,28271,28272,28273,
8232428274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,
8232528286,28287,28288,28289,28290,28291,28292,28293,28294,28295,28296,28297,
8232628298,28299,28300,28301,28302,28303,28304,28305,28306,28307,28308,28309,
8232728310,28311,28312,28313,28314,28315,28316,28317,28318,28319,28320,28321,
8232828322,28323,28324,28325,28326,28327,28328,28329,28330,28331,28332,28333,
8232928334,28335,28336,28337,28338,28339,28340,28341,28342,28343,28344,28345,
8233028346,28347,28348,28349,28350,28351,28352,28353,28354,28355,28356,28357,
8233128358,28359,28360,28361,28362,28363,28364,28365,28366,28367,28368,28369,
8233228370,28371,28372,28373,28374,28375,28376,28377,28378,28379,28380,28381,
8233328382,28383,28384,28385,28386,28387,28388,28389,28390,28391,28392,28393,
8233428394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28404,28405,
8233528406,28407,28408,28409,28410,28411,28412,28413,28414,28415,28416,28417,
8233628418,28419,28420,28421,28422,28423,28424,28425,28426,28427,28428,28429,
8233728430,28431,28432,28433,28434,28435,28436,28437,28438,28439,28440,28441,
8233828442,28443,28444,28445,28446,28447,28448,28449,28450,28451,28452,28453,
8233928454,28455,28456,28457,28458,28459,28460,28461,28462,28463,28464,28465,
8234028466,28467,28468,28469,28470,28471,28472,28473,28474,28475,28476,28477,
8234128478,28479,28480,28481,28482,28483,28484,28485,28486,28487,28488,28489,
8234228490,28491,28492,28493,28494,28495,28496,28497,28498,28499,28500,28501,
8234328502,28503,28504,28505,28506,28507,28508,28509,28510,28511,28512,28513,
8234428514,28515,28516,28517,28518,28519,28520,28521,28522,28523,28524,28525,
8234528526,28527,28528,28529,28530,28531,28532,28533,28534,28535,28536,28537,
8234628538,28539,28540,28541,28542,28543,28544,28545,28546,28547,28548,28549,
8234728550,28551,28552,28553,28554,28555,28556,28557,28558,28559,28560,28561,
8234828562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28572,28573,
8234928574,28575,28576,28577,28578,28579,28580,28581,28582,28583,28584,28585,
8235028586,28587,28588,28589,28590,28591,28592,28593,28594,28595,28596,28597,
8235128598,28599,28600,28601,28602,28603,28604,28605,28606,28607,28608,28609,
8235228610,28611,28612,28613,28614,28615,28616,28617,28618,28619,28620,28621,
8235328622,28623,28624,28625,28626,28627,28628,28629,28630,28631,28632,28633,
8235428634,28635,28636,28637,28638,28639,28640,28641,28642,28643,28644,28645,
8235528646,28647,28648,28649,28650,28651,28652,28653,28654,28655,28656,28657,
8235628658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,
8235728670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,
8235828682,28683,28684,28685,28686,28687,28688,28689,28690,28691,28692,28693,
8235928694,28695,28696,28697,28698,28699,28700,28701,28702,28703,28704,28705,
8236028706,28707,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,
8236128718,28719,28720,28721,28722,28723,28724,28725,28726,28727,28728,28729,
8236228730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,
8236328742,28743,28744,28745,28746,28747,28748,28749,28750,28751,28752,28753,
8236428754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,
8236528766,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,
8236628778,28779,28780,28781,28782,28783,28784,28785,28786,28787,28788,28789,
8236728790,28791,28792,28793,28794,28795,28796,28797,28798,28799,28800,28801,
8236828802,28803,28804,28805,28806,28807,28808,28809,28810,28811,28812,28813,
8236928814,28815,28816,28817,28818,28819,28820,28821,28822,28823,28824,28825,
8237028826,28827,28828,28829,28830,28831,28832,28833,28834,28835,28836,28837,
8237128838,28839,28840,28841,28842,28843,28844,28845,28846,28847,28848,28849,
8237228850,28851,28852,28853,28854,28855,28856,28857,28858,28859,28860,28861,
8237328862,28863,28864,28865,28866,28867,28868,28869,28870,28871,28872,28873,
8237428874,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,
8237528886,28887,28888,28889,28890,28891,28892,28893,28894,28895,28896,28897,
8237628898,28899,28900,28901,28902,28903,28904,28905,28906,28907,28908,28909,
8237728910,28911,28912,28913,28914,28915,28916,28917,28918,28919,28920,28921,
8237828922,28923,28924,28925,28926,28927,28928,28929,28930,28931,28932,28933,
8237928934,28935,28936,28937,28938,28939,28940,28941,28942,28943,28944,28945,
8238028946,28947,28948,28949,28950,28951,28952,28953,28954,28955,28956,28957,
8238128958,28959,28960,28961,28962,28963,28964,28965,28966,28967,28968,28969,
8238228970,28971,28972,28973,28974,28975,28976,28977,28978,28979,28980,28981,
8238328982,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,
8238428994,28995,28996,28997,28998,28999,29000,29001,29002,29003,29004,29005,
8238529006,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,
8238629018,29019,29020,29021,29022,29023,29024,29025,29026,29027,29028,29029,
8238729030,29031,29032,29033,29034,29035,29036,29037,29038,29039,29040,29041,
8238829042,29043,29044,29045,29046,29047,29048,29049,29050,29051,29052,29053,
8238929054,29055,29056,29057,29058,29059,29060,29061,29062,29063,29064,29065,
8239029066,29067,29068,29069,29070,29071,29072,29073,29074,29075,29076,29077,
8239129078,29079,29080,29081,29082,29083,29084,29085,29086,29087,29088,29089,
8239229090,29091,29092,29093,29094,29095,29096,29097,29098,29099,29100,29101,
8239329102,29103,29104,29105,29106,29107,29108,29109,29110,29111,29112,29113,
8239429114,29115,29116,29117,29118,29119,29120,29121,29122,29123,29124,29125,
8239529126,29127,29128,29129,29130,29131,29132,29133,29134,29135,29136,29137,
8239629138,29139,29140,29141,29142,29143,29144,29145,29146,29147,29148,29149,
8239729150,29151,29152,29153,29154,29155,29156,29157,29158,29159,29160,29161,
8239829162,29163,29164,29165,29166,29167,29168,29169,29170,29171,29172,29173,
8239929174,29175,29176,29177,29178,29179,29180,29181,29182,29183,29184,29185,
8240029186,29187,29188,29189,29190,29191,29192,29193,29194,29195,29196,29197,
8240129198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,
8240229210,29211,29212,29213,29214,29215,29216,29217,29218,29219,29220,29221,
8240329222,29223,29224,29225,29226,29227,29228,29229,29230,29231,29232,29233,
8240429234,29235,29236,29237,29238,29239,29240,29241,29242,29243,29244,29245,
8240529246,29247,29248,29249,29250,29251,29252,29253,29254,29255,29256,29257,
8240629258,29259,29260,29261,29262,29263,29264,29265,29266,29267,29268,29269,
8240729270,29271,29272,29273,29274,29275,29276,29277,29278,29279,29280,29281,
8240829282,29283,29284,29285,29286,29287,29288,29289,29290,29291,29292,29293,
8240929294,29295,29296,29297,29298,29299,29300,29301,29302,29303,29304,29305,
8241029306,29307,29308,29309,29310,29311,29312,29313,29314,29315,29316,29317,
8241129318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,
8241229330,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,
8241329342,29343,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,
8241429354,29355,29356,29357,29358,29359,29360,29361,29362,29363,29364,29365,
8241529366,29367,29368,29369,29370,29371,29372,29373,29374,29375,29376,29377,
8241629378,29379,29380,29381,29382,29383,29384,29385,29386,29387,29388,29389,
8241729390,29391,29392,29393,29394,29395,29396,29397,29398,29399,29400,29401,
8241829402,29403,29404,29405,29406,29407,29408,29409,29410,29411,29412,29413,
8241929414,29415,29416,29417,29418,29419,29420,29421,29422,29423,29424,29425,
8242029426,29427,29428,29429,29430,29431,29432,29433,29434,29435,29436,29437,
8242129438,29439,29440,29441,29442,29443,29444,29445,29446,29447,29448,29449,
8242229450,29451,29452,29453,29454,29455,29456,29457,29458,29459,29460,29461,
8242329462,29463,29464,29465,29466,29467,29468,29469,29470,29471,29472,29473,
8242429474,29475,29476,29477,29478,29479,29480,29481,29482,29483,29484,29485,
8242529486,29487,29488,29489,29490,29491,29492,29493,29494,29495,29496,29497,
8242629498,29499,29500,29501,29502,29503,29504,29505,29506,29507,29508,29509,
8242729510,29511,29512,29513,29514,29515,29516,29517,29518,29519,29520,29521,
8242829522,29523,29524,29525,29526,29527,29528,29529,29530,29531,29532,29533,
8242929534,29535,29536,29537,29538,29539,29540,29541,29542,29543,29544,29545,
8243029546,29547,29548,29549,29550,29551,29552,29553,29554,29555,29556,29557,
8243129558,29559,29560,29561,29562,29563,29564,29565,29566,29567,29568,29569,
8243229570,29571,29572,29573,29574,29575,29576,29577,29578,29579,29580,29581,
8243329582,29583,29584,29585,29586,29587,29588,29589,29590,29591,29592,29593,
8243429594,29595,29596,29597,29598,29599,29600,29601,29602,29603,29604,29605,
8243529606,29607,29608,29609,29610,29611,29612,29613,29614,29615,29616,29617,
8243629618,29619,29620,29621,29622,29623,29624,29625,29626,29627,29628,29629,
8243729630,29631,29632,29633,29634,29635,29636,29637,29638,29639,29640,29641,
8243829642,29643,29644,29645,29646,29647,29648,29649,29650,29651,29652,29653,
8243929654,29655,29656,29657,29658,29659,29660,29661,29662,29663,29664,29665,
8244029666,29667,29668,29669,29670,29671,29672,29673,29674,29675,29676,29677,
8244129678,29679,29680,29681,29682,29683,29684,29685,29686,29687,29688,29689,
8244229690,29691,29692,29693,29694,29695,29696,29697,29698,29699,29700,29701,
8244329702,29703,29704,29705,29706,29707,29708,29709,29710,29711,29712,29713,
8244429714,29715,29716,29717,29718,29719,29720,29721,29722,29723,29724,29725,
8244529726,29727,29728,29729,29730,29731,29732,29733,29734,29735,29736,29737,
8244629738,29739,29740,29741,29742,29743,29744,29745,29746,29747,29748,29749,
8244729750,29751,29752,29753,29754,29755,29756,29757,29758,29759,29760,29761,
8244829762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,
8244929774,29775,29776,29777,29778,29779,29780,29781,29782,29783,29784,29785,
8245029786,29787,29788,29789,29790,29791,29792,29793,29794,29795,29796,29797,
8245129798,29799,29800,29801,29802,29803,29804,29805,29806,29807,29808,29809,
8245229810,29811,29812,29813,29814,29815,29816,29817,29818,29819,29820,29821,
8245329822,29823,29824,29825,29826,29827,29828,29829,29830,29831,29832,29833,
8245429834,29835,29836,29837,29838,29839,29840,29841,29842,29843,29844,29845,
8245529846,29847,29848,29849,29850,29851,29852,29853,29854,29855,29856,29857,
8245629858,29859,29860,29861,29862,29863,29864,29865,29866,29867,29868,29869,
8245729870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,
8245829882,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,
8245929894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,
8246029906,29907,29908,29909,29910,29911,29912,29913,29914,29915,29916,29917,
8246129918,29919,29920,29921,29922,29923,29924,29925,29926,29927,29928,29929,
8246229930,29931,29932,29933,29934,29935,29936,29937,29938,29939,29940,29941,
8246329942,29943,29944,29945,29946,29947,29948,29949,29950,29951,29952,29953,
8246429954,29955,29956,29957,29958,29959,29960,29961,29962,29963,29964,29965,
8246529966,29967,29968,29969,29970,29971,29972,29973,29974,29975,29976,29977,
8246629978,29979,29980,29981,29982,29983,29984,29985,29986,29987,29988,29989,
8246729990,29991,29992,29993,29994,29995,29996,29997,29998,29999,30000,30001,
8246830002,30003,30004,30005,30006,30007,30008,30009,30010,30011,30012,30013,
8246930014,30015,30016,30017,30018,30019,30020,30021,30022,30023,30024,30025,
8247030026,30027,30028,30029,30030,30031,30032,30033,30034,30035,30036,30037,
8247130038,30039,30040,30041,30042,30043,30044,30045,30046,30047,30048,30049,
8247230050,30051,30052,30053,30054,30055,30056,30057,30058,30059,30060,30061,
8247330062,30063,30064,30065,30066,30067,30068,30069,30070,30071,30072,30073,
8247430074,30075,30076,30077,30078,30079,30080,30081,30082,30083,30084,30085,
8247530086,30087,30088,30089,30090,30091,30092,30093,30094,30095,30096,30097,
8247630098,30099,30100,30101,30102,30103,30104,30105,30106,30107,30108,30109,
8247730110,30111,30112,30113,30114,30115,30116,30117,30118,30119,30120,30121,
8247830122,30123,30124,30125,30126,30127,30128,30129,30130,30131,30132,30133,
8247930134,30135,30136,30137,30138,30139,30140,30141,30142,30143,30144,30145,
8248030146,30147,30148,30149,30150,30151,30152,30153,30154,30155,30156,30157,
8248130158,30159,30160,30161,30162,30163,30164,30165,30166,30167,30168,30169,
8248230170,30171,30172,30173,30174,30175,30176,30177,30178,30179,30180,30181,
8248330182,30183,30184,30185,30186,30187,30188,30189,30190,30191,30192,30193,
8248430194,30195,30196,30197,30198,30199,30200,30201,30202,30203,30204,30205,
8248530206,30207,30208,30209,30210,30211,30212,30213,30214,30215,30216,30217,
8248630218,30219,30220,30221,30222,30223,30224,30225,30226,30227,30228,30229,
8248730230,30231,30232,30233,30234,30235,30236,30237,30238,30239,30240,30241,
8248830242,30243,30244,30245,30246,30247,30248,30249,30250,30251,30252,30253,
8248930254,30255,30256,30257,30258,30259,30260,30261,30262,30263,30264,30265,
8249030266,30267,30268,30269,30270,30271,30272,30273,30274,30275,30276,30277,
8249130278,30279,30280,30281,30282,30283,30284,30285,30286,30287,30288,30289,
8249230290,30291,30292,30293,30294,30295,30296,30297,30298,30299,30300,30301,
8249330302,30303,30304,30305,30306,30307,30308,30309,30310,30311,30312,30313,
8249430314,30315,30316,30317,30318,30319,30320,30321,30322,30323,30324,30325,
8249530326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,
8249630338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,
8249730350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,
8249830362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30372,30373,
8249930374,30375,30376,30377,30378,30379,30380,30381,30382,30383,30384,30385,
8250030386,30387,30388,30389,30390,30391,30392,30393,30394,30395,30396,30397,
8250130398,30399,30400,30401,30402,30403,30404,30405,30406,30407,30408,30409,
8250230410,30411,30412,30413,30414,30415,30416,30417,30418,30419,30420,30421,
8250330422,30423,30424,30425,30426,30427,30428,30429,30430,30431,30432,30433,
8250430434,30435,30436,30437,30438,30439,30440,30441,30442,30443,30444,30445,
8250530446,30447,30448,30449,30450,30451,30452,30453,30454,30455,30456,30457,
8250630458,30459,30460,30461,30462,30463,30464,30465,30466,30467,30468,30469,
8250730470,30471,30472,30473,30474,30475,30476,30477,30478,30479,30480,30481,
8250830482,30483,30484,30485,30486,30487,30488,30489,30490,30491,30492,30493,
8250930494,30495,30496,30497,30498,30499,30500,30501,30502,30503,30504,30505,
8251030506,30507,30508,30509,30510,30511,30512,30513,30514,30515,30516,30517,
8251130518,30519,30520,30521,30522,30523,30524,30525,30526,30527,30528,30529,
8251230530,30531,30532,30533,30534,30535,30536,30537,30538,30539,30540,30541,
8251330542,30543,30544,30545,30546,30547,30548,30549,30550,30551,30552,30553,
8251430554,30555,30556,30557,30558,30559,30560,30561,30562,30563,30564,30565,
8251530566,30567,30568,30569,30570,30571,30572,30573,30574,30575,30576,30577,
8251630578,30579,30580,30581,30582,30583,30584,30585,30586,30587,30588,30589,
8251730590,30591,30592,30593,30594,30595,30596,30597,30598,30599,30600,30601,
8251830602,30603,30604,30605,30606,30607,30608,30609,30610,30611,30612,30613,
8251930614,30615,30616,30617,30618,30619,30620,30621,30622,30623,30624,30625,
8252030626,30627,30628,30629,30630,30631,30632,30633,30634,30635,30636,30637,
8252130638,30639,30640,30641,30642,30643,30644,30645,30646,30647,30648,30649,
8252230650,30651,30652,30653,30654,30655,30656,30657,30658,30659,30660,30661,
8252330662,30663,30664,30665,30666,30667,30668,30669,30670,30671,30672,30673,
8252430674,30675,30676,30677,30678,30679,30680,30681,30682,30683,30684,30685,
8252530686,30687,30688,30689,30690,30691,30692,30693,30694,30695,30696,30697,
8252630698,30699,30700,30701,30702,30703,30704,30705,30706,30707,30708,30709,
8252730710,30711,30712,30713,30714,30715,30716,30717,30718,30719,30720,30721,
8252830722,30723,30724,30725,30726,30727,30728,30729,30730,30731,30732,30733,
8252930734,30735,30736,30737,30738,30739,30740,30741,30742,30743,30744,30745,
8253030746,30747,30748,30749,30750,30751,30752,30753,30754,30755,30756,30757,
8253130758,30759,30760,30761,30762,30763,30764,30765,30766,30767,30768,30769,
8253230770,30771,30772,30773,30774,30775,30776,30777,30778,30779,30780,30781,
8253330782,30783,30784,30785,30786,30787,30788,30789,30790,30791,30792,30793,
8253430794,30795,30796,30797,30798,30799,30800,30801,30802,30803,30804,30805,
8253530806,30807,30808,30809,30810,30811,30812,30813,30814,30815,30816,30817,
8253630818,30819,30820,30821,30822,30823,30824,30825,30826,30827,30828,30829,
8253730830,30831,30832,30833,30834,30835,30836,30837,30838,30839,30840,30841,
8253830842,30843,30844,30845,30846,30847,30848,30849,30850,30851,30852,30853,
8253930854,30855,30856,30857,30858,30859,30860,30861,30862,30863,30864,30865,
8254030866,30867,30868,30869,30870,30871,30872,30873,30874,30875,30876,30877,
8254130878,30879,30880,30881,30882,30883,30884,30885,30886,30887,30888,30889,
8254230890,30891,30892,30893,30894,30895,30896,30897,30898,30899,30900,30901,
8254330902,30903,30904,30905,30906,30907,30908,30909,30910,30911,30912,30913,
8254430914,30915,30916,30917,30918,30919,30920,30921,30922,30923,30924,30925,
8254530926,30927,30928,30929,30930,30931,30932,30933,30934,30935,30936,30937,
8254630938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,
8254730950,30951,30952,30953,30954,30955,30956,30957,30958,30959,30960,30961,
8254830962,30963,30964,30965,30966,30967,30968,30969,30970,30971,30972,30973,
8254930974,30975,30976,30977,30978,30979,30980,30981,30982,30983,30984,30985,
8255030986,30987,30988,30989,30990,30991,30992,30993,30994,30995,30996,30997,
8255130998,30999,31000,31001,31002,31003,31004,31005,31006,31007,31008,31009,
8255231010,31011,31012,31013,31014,31015,31016,31017,31018,31019,31020,31021,
8255331022,31023,31024,31025,31026,31027,31028,31029,31030,31031,31032,31033,
8255431034,31035,31036,31037,31038,31039,31040,31041,31042,31043,31044,31045,
8255531046,31047,31048,31049,31050,31051,31052,31053,31054,31055,31056,31057,
8255631058,31059,31060,31061,31062,31063,31064,31065,31066,31067,31068,31069,
8255731070,31071,31072,31073,31074,31075,31076,31077,31078,31079,31080,31081,
8255831082,31083,31084,31085,31086,31087,31088,31089,31090,31091,31092,31093,
8255931094,31095,31096,31097,31098,31099,31100,31101,31102,31103,31104,31105,
8256031106,31107,31108,31109,31110,31111,31112,31113,31114,31115,31116,31117,
8256131118,31119,31120,31121,31122,31123,31124,31125,31126,31127,31128,31129,
8256231130,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,
8256331142,31143,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,
8256431154,31155,31156,31157,31158,31159,31160,31161,31162,31163,31164,31165,
8256531166,31167,31168,31169,31170,31171,31172,31173,31174,31175,31176,31177,
8256631178,31179,31180,31181,31182,31183,31184,31185,31186,31187,31188,31189,
8256731190,31191,31192,31193,31194,31195,31196,31197,31198,31199,31200,31201,
8256831202,31203,31204,31205,31206,31207,31208,31209,31210,31211,31212,31213,
8256931214,31215,31216,31217,31218,31219,31220,31221,31222,31223,31224,31225,
8257031226,31227,31228,31229,31230,31231,31232,31233,31234,31235,31236,31237,
8257131238,31239,31240,31241,31242,31243,31244,31245,31246,31247,31248,31249,
8257231250,31251,31252,31253,31254,31255,31256,31257,31258,31259,31260,31261,
8257331262,31263,31264,31265,31266,31267,31268,31269,31270,31271,31272,31273,
8257431274,31275,31276,31277,31278,31279,31280,31281,31282,31283,31284,31285,
8257531286,31287,31288,31289,31290,31291,31292,31293,31294,31295,31296,31297,
8257631298,31299,31300,31301,31302,31303,31304,31305,31306,31307,31308,31309,
8257731310,31311,31312,31313,31314,31315,31316,31317,31318,31319,31320,31321,
8257831322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,
8257931334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31344,31345,
8258031346,31347,31348,31349,31350,31351,31352,31353,31354,31355,31356,31357,
8258131358,31359,31360,31361,31362,31363,31364,31365,31366,31367,31368,31369,
8258231370,31371,31372,31373,31374,31375,31376,31377,31378,31379,31380,31381,
8258331382,31383,31384,31385,31386,31387,31388,31389,31390,31391,31392,31393,
8258431394,31395,31396,31397,31398,31399,31400,31401,31402,31403,31404,31405,
8258531406,31407,31408,31409,31410,31411,31412,31413,31414,31415,31416,31417,
8258631418,31419,31420,31421,31422,31423,31424,31425,31426,31427,31428,31429,
8258731430,31431,31432,31433,31434,31435,31436,31437,31438,31439,31440,31441,
8258831442,31443,31444,31445,31446,31447,31448,31449,31450,31451,31452,31453,
8258931454,31455,31456,31457,31458,31459,31460,31461,31462,31463,31464,31465,
8259031466,31467,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,
8259131478,31479,31480,31481,31482,31483,31484,31485,31486,31487,31488,31489,
8259231490,31491,31492,31493,31494,31495,31496,31497,31498,31499,31500,31501,
8259331502,31503,31504,31505,31506,31507,31508,31509,31510,31511,31512,31513,
8259431514,31515,31516,31517,31518,31519,31520,31521,31522,31523,31524,31525,
8259531526,31527,31528,31529,31530,31531,31532,31533,31534,31535,31536,31537,
8259631538,31539,31540,31541,31542,31543,31544,31545,31546,31547,31548,31549,
8259731550,31551,31552,31553,31554,31555,31556,31557,31558,31559,31560,31561,
8259831562,31563,31564,31565,31566,31567,31568,31569,31570,31571,31572,31573,
8259931574,31575,31576,31577,31578,31579,31580,31581,31582,31583,31584,31585,
8260031586,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,
8260131598,31599,31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,
8260231610,31611,31612,31613,31614,31615,31616,31617,31618,31619,31620,31621,
8260331622,31623,31624,31625,31626,31627,31628,31629,31630,31631,31632,31633,
8260431634,31635,31636,31637,31638,31639,31640,31641,31642,31643,31644,31645,
8260531646,31647,31648,31649,31650,31651,31652,31653,31654,31655,31656,31657,
8260631658,31659,31660,31661,31662,31663,31664,31665,31666,31667,31668,31669,
8260731670,31671,31672,31673,31674,31675,31676,31677,31678,31679,31680,31681,
8260831682,31683,31684,31685,31686,31687,31688,31689,31690,31691,31692,31693,
8260931694,31695,31696,31697,31698,31699,31700,31701,31702,31703,31704,31705,
8261031706,31707,31708,31709,31710,31711,31712,31713,31714,31715,31716,31717,
8261131718,31719,31720,31721,31722,31723,31724,31725,31726,31727,31728,31729,
8261231730,31731,31732,31733,31734,31735,31736,31737,31738,31739,31740,31741,
8261331742,31743,31744,31745,31746,31747,31748,31749,31750,31751,31752,31753,
8261431754,31755,31756,31757,31758,31759,31760,31761,31762,31763,31764,31765,
8261531766,31767,31768,31769,31770,31771,31772,31773,31774,31775,31776,31777,
8261631778,31779,31780,31781,31782,31783,31784,31785,31786,31787,31788,31789,
8261731790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31800,31801,
8261831802,31803,31804,31805,31806,31807,31808,31809,31810,31811,31812,31813,
8261931814,31815,31816,31817,31818,31819,31820,31821,31822,31823,31824,31825,
8262031826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,
8262131838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,
8262231850,31851,31852,31853,31854,31855,31856,31857,31858,31859,31860,31861,
8262331862,31863,31864,31865,31866,31867,31868,31869,31870,31871,31872,31873,
8262431874,31875,31876,31877,31878,31879,31880,31881,31882,31883,31884,31885,
8262531886,31887,31888,31889,31890,31891,31892,31893,31894,31895,31896,31897,
8262631898,31899,31900,31901,31902,31903,31904,31905,31906,31907,31908,31909,
8262731910,31911,31912,31913,31914,31915,31916,31917,31918,31919,31920,31921,
8262831922,31923,31924,31925,31926,31927,31928,31929,31930,31931,31932,31933,
8262931934,31935,31936,31937,31938,31939,31940,31941,31942,31943,31944,31945,
8263031946,31947,31948,31949,31950,31951,31952,31953,31954,31955,31956,31957,
8263131958,31959,31960,31961,31962,31963,31964,31965,31966,31967,31968,31969,
8263231970,31971,31972,31973,31974,31975,31976,31977,31978,31979,31980,31981,
8263331982,31983,31984,31985,31986,31987,31988,31989,31990,31991,31992,31993,
8263431994,31995,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,
8263532006,32007,32008,32009,32010,32011,32012,32013,32014,32015,32016,32017,
8263632018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,
8263732030,32031,32032,32033,32034,32035,32036,32037,32038,32039,32040,32041,
8263832042,32043,32044,32045,32046,32047,32048,32049,32050,32051,32052,32053,
8263932054,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,
8264032066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,
8264132078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,
8264232090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,
8264332102,32103,32104,32105,32106,32107,32108,32109,32110,32111,32112,32113,
8264432114,32115,32116,32117,32118,32119,32120,32121,32122,32123,32124,32125,
8264532126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,
8264632138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,
8264732150,32151,32152,32153,32154,32155,32156,32157,32158,32159,32160,32161,
8264832162,32163,32164,32165,32166,32167,32168,32169,32170,32171,32172,32173,
8264932174,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,
8265032186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,
8265132198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,
8265232210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,
8265332222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,
8265432234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,
8265532246,32247,32248,32249,32250,32251,32252,32253,32254,32255,32256,32257,
8265632258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,
8265732270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,
8265832282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,
8265932294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,
8266032306,32307,32308,32309,32310,32311,32312,32313,32314,32315,32316,32317,
8266132318,32319,32320,32321,32322,32323,32324,32325,32326,32327,32328,32329,
8266232330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,
8266332342,32343,32344,32345,32346,32347,32348,32349,32350,32351,32352,32353,
8266432354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,
8266532366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,
8266632378,32379,32380,32381,32382,32383,32384,32385,32386,32387,32388,32389,
8266732390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,
8266832402,32403,32404,32405,32406,32407,32408,32409,32410,32411,32412,32413,
8266932414,32415,32416,32417,32418,32419,32420,32421,32422,32423,32424,32425,
8267032426,32427,32428,32429,32430,32431,32432,32433,32434,32435,32436,32437,
8267132438,32439,32440,32441,32442,32443,32444,32445,32446,32447,32448,32449,
8267232450,32451,32452,32453,32454,32455,32456,32457,32458,32459,32460,32461,
8267332462,32463,32464,32465,32466,32467,32468,32469,32470,32471,32472,32473,
8267432474,32475,32476,32477,32478,32479,32480,32481,32482,32483,32484,32485,
8267532486,32487,32488,32489,32490,32491,32492,32493,32494,32495,32496,32497,
8267632498,32499,32500,32501,32502,32503,32504,32505,32506,32507,32508,32509,
8267732510,32511,32512,32513,32514,32515,32516,32517,32518,32519,32520,32521,
8267832522,32523,32524,32525,32526,32527,32528,32529,32530,32531,32532,32533,
8267932534,32535,32536,32537,32538,32539,32540,32541,32542,32543,32544,32545,
8268032546,32547,32548,32549,32550,32551,32552,32553,32554,32555,32556,32557,
8268132558,32559,32560,32561,32562,32563,32564,32565,32566,32567,32568,32569,
8268232570,32571,32572,32573,32574,32575,32576,32577,32578,32579,32580,32581,
8268332582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32592,32593,
8268432594,32595,32596,32597,32598,32599,32600,32601,32602,32603,32604,32605,
8268532606,32607,32608,32609,32610,32611,32612,32613,32614,32615,32616,32617,
8268632618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,
8268732630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,
8268832642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,
8268932654,32655,32656,32657,32658,32659,32660,32661,32662,32663,32664,32665,
8269032666,32667,32668,32669,32670,32671,32672,32673,32674,32675,32676,32677,
8269132678,32679,32680,32681,32682,32683,32684,32685,32686,32687,32688,32689,
8269232690,32691,32692,32693,32694,32695,32696,32697,32698,32699,32700,32701,
8269332702,32703,32704,32705,32706,32707,32708,32709,32710,32711,32712,32713,
8269432714,32715,32716,32717,32718,32719,32720,32721,32722,32723,32724,32725,
8269532726,32727,32728,32729,32730,32731,32732,32733,32734,32735,32736,32737,
8269632738,32739,32740,32741,32742,32743,32744,32745,32746,32747,32748,32749,
8269732750,32751,32752,32753,32754,32755,32756,32757,32758,32759,32760,32761,
8269832762,32763,32764,32765,32766,32767,32768L,32769L,32770L,32771L,32772L,
8269932773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,32781L,32782L,
8270032783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,32791L,32792L,
8270132793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,32801L,32802L,
8270232803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,32811L,32812L,
8270332813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,32821L,32822L,
8270432823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,32831L,32832L,
8270532833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,32841L,32842L,
8270632843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,32851L,32852L,
8270732853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,32861L,32862L,
8270832863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,32871L,32872L,
8270932873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,32881L,32882L,
8271032883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,32891L,32892L,
8271132893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,32901L,32902L,
8271232903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,32911L,32912L,
8271332913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,32921L,32922L,
8271432923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,32931L,32932L,
8271532933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,32941L,32942L,
8271632943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,32951L,32952L,
8271732953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,32961L,32962L,
8271832963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,32971L,32972L,
8271932973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,32981L,32982L,
8272032983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,32991L,32992L,
8272132993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,33001L,33002L,
8272233003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,33011L,33012L,
8272333013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,33021L,33022L,
8272433023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,33031L,33032L,
8272533033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,33041L,33042L,
8272633043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,33051L,33052L,
8272733053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,33061L,33062L,
8272833063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,33071L,33072L,
8272933073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,33081L,33082L,
8273033083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,33091L,33092L,
8273133093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,33101L,33102L,
8273233103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,33111L,33112L,
8273333113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,33121L,33122L,
8273433123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,33131L,33132L,
8273533133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,33141L,33142L,
8273633143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,33151L,33152L,
8273733153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,33161L,33162L,
8273833163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,33171L,33172L,
8273933173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,33181L,33182L,
8274033183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,33191L,33192L,
8274133193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,33201L,33202L,
8274233203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,33211L,33212L,
8274333213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,33221L,33222L,
8274433223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,33231L,33232L,
8274533233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,33241L,33242L,
8274633243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,33251L,33252L,
8274733253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,33261L,33262L,
8274833263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,33271L,33272L,
8274933273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,33281L,33282L,
8275033283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,33291L,33292L,
8275133293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,33301L,33302L,
8275233303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,33311L,33312L,
8275333313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,33321L,33322L,
8275433323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,33331L,33332L,
8275533333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,33341L,33342L,
8275633343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,33351L,33352L,
8275733353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,33361L,33362L,
8275833363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,33371L,33372L,
8275933373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,33381L,33382L,
8276033383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,33391L,33392L,
8276133393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,33401L,33402L,
8276233403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,33411L,33412L,
8276333413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,33421L,33422L,
8276433423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,33431L,33432L,
8276533433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,33441L,33442L,
8276633443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,33451L,33452L,
8276733453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,33461L,33462L,
8276833463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,33471L,33472L,
8276933473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,33481L,33482L,
8277033483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,33491L,33492L,
8277133493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,33501L,33502L,
8277233503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,33511L,33512L,
8277333513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,33521L,33522L,
8277433523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,33531L,33532L,
8277533533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,33541L,33542L,
8277633543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,33551L,33552L,
8277733553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,33561L,33562L,
8277833563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,33571L,33572L,
8277933573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,33581L,33582L,
8278033583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,33591L,33592L,
8278133593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,33601L,33602L,
8278233603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,33611L,33612L,
8278333613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,33621L,33622L,
8278433623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,33631L,33632L,
8278533633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,33641L,33642L,
8278633643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,33651L,33652L,
8278733653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,33661L,33662L,
8278833663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,33671L,33672L,
8278933673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,33681L,33682L,
8279033683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,33691L,33692L,
8279133693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,33701L,33702L,
8279233703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,33711L,33712L,
8279333713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,33721L,33722L,
8279433723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,33731L,33732L,
8279533733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,33741L,33742L,
8279633743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,33751L,33752L,
8279733753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,33761L,33762L,
8279833763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,33771L,33772L,
8279933773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,33781L,33782L,
8280033783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,33791L,33792L,
8280133793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,33801L,33802L,
8280233803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,33811L,33812L,
8280333813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,33821L,33822L,
8280433823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,33831L,33832L,
8280533833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,33841L,33842L,
8280633843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,33851L,33852L,
8280733853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,33861L,33862L,
8280833863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,33871L,33872L,
8280933873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,33881L,33882L,
8281033883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,33891L,33892L,
8281133893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,33901L,33902L,
8281233903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,33911L,33912L,
8281333913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,33921L,33922L,
8281433923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,33931L,33932L,
8281533933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,33941L,33942L,
8281633943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,33951L,33952L,
8281733953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,33961L,33962L,
8281833963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,33971L,33972L,
8281933973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,33981L,33982L,
8282033983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,33991L,33992L,
8282133993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,34001L,34002L,
8282234003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,34011L,34012L,
8282334013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,34021L,34022L,
8282434023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,34031L,34032L,
8282534033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,34041L,34042L,
8282634043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,34051L,34052L,
8282734053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,34061L,34062L,
8282834063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,34071L,34072L,
8282934073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,34081L,34082L,
8283034083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,34091L,34092L,
8283134093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,34101L,34102L,
8283234103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,34111L,34112L,
8283334113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,34121L,34122L,
8283434123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,34131L,34132L,
8283534133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,34141L,34142L,
8283634143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,34151L,34152L,
8283734153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,34161L,34162L,
8283834163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,34171L,34172L,
8283934173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,34181L,34182L,
8284034183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,34191L,34192L,
8284134193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,34201L,34202L,
8284234203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,34211L,34212L,
8284334213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,34221L,34222L,
8284434223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,34231L,34232L,
8284534233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,34241L,34242L,
8284634243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,34251L,34252L,
8284734253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,34261L,34262L,
8284834263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,34271L,34272L,
8284934273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,34281L,34282L,
8285034283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,34291L,34292L,
8285134293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,34301L,34302L,
8285234303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,34311L,34312L,
8285334313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,34321L,34322L,
8285434323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,34331L,34332L,
8285534333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,34341L,34342L,
8285634343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,34351L,34352L,
8285734353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,34361L,34362L,
8285834363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,34371L,34372L,
8285934373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,34381L,34382L,
8286034383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,34391L,34392L,
8286134393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,34401L,34402L,
8286234403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,34411L,34412L,
8286334413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,34421L,34422L,
8286434423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,34431L,34432L,
8286534433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,34441L,34442L,
8286634443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,34451L,34452L,
8286734453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,34461L,34462L,
8286834463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,34471L,34472L,
8286934473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,34481L,34482L,
8287034483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,34491L,34492L,
8287134493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,34501L,34502L,
8287234503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,34511L,34512L,
8287334513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,34521L,34522L,
8287434523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,34531L,34532L,
8287534533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,34541L,34542L,
8287634543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,34551L,34552L,
8287734553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,34561L,34562L,
8287834563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,34571L,34572L,
8287934573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,34581L,34582L,
8288034583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,34591L,34592L,
8288134593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,34601L,34602L,
8288234603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,34611L,34612L,
8288334613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,34621L,34622L,
8288434623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,34631L,34632L,
8288534633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,34641L,34642L,
8288634643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,34651L,34652L,
8288734653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,34661L,34662L,
8288834663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,34671L,34672L,
8288934673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,34681L,34682L,
8289034683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,34691L,34692L,
8289134693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,34701L,34702L,
8289234703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,34711L,34712L,
8289334713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,34721L,34722L,
8289434723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,34731L,34732L,
8289534733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,34741L,34742L,
8289634743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,34751L,34752L,
8289734753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,34761L,34762L,
8289834763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,34771L,34772L,
8289934773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,34781L,34782L,
8290034783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,34791L,34792L,
8290134793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,34801L,34802L,
8290234803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,34811L,34812L,
8290334813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,34821L,34822L,
8290434823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,34831L,34832L,
8290534833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,34841L,34842L,
8290634843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,34851L,34852L,
8290734853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,34861L,34862L,
8290834863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,34871L,34872L,
8290934873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,34881L,34882L,
8291034883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,34891L,34892L,
8291134893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,34901L,34902L,
8291234903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,34911L,34912L,
8291334913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,34921L,34922L,
8291434923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,34931L,34932L,
8291534933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,34941L,34942L,
8291634943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,34951L,34952L,
8291734953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,34961L,34962L,
8291834963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,34971L,34972L,
8291934973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,34981L,34982L,
8292034983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,34991L,34992L,
8292134993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,35001L,35002L,
8292235003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,35011L,35012L,
8292335013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,35021L,35022L,
8292435023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,35031L,35032L,
8292535033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,35041L,35042L,
8292635043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,35051L,35052L,
8292735053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,35061L,35062L,
8292835063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,35071L,35072L,
8292935073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,35081L,35082L,
8293035083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,35091L,35092L,
8293135093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,35101L,35102L,
8293235103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,35111L,35112L,
8293335113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,35121L,35122L,
8293435123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,35131L,35132L,
8293535133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,35141L,35142L,
8293635143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,35151L,35152L,
8293735153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,35161L,35162L,
8293835163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,35171L,35172L,
8293935173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,35181L,35182L,
8294035183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,35191L,35192L,
8294135193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,35201L,35202L,
8294235203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,35211L,35212L,
8294335213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,35221L,35222L,
8294435223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,35231L,35232L,
8294535233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,35241L,35242L,
8294635243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,35251L,35252L,
8294735253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,35261L,35262L,
8294835263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,35271L,35272L,
8294935273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,35281L,35282L,
8295035283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,35291L,35292L,
8295135293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,35301L,35302L,
8295235303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,35311L,35312L,
8295335313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,35321L,35322L,
8295435323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,35331L,35332L,
8295535333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,35341L,35342L,
8295635343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,35351L,35352L,
8295735353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,35361L,35362L,
8295835363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,35371L,35372L,
8295935373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,35381L,35382L,
8296035383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,35391L,35392L,
8296135393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,35401L,35402L,
8296235403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,35411L,35412L,
8296335413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,35421L,35422L,
8296435423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,35431L,35432L,
8296535433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,35441L,35442L,
8296635443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,35451L,35452L,
8296735453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,35461L,35462L,
8296835463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,35471L,35472L,
8296935473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,35481L,35482L,
8297035483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,35491L,35492L,
8297135493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,35501L,35502L,
8297235503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,35511L,35512L,
8297335513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,35521L,35522L,
8297435523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,35531L,35532L,
8297535533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,35541L,35542L,
8297635543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,35551L,35552L,
8297735553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,35561L,35562L,
8297835563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,35571L,35572L,
8297935573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,35581L,35582L,
8298035583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,35591L,35592L,
8298135593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,35601L,35602L,
8298235603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,35611L,35612L,
8298335613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,35621L,35622L,
8298435623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,35631L,35632L,
8298535633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,35641L,35642L,
8298635643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,35651L,35652L,
8298735653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,35661L,35662L,
8298835663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,35671L,35672L,
8298935673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,35681L,35682L,
8299035683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,35691L,35692L,
8299135693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,35701L,35702L,
8299235703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,35711L,35712L,
8299335713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,35721L,35722L,
8299435723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,35731L,35732L,
8299535733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,35741L,35742L,
8299635743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,35751L,35752L,
8299735753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,35761L,35762L,
8299835763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,35771L,35772L,
8299935773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,35781L,35782L,
8300035783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,35791L,35792L,
8300135793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,35801L,35802L,
8300235803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,35811L,35812L,
8300335813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,35821L,35822L,
8300435823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,35831L,35832L,
8300535833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,35841L,35842L,
8300635843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,35851L,35852L,
8300735853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,35861L,35862L,
8300835863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,35871L,35872L,
8300935873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,35881L,35882L,
8301035883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,35891L,35892L,
8301135893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,35901L,35902L,
8301235903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,35911L,35912L,
8301335913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,35921L,35922L,
8301435923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,35931L,35932L,
8301535933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,35941L,35942L,
8301635943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,35951L,35952L,
8301735953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,35961L,35962L,
8301835963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,35971L,35972L,
8301935973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,35981L,35982L,
8302035983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,35991L,35992L,
8302135993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,36001L,36002L,
8302236003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,36011L,36012L,
8302336013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,36021L,36022L,
8302436023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,36031L,36032L,
8302536033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,36041L,36042L,
8302636043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,36051L,36052L,
8302736053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,36061L,36062L,
8302836063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,36071L,36072L,
8302936073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,36081L,36082L,
8303036083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,36091L,36092L,
8303136093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,36101L,36102L,
8303236103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,36111L,36112L,
8303336113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,36121L,36122L,
8303436123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,36131L,36132L,
8303536133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,36141L,36142L,
8303636143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,36151L,36152L,
8303736153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,36161L,36162L,
8303836163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,36171L,36172L,
8303936173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,36181L,36182L,
8304036183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,36191L,36192L,
8304136193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,36201L,36202L,
8304236203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,36211L,36212L,
8304336213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,36221L,36222L,
8304436223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,36231L,36232L,
8304536233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,36241L,36242L,
8304636243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,36251L,36252L,
8304736253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,36261L,36262L,
8304836263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,36271L,36272L,
8304936273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,36281L,36282L,
8305036283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,36291L,36292L,
8305136293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,36301L,36302L,
8305236303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,36311L,36312L,
8305336313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,36321L,36322L,
8305436323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,36331L,36332L,
8305536333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,36341L,36342L,
8305636343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,36351L,36352L,
8305736353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,36361L,36362L,
8305836363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,36371L,36372L,
8305936373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,36381L,36382L,
8306036383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,36391L,36392L,
8306136393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,36401L,36402L,
8306236403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,36411L,36412L,
8306336413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,36421L,36422L,
8306436423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,36431L,36432L,
8306536433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,36441L,36442L,
8306636443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,36451L,36452L,
8306736453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,36461L,36462L,
8306836463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,36471L,36472L,
8306936473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,36481L,36482L,
8307036483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,36491L,36492L,
8307136493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,36501L,36502L,
8307236503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,36511L,36512L,
8307336513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,36521L,36522L,
8307436523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,36531L,36532L,
8307536533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,36541L,36542L,
8307636543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,36551L,36552L,
8307736553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,36561L,36562L,
8307836563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,36571L,36572L,
8307936573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,36581L,36582L,
8308036583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,36591L,36592L,
8308136593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,36601L,36602L,
8308236603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,36611L,36612L,
8308336613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,36621L,36622L,
8308436623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,36631L,36632L,
8308536633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,36641L,36642L,
8308636643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,36651L,36652L,
8308736653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,36661L,36662L,
8308836663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,36671L,36672L,
8308936673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,36681L,36682L,
8309036683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,36691L,36692L,
8309136693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,36701L,36702L,
8309236703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,36711L,36712L,
8309336713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,36721L,36722L,
8309436723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,36731L,36732L,
8309536733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,36741L,36742L,
8309636743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,36751L,36752L,
8309736753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,36761L,36762L,
8309836763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,36771L,36772L,
8309936773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,36781L,36782L,
8310036783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,36791L,36792L,
8310136793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,36801L,36802L,
8310236803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,36811L,36812L,
8310336813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,36821L,36822L,
8310436823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,36831L,36832L,
8310536833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,36841L,36842L,
8310636843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,36851L,36852L,
8310736853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,36861L,36862L,
8310836863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,36871L,36872L,
8310936873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,36881L,36882L,
8311036883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,36891L,36892L,
8311136893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,36901L,36902L,
8311236903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,36911L,36912L,
8311336913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,36921L,36922L,
8311436923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,36931L,36932L,
8311536933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,36941L,36942L,
8311636943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,36951L,36952L,
8311736953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,36961L,36962L,
8311836963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,36971L,36972L,
8311936973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,36981L,36982L,
8312036983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,36991L,36992L,
8312136993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,37001L,37002L,
8312237003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,37011L,37012L,
8312337013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,37021L,37022L,
8312437023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,37031L,37032L,
8312537033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,37041L,37042L,
8312637043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,37051L,37052L,
8312737053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,37061L,37062L,
8312837063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,37071L,37072L,
8312937073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,37081L,37082L,
8313037083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,37091L,37092L,
8313137093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,37101L,37102L,
8313237103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,37111L,37112L,
8313337113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,37121L,37122L,
8313437123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,37131L,37132L,
8313537133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,37141L,37142L,
8313637143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,37151L,37152L,
8313737153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,37161L,37162L,
8313837163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,37171L,37172L,
8313937173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,37181L,37182L,
8314037183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,37191L,37192L,
8314137193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,37201L,37202L,
8314237203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,37211L,37212L,
8314337213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,37221L,37222L,
8314437223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,37231L,37232L,
8314537233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,37241L,37242L,
8314637243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,37251L,37252L,
8314737253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,37261L,37262L,
8314837263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,37271L,37272L,
8314937273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,37281L,37282L,
8315037283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,37291L,37292L,
8315137293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,37301L,37302L,
8315237303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,37311L,37312L,
8315337313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,37321L,37322L,
8315437323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,37331L,37332L,
8315537333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,37341L,37342L,
8315637343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,37351L,37352L,
8315737353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,37361L,37362L,
8315837363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,37371L,37372L,
8315937373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,37381L,37382L,
8316037383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,37391L,37392L,
8316137393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,37401L,37402L,
8316237403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,37411L,37412L,
8316337413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,37421L,37422L,
8316437423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,37431L,37432L,
8316537433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,37441L,37442L,
8316637443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,37451L,37452L,
8316737453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,37461L,37462L,
8316837463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,37471L,37472L,
8316937473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,37481L,37482L,
8317037483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,37491L,37492L,
8317137493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,37501L,37502L,
8317237503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,37511L,37512L,
8317337513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,37521L,37522L,
8317437523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,37531L,37532L,
8317537533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,37541L,37542L,
8317637543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,37551L,37552L,
8317737553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,37561L,37562L,
8317837563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,37571L,37572L,
8317937573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,37581L,37582L,
8318037583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,37591L,37592L,
8318137593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,37601L,37602L,
8318237603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,37611L,37612L,
8318337613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,37621L,37622L,
8318437623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,37631L,37632L,
8318537633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,37641L,37642L,
8318637643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,37651L,37652L,
8318737653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,37661L,37662L,
8318837663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,37671L,37672L,
8318937673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,37681L,37682L,
8319037683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,37691L,37692L,
8319137693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,37701L,37702L,
8319237703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,37711L,37712L,
8319337713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,37721L,37722L,
8319437723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,37731L,37732L,
8319537733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,37741L,37742L,
8319637743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,37751L,37752L,
8319737753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,37761L,37762L,
8319837763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,37771L,37772L,
8319937773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,37781L,37782L,
8320037783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,37791L,37792L,
8320137793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,37801L,37802L,
8320237803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,37811L,37812L,
8320337813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,37821L,37822L,
8320437823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,37831L,37832L,
8320537833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,37841L,37842L,
8320637843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,37851L,37852L,
8320737853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,37861L,37862L,
8320837863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,37871L,37872L,
8320937873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,37881L,37882L,
8321037883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,37891L,37892L,
8321137893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,37901L,37902L,
8321237903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,37911L,37912L,
8321337913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,37921L,37922L,
8321437923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,37931L,37932L,
8321537933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,37941L,37942L,
8321637943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,37951L,37952L,
8321737953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,37961L,37962L,
8321837963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,37971L,37972L,
8321937973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,37981L,37982L,
8322037983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,37991L,37992L,
8322137993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,38001L,38002L,
8322238003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,38011L,38012L,
8322338013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,38021L,38022L,
8322438023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,38031L,38032L,
8322538033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,38041L,38042L,
8322638043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,38051L,38052L,
8322738053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,38061L,38062L,
8322838063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,38071L,38072L,
8322938073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,38081L,38082L,
8323038083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,38091L,38092L,
8323138093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,38101L,38102L,
8323238103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,38111L,38112L,
8323338113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,38121L,38122L,
8323438123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,38131L,38132L,
8323538133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,38141L,38142L,
8323638143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,38151L,38152L,
8323738153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,38161L,38162L,
8323838163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,38171L,38172L,
8323938173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,38181L,38182L,
8324038183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,38191L,38192L,
8324138193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,38201L,38202L,
8324238203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,38211L,38212L,
8324338213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,38221L,38222L,
8324438223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,38231L,38232L,
8324538233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,38241L,38242L,
8324638243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,38251L,38252L,
8324738253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,38261L,38262L,
8324838263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,38271L,38272L,
8324938273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,38281L,38282L,
8325038283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,38291L,38292L,
8325138293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,38301L,38302L,
8325238303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,38311L,38312L,
8325338313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,38321L,38322L,
8325438323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,38331L,38332L,
8325538333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,38341L,38342L,
8325638343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,38351L,38352L,
8325738353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,38361L,38362L,
8325838363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,38371L,38372L,
8325938373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,38381L,38382L,
8326038383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,38391L,38392L,
8326138393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,38401L,38402L,
8326238403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,38411L,38412L,
8326338413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,38421L,38422L,
8326438423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,38431L,38432L,
8326538433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,38441L,38442L,
8326638443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,38451L,38452L,
8326738453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,38461L,38462L,
8326838463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,38471L,38472L,
8326938473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,38481L,38482L,
8327038483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,38491L,38492L,
8327138493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,38501L,38502L,
8327238503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,38511L,38512L,
8327338513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,38521L,38522L,
8327438523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,38531L,38532L,
8327538533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,38541L,38542L,
8327638543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,38551L,38552L,
8327738553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,38561L,38562L,
8327838563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,38571L,38572L,
8327938573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,38581L,38582L,
8328038583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,38591L,38592L,
8328138593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,38601L,38602L,
8328238603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,38611L,38612L,
8328338613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,38621L,38622L,
8328438623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,38631L,38632L,
8328538633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,38641L,38642L,
8328638643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,38651L,38652L,
8328738653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,38661L,38662L,
8328838663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,38671L,38672L,
8328938673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,38681L,38682L,
8329038683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,38691L,38692L,
8329138693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,38701L,38702L,
8329238703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,38711L,38712L,
8329338713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,38721L,38722L,
8329438723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,38731L,38732L,
8329538733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,38741L,38742L,
8329638743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,38751L,38752L,
8329738753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,38761L,38762L,
8329838763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,38771L,38772L,
8329938773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,38781L,38782L,
8330038783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,38791L,38792L,
8330138793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,38801L,38802L,
8330238803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,38811L,38812L,
8330338813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,38821L,38822L,
8330438823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,38831L,38832L,
8330538833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,38841L,38842L,
8330638843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,38851L,38852L,
8330738853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,38861L,38862L,
8330838863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,38871L,38872L,
8330938873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,38881L,38882L,
8331038883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,38891L,38892L,
8331138893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,38901L,38902L,
8331238903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,38911L,38912L,
8331338913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,38921L,38922L,
8331438923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,38931L,38932L,
8331538933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,38941L,38942L,
8331638943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,38951L,38952L,
8331738953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,38961L,38962L,
8331838963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,38971L,38972L,
8331938973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,38981L,38982L,
8332038983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,38991L,38992L,
8332138993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,39001L,39002L,
8332239003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,39011L,39012L,
8332339013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,39021L,39022L,
8332439023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,39031L,39032L,
8332539033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,39041L,39042L,
8332639043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,39051L,39052L,
8332739053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,39061L,39062L,
8332839063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,39071L,39072L,
8332939073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,39081L,39082L,
8333039083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,39091L,39092L,
8333139093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,39101L,39102L,
8333239103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,39111L,39112L,
8333339113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,39121L,39122L,
8333439123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,39131L,39132L,
8333539133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,39141L,39142L,
8333639143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,39151L,39152L,
8333739153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,39161L,39162L,
8333839163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,39171L,39172L,
8333939173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,39181L,39182L,
8334039183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,39191L,39192L,
8334139193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,39201L,39202L,
8334239203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,39211L,39212L,
8334339213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,39221L,39222L,
8334439223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,39231L,39232L,
8334539233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,39241L,39242L,
8334639243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,39251L,39252L,
8334739253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,39261L,39262L,
8334839263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,39271L,39272L,
8334939273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,39281L,39282L,
8335039283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,39291L,39292L,
8335139293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,39301L,39302L,
8335239303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,39311L,39312L,
8335339313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,39321L,39322L,
8335439323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,39331L,39332L,
8335539333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,39341L,39342L,
8335639343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,39351L,39352L,
8335739353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,39361L,39362L,
8335839363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,39371L,39372L,
8335939373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,39381L,39382L,
8336039383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,39391L,39392L,
8336139393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,39401L,39402L,
8336239403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,39411L,39412L,
8336339413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,39421L,39422L,
8336439423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,39431L,39432L,
8336539433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,39441L,39442L,
8336639443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,39451L,39452L,
8336739453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,39461L,39462L,
8336839463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,39471L,39472L,
8336939473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,39481L,39482L,
8337039483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,39491L,39492L,
8337139493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,39501L,39502L,
8337239503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,39511L,39512L,
8337339513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,39521L,39522L,
8337439523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,39531L,39532L,
8337539533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,39541L,39542L,
8337639543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,39551L,39552L,
8337739553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,39561L,39562L,
8337839563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,39571L,39572L,
8337939573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,39581L,39582L,
8338039583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,39591L,39592L,
8338139593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,39601L,39602L,
8338239603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,39611L,39612L,
8338339613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,39621L,39622L,
8338439623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,39631L,39632L,
8338539633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,39641L,39642L,
8338639643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,39651L,39652L,
8338739653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,39661L,39662L,
8338839663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,39671L,39672L,
8338939673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,39681L,39682L,
8339039683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,39691L,39692L,
8339139693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,39701L,39702L,
8339239703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,39711L,39712L,
8339339713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,39721L,39722L,
8339439723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,39731L,39732L,
8339539733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,39741L,39742L,
8339639743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,39751L,39752L,
8339739753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,39761L,39762L,
8339839763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,39771L,39772L,
8339939773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,39781L,39782L,
8340039783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,39791L,39792L,
8340139793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,39801L,39802L,
8340239803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,39811L,39812L,
8340339813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,39821L,39822L,
8340439823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,39831L,39832L,
8340539833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,39841L,39842L,
8340639843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,39851L,39852L,
8340739853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,39861L,39862L,
8340839863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,39871L,39872L,
8340939873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,39881L,39882L,
8341039883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,39891L,39892L,
8341139893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,39901L,39902L,
8341239903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,39911L,39912L,
8341339913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,39921L,39922L,
8341439923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,39931L,39932L,
8341539933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,39941L,39942L,
8341639943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,39951L,39952L,
8341739953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,39961L,39962L,
8341839963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,39971L,39972L,
8341939973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,39981L,39982L,
8342039983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,39991L,39992L,
8342139993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,40001L,40002L,
8342240003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,40011L,40012L,
8342340013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,40021L,40022L,
8342440023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,40031L,40032L,
8342540033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,40041L,40042L,
8342640043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,40051L,40052L,
8342740053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,40061L,40062L,
8342840063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,40071L,40072L,
8342940073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,40081L,40082L,
8343040083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,40091L,40092L,
8343140093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,40101L,40102L,
8343240103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,40111L,40112L,
8343340113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,40121L,40122L,
8343440123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,40131L,40132L,
8343540133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,40141L,40142L,
8343640143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,40151L,40152L,
8343740153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,40161L,40162L,
8343840163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,40171L,40172L,
8343940173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,40181L,40182L,
8344040183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,40191L,40192L,
8344140193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,40201L,40202L,
8344240203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,40211L,40212L,
8344340213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,40221L,40222L,
8344440223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,40231L,40232L,
8344540233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,40241L,40242L,
8344640243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,40251L,40252L,
8344740253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,40261L,40262L,
8344840263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,40271L,40272L,
8344940273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,40281L,40282L,
8345040283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,40291L,40292L,
8345140293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,40301L,40302L,
8345240303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,40311L,40312L,
8345340313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,40321L,40322L,
8345440323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,40331L,40332L,
8345540333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,40341L,40342L,
8345640343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,40351L,40352L,
8345740353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,40361L,40362L,
8345840363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,40371L,40372L,
8345940373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,40381L,40382L,
8346040383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,40391L,40392L,
8346140393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,40401L,40402L,
8346240403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,40411L,40412L,
8346340413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,40421L,40422L,
8346440423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,40431L,40432L,
8346540433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,40441L,40442L,
8346640443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,40451L,40452L,
8346740453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,40461L,40462L,
8346840463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,40471L,40472L,
8346940473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,40481L,40482L,
8347040483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,40491L,40492L,
8347140493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,40501L,40502L,
8347240503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,40511L,40512L,
8347340513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,40521L,40522L,
8347440523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,40531L,40532L,
8347540533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,40541L,40542L,
8347640543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,40551L,40552L,
8347740553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,40561L,40562L,
8347840563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,40571L,40572L,
8347940573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,40581L,40582L,
8348040583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,40591L,40592L,
8348140593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,40601L,40602L,
8348240603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,40611L,40612L,
8348340613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,40621L,40622L,
8348440623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,40631L,40632L,
8348540633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,40641L,40642L,
8348640643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,40651L,40652L,
8348740653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,40661L,40662L,
8348840663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,40671L,40672L,
8348940673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,40681L,40682L,
8349040683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,40691L,40692L,
8349140693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,40701L,40702L,
8349240703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,40711L,40712L,
8349340713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,40721L,40722L,
8349440723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,40731L,40732L,
8349540733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,40741L,40742L,
8349640743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,40751L,40752L,
8349740753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,40761L,40762L,
8349840763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,40771L,40772L,
8349940773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,40781L,40782L,
8350040783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,40791L,40792L,
8350140793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,40801L,40802L,
8350240803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,40811L,40812L,
8350340813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,40821L,40822L,
8350440823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,40831L,40832L,
8350540833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,40841L,40842L,
8350640843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,40851L,40852L,
8350740853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,40861L,40862L,
8350840863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,40871L,40872L,
8350940873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,40881L,40882L,
8351040883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,40891L,40892L,
8351140893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,40901L,40902L,
8351240903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,40911L,40912L,
8351340913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,40921L,40922L,
8351440923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,40931L,40932L,
8351540933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,40941L,40942L,
8351640943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,40951L,40952L,
8351740953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,40961L,40962L,
8351840963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,40971L,40972L,
8351940973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,40981L,40982L,
8352040983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,40991L,40992L,
8352140993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,41001L,41002L,
8352241003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,41011L,41012L,
8352341013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,41021L,41022L,
8352441023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,41031L,41032L,
8352541033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,41041L,41042L,
8352641043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,41051L,41052L,
8352741053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,41061L,41062L,
8352841063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,41071L,41072L,
8352941073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,41081L,41082L,
8353041083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,41091L,41092L,
8353141093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,41101L,41102L,
8353241103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,41111L,41112L,
8353341113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,41121L,41122L,
8353441123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,41131L,41132L,
8353541133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,41141L,41142L,
8353641143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,41151L,41152L,
8353741153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,41161L,41162L,
8353841163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,41171L,41172L,
8353941173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,41181L,41182L,
8354041183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,41191L,41192L,
8354141193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,41201L,41202L,
8354241203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,41211L,41212L,
8354341213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,41221L,41222L,
8354441223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,41231L,41232L,
8354541233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,41241L,41242L,
8354641243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,41251L,41252L,
8354741253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,41261L,41262L,
8354841263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,41271L,41272L,
8354941273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,41281L,41282L,
8355041283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,41291L,41292L,
8355141293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,41301L,41302L,
8355241303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,41311L,41312L,
8355341313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,41321L,41322L,
8355441323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,41331L,41332L,
8355541333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,41341L,41342L,
8355641343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,41351L,41352L,
8355741353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,41361L,41362L,
8355841363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,41371L,41372L,
8355941373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,41381L,41382L,
8356041383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,41391L,41392L,
8356141393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,41401L,41402L,
8356241403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,41411L,41412L,
8356341413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,41421L,41422L,
8356441423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,41431L,41432L,
8356541433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,41441L,41442L,
8356641443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,41451L,41452L,
8356741453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,41461L,41462L,
8356841463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,41471L,41472L,
8356941473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,41481L,41482L,
8357041483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,41491L,41492L,
8357141493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,41501L,41502L,
8357241503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,41511L,41512L,
8357341513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,41521L,41522L,
8357441523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,41531L,41532L,
8357541533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,41541L,41542L,
8357641543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,41551L,41552L,
8357741553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,41561L,41562L,
8357841563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,41571L,41572L,
8357941573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,41581L,41582L,
8358041583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,41591L,41592L,
8358141593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,41601L,41602L,
8358241603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,41611L,41612L,
8358341613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,41621L,41622L,
8358441623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,41631L,41632L,
8358541633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,41641L,41642L,
8358641643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,41651L,41652L,
8358741653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,41661L,41662L,
8358841663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,41671L,41672L,
8358941673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,41681L,41682L,
8359041683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,41691L,41692L,
8359141693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,41701L,41702L,
8359241703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,41711L,41712L,
8359341713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,41721L,41722L,
8359441723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,41731L,41732L,
8359541733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,41741L,41742L,
8359641743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,41751L,41752L,
8359741753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,41761L,41762L,
8359841763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,41771L,41772L,
8359941773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,41781L,41782L,
8360041783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,41791L,41792L,
8360141793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,41801L,41802L,
8360241803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,41811L,41812L,
8360341813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,41821L,41822L,
8360441823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,41831L,41832L,
8360541833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,41841L,41842L,
8360641843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,41851L,41852L,
8360741853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,41861L,41862L,
8360841863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,41871L,41872L,
8360941873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,41881L,41882L,
8361041883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,41891L,41892L,
8361141893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,41901L,41902L,
8361241903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,41911L,41912L,
8361341913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,41921L,41922L,
8361441923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,41931L,41932L,
8361541933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,41941L,41942L,
8361641943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,41951L,41952L,
8361741953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,41961L,41962L,
8361841963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,41971L,41972L,
8361941973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,41981L,41982L,
8362041983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,41991L,41992L,
8362141993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,42001L,42002L,
8362242003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,42011L,42012L,
8362342013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,42021L,42022L,
8362442023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,42031L,42032L,
8362542033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,42041L,42042L,
8362642043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,42051L,42052L,
8362742053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,42061L,42062L,
8362842063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,42071L,42072L,
8362942073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,42081L,42082L,
8363042083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,42091L,42092L,
8363142093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,42101L,42102L,
8363242103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,42111L,42112L,
8363342113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,42121L,42122L,
8363442123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,42131L,42132L,
8363542133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,42141L,42142L,
8363642143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,42151L,42152L,
8363742153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,42161L,42162L,
8363842163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,42171L,42172L,
8363942173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,42181L,42182L,
8364042183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,42191L,42192L,
8364142193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,42201L,42202L,
8364242203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,42211L,42212L,
8364342213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,42221L,42222L,
8364442223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,42231L,42232L,
8364542233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,42241L,42242L,
8364642243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,42251L,42252L,
8364742253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,42261L,42262L,
8364842263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,42271L,42272L,
8364942273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,42281L,42282L,
8365042283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,42291L,42292L,
8365142293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,42301L,42302L,
8365242303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,42311L,42312L,
8365342313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,42321L,42322L,
8365442323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,42331L,42332L,
8365542333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,42341L,42342L,
8365642343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,42351L,42352L,
8365742353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,42361L,42362L,
8365842363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,42371L,42372L,
8365942373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,42381L,42382L,
8366042383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,42391L,42392L,
8366142393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,42401L,42402L,
8366242403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,42411L,42412L,
8366342413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,42421L,42422L,
8366442423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,42431L,42432L,
8366542433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,42441L,42442L,
8366642443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,42451L,42452L,
8366742453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,42461L,42462L,
8366842463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,42471L,42472L,
8366942473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,42481L,42482L,
8367042483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,42491L,42492L,
8367142493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,42501L,42502L,
8367242503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,42511L,42512L,
8367342513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,42521L,42522L,
8367442523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,42531L,42532L,
8367542533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,42541L,42542L,
8367642543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,42551L,42552L,
8367742553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,42560L,42562L,
8367842562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,42570L,42572L,
8367942572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,42580L,42582L,
8368042582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,42590L,42592L,
8368142592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,42600L,42602L,
8368242602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,42611L,42612L,
8368342613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,42621L,42622L,
8368442623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,42630L,42632L,
8368542632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,42640L,42642L,
8368642642L,42644L,42644L,42646L,42646L,42648L,42649L,42650L,42651L,42652L,
8368742653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,42661L,42662L,
8368842663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,42671L,42672L,
8368942673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,42681L,42682L,
8369042683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,42691L,42692L,
8369142693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,42701L,42702L,
8369242703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,42711L,42712L,
8369342713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,42721L,42722L,
8369442723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,42731L,42732L,
8369542733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,42741L,42742L,
8369642743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,42751L,42752L,
8369742753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,42761L,42762L,
8369842763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,42771L,42772L,
8369942773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,42781L,42782L,
8370042783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,42790L,42792L,
8370142792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,42801L,42802L,
8370242802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,42810L,42812L,
8370342812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,42820L,42822L,
8370442822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,42830L,42832L,
8370542832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,42840L,42842L,
8370642842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,42850L,42852L,
8370742852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,42860L,42862L,
8370842862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,42871L,42872L,
8370942873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,42880L,42882L,
8371042882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,42891L,42891L,
8371142893L,42894L,42895L,42896L,42896L,42898L,42899L,42900L,42901L,42902L,
8371242903L,42904L,42905L,42906L,42907L,42908L,42909L,42910L,42911L,42912L,
8371342912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,42920L,42922L,
8371442923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,42931L,42932L,
8371542933L,42934L,42935L,42936L,42937L,42938L,42939L,42940L,42941L,42942L,
8371642943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,42951L,42952L,
8371742953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,42961L,42962L,
8371842963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,42971L,42972L,
8371942973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,42981L,42982L,
8372042983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,42991L,42992L,
8372142993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,43001L,43002L,
8372243003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,43011L,43012L,
8372343013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,43021L,43022L,
8372443023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,43031L,43032L,
8372543033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,43041L,43042L,
8372643043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,43051L,43052L,
8372743053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,43061L,43062L,
8372843063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,43071L,43072L,
8372943073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,43081L,43082L,
8373043083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,43091L,43092L,
8373143093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,43101L,43102L,
8373243103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,43111L,43112L,
8373343113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,43121L,43122L,
8373443123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,43131L,43132L,
8373543133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,43141L,43142L,
8373643143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,43151L,43152L,
8373743153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,43161L,43162L,
8373843163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,43171L,43172L,
8373943173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,43181L,43182L,
8374043183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,43191L,43192L,
8374143193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,43201L,43202L,
8374243203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,43211L,43212L,
8374343213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,43221L,43222L,
8374443223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,43231L,43232L,
8374543233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,43241L,43242L,
8374643243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,43251L,43252L,
8374743253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,43261L,43262L,
8374843263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,43271L,43272L,
8374943273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,43281L,43282L,
8375043283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,43291L,43292L,
8375143293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,43301L,43302L,
8375243303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,43311L,43312L,
8375343313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,43321L,43322L,
8375443323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,43331L,43332L,
8375543333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,43341L,43342L,
8375643343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,43351L,43352L,
8375743353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,43361L,43362L,
8375843363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,43371L,43372L,
8375943373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,43381L,43382L,
8376043383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,43391L,43392L,
8376143393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,43401L,43402L,
8376243403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,43411L,43412L,
8376343413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,43421L,43422L,
8376443423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,43431L,43432L,
8376543433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,43441L,43442L,
8376643443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,43451L,43452L,
8376743453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,43461L,43462L,
8376843463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,43471L,43472L,
8376943473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,43481L,43482L,
8377043483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,43491L,43492L,
8377143493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,43501L,43502L,
8377243503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,43511L,43512L,
8377343513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,43521L,43522L,
8377443523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,43531L,43532L,
8377543533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,43541L,43542L,
8377643543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,43551L,43552L,
8377743553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,43561L,43562L,
8377843563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,43571L,43572L,
8377943573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,43581L,43582L,
8378043583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,43591L,43592L,
8378143593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,43601L,43602L,
8378243603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,43611L,43612L,
8378343613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,43621L,43622L,
8378443623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,43631L,43632L,
8378543633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,43641L,43642L,
8378643643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,43651L,43652L,
8378743653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,43661L,43662L,
8378843663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,43671L,43672L,
8378943673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,43681L,43682L,
8379043683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,43691L,43692L,
8379143693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,43701L,43702L,
8379243703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,43711L,43712L,
8379343713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,43721L,43722L,
8379443723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,43731L,43732L,
8379543733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,43741L,43742L,
8379643743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,43751L,43752L,
8379743753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,43761L,43762L,
8379843763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,43771L,43772L,
8379943773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,43781L,43782L,
8380043783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,43791L,43792L,
8380143793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,43801L,43802L,
8380243803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,43811L,43812L,
8380343813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,43821L,43822L,
8380443823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,43831L,43832L,
8380543833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,43841L,43842L,
8380643843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,43851L,43852L,
8380743853L,43854L,43855L,43856L,43857L,43858L,43859L,43860L,43861L,43862L,
8380843863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,43871L,43872L,
8380943873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,43881L,43882L,
8381043883L,43884L,43885L,43886L,43887L,43888L,43889L,43890L,43891L,43892L,
8381143893L,43894L,43895L,43896L,43897L,43898L,43899L,43900L,43901L,43902L,
8381243903L,43904L,43905L,43906L,43907L,43908L,43909L,43910L,43911L,43912L,
8381343913L,43914L,43915L,43916L,43917L,43918L,43919L,43920L,43921L,43922L,
8381443923L,43924L,43925L,43926L,43927L,43928L,43929L,43930L,43931L,43932L,
8381543933L,43934L,43935L,43936L,43937L,43938L,43939L,43940L,43941L,43942L,
8381643943L,43944L,43945L,43946L,43947L,43948L,43949L,43950L,43951L,43952L,
8381743953L,43954L,43955L,43956L,43957L,43958L,43959L,43960L,43961L,43962L,
8381843963L,43964L,43965L,43966L,43967L,43968L,43969L,43970L,43971L,43972L,
8381943973L,43974L,43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,
8382043983L,43984L,43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,
8382143993L,43994L,43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,
8382244003L,44004L,44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,
8382344013L,44014L,44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,
8382444023L,44024L,44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,
8382544033L,44034L,44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,
8382644043L,44044L,44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,
8382744053L,44054L,44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,
8382844063L,44064L,44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,
8382944073L,44074L,44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,
8383044083L,44084L,44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,
8383144093L,44094L,44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,
8383244103L,44104L,44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,
8383344113L,44114L,44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,
8383444123L,44124L,44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,
8383544133L,44134L,44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,
8383644143L,44144L,44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,
8383744153L,44154L,44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,
8383844163L,44164L,44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,
8383944173L,44174L,44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,
8384044183L,44184L,44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,
8384144193L,44194L,44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,
8384244203L,44204L,44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,
8384344213L,44214L,44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,
8384444223L,44224L,44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,
8384544233L,44234L,44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,
8384644243L,44244L,44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,
8384744253L,44254L,44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,
8384844263L,44264L,44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,
8384944273L,44274L,44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,
8385044283L,44284L,44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,
8385144293L,44294L,44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,
8385244303L,44304L,44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,
8385344313L,44314L,44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,
8385444323L,44324L,44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,
8385544333L,44334L,44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,
8385644343L,44344L,44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,
8385744353L,44354L,44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,
8385844363L,44364L,44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,
8385944373L,44374L,44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,
8386044383L,44384L,44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,
8386144393L,44394L,44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,
8386244403L,44404L,44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,
8386344413L,44414L,44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,
8386444423L,44424L,44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,
8386544433L,44434L,44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,
8386644443L,44444L,44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,
8386744453L,44454L,44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,
8386844463L,44464L,44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,
8386944473L,44474L,44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,
8387044483L,44484L,44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,
8387144493L,44494L,44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,
8387244503L,44504L,44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,
8387344513L,44514L,44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,
8387444523L,44524L,44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,
8387544533L,44534L,44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,
8387644543L,44544L,44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,
8387744553L,44554L,44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,
8387844563L,44564L,44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,
8387944573L,44574L,44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,
8388044583L,44584L,44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,
8388144593L,44594L,44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,
8388244603L,44604L,44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,
8388344613L,44614L,44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,
8388444623L,44624L,44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,
8388544633L,44634L,44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,
8388644643L,44644L,44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,
8388744653L,44654L,44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,
8388844663L,44664L,44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,
8388944673L,44674L,44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,
8389044683L,44684L,44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,
8389144693L,44694L,44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,
8389244703L,44704L,44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,
8389344713L,44714L,44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,
8389444723L,44724L,44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,
8389544733L,44734L,44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,
8389644743L,44744L,44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,
8389744753L,44754L,44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,
8389844763L,44764L,44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,
8389944773L,44774L,44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,
8390044783L,44784L,44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,
8390144793L,44794L,44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,
8390244803L,44804L,44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,
8390344813L,44814L,44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,
8390444823L,44824L,44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,
8390544833L,44834L,44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,
8390644843L,44844L,44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,
8390744853L,44854L,44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,
8390844863L,44864L,44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,
8390944873L,44874L,44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,
8391044883L,44884L,44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,
8391144893L,44894L,44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,
8391244903L,44904L,44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,
8391344913L,44914L,44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,
8391444923L,44924L,44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,
8391544933L,44934L,44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,
8391644943L,44944L,44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,
8391744953L,44954L,44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,
8391844963L,44964L,44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,
8391944973L,44974L,44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,
8392044983L,44984L,44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,
8392144993L,44994L,44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,
8392245003L,45004L,45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,
8392345013L,45014L,45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,
8392445023L,45024L,45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,
8392545033L,45034L,45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,
8392645043L,45044L,45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,
8392745053L,45054L,45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,
8392845063L,45064L,45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,
8392945073L,45074L,45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,
8393045083L,45084L,45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,
8393145093L,45094L,45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,
8393245103L,45104L,45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,
8393345113L,45114L,45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,
8393445123L,45124L,45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,
8393545133L,45134L,45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,
8393645143L,45144L,45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,
8393745153L,45154L,45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,
8393845163L,45164L,45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,
8393945173L,45174L,45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,
8394045183L,45184L,45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,
8394145193L,45194L,45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,
8394245203L,45204L,45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,
8394345213L,45214L,45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,
8394445223L,45224L,45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,
8394545233L,45234L,45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,
8394645243L,45244L,45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,
8394745253L,45254L,45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,
8394845263L,45264L,45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,
8394945273L,45274L,45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,
8395045283L,45284L,45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,
8395145293L,45294L,45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,
8395245303L,45304L,45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,
8395345313L,45314L,45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,
8395445323L,45324L,45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,
8395545333L,45334L,45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,
8395645343L,45344L,45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,
8395745353L,45354L,45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,
8395845363L,45364L,45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,
8395945373L,45374L,45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,
8396045383L,45384L,45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,
8396145393L,45394L,45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,
8396245403L,45404L,45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,
8396345413L,45414L,45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,
8396445423L,45424L,45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,
8396545433L,45434L,45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,
8396645443L,45444L,45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,
8396745453L,45454L,45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,
8396845463L,45464L,45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,
8396945473L,45474L,45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,
8397045483L,45484L,45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,
8397145493L,45494L,45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,
8397245503L,45504L,45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,
8397345513L,45514L,45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,
8397445523L,45524L,45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,
8397545533L,45534L,45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,
8397645543L,45544L,45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,
8397745553L,45554L,45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,
8397845563L,45564L,45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,
8397945573L,45574L,45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,
8398045583L,45584L,45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,
8398145593L,45594L,45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,
8398245603L,45604L,45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,
8398345613L,45614L,45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,
8398445623L,45624L,45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,
8398545633L,45634L,45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,
8398645643L,45644L,45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,
8398745653L,45654L,45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,
8398845663L,45664L,45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,
8398945673L,45674L,45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,
8399045683L,45684L,45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,
8399145693L,45694L,45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,
8399245703L,45704L,45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,
8399345713L,45714L,45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,
8399445723L,45724L,45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,
8399545733L,45734L,45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,
8399645743L,45744L,45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,
8399745753L,45754L,45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,
8399845763L,45764L,45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,
8399945773L,45774L,45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,
8400045783L,45784L,45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,
8400145793L,45794L,45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,
8400245803L,45804L,45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,
8400345813L,45814L,45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,
8400445823L,45824L,45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,
8400545833L,45834L,45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,
8400645843L,45844L,45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,
8400745853L,45854L,45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,
8400845863L,45864L,45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,
8400945873L,45874L,45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,
8401045883L,45884L,45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,
8401145893L,45894L,45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,
8401245903L,45904L,45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,
8401345913L,45914L,45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,
8401445923L,45924L,45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,
8401545933L,45934L,45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,
8401645943L,45944L,45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,
8401745953L,45954L,45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,
8401845963L,45964L,45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,
8401945973L,45974L,45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,
8402045983L,45984L,45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,
8402145993L,45994L,45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,
8402246003L,46004L,46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,
8402346013L,46014L,46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,
8402446023L,46024L,46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,
8402546033L,46034L,46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,
8402646043L,46044L,46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,
8402746053L,46054L,46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,
8402846063L,46064L,46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,
8402946073L,46074L,46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,
8403046083L,46084L,46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,
8403146093L,46094L,46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,
8403246103L,46104L,46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,
8403346113L,46114L,46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,
8403446123L,46124L,46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,
8403546133L,46134L,46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,
8403646143L,46144L,46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,
8403746153L,46154L,46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,
8403846163L,46164L,46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,
8403946173L,46174L,46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,
8404046183L,46184L,46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,
8404146193L,46194L,46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,
8404246203L,46204L,46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,
8404346213L,46214L,46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,
8404446223L,46224L,46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,
8404546233L,46234L,46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,
8404646243L,46244L,46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,
8404746253L,46254L,46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,
8404846263L,46264L,46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,
8404946273L,46274L,46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,
8405046283L,46284L,46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,
8405146293L,46294L,46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,
8405246303L,46304L,46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,
8405346313L,46314L,46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,
8405446323L,46324L,46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,
8405546333L,46334L,46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,
8405646343L,46344L,46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,
8405746353L,46354L,46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,
8405846363L,46364L,46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,
8405946373L,46374L,46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,
8406046383L,46384L,46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,
8406146393L,46394L,46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,
8406246403L,46404L,46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,
8406346413L,46414L,46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,
8406446423L,46424L,46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,
8406546433L,46434L,46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,
8406646443L,46444L,46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,
8406746453L,46454L,46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,
8406846463L,46464L,46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,
8406946473L,46474L,46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,
8407046483L,46484L,46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,
8407146493L,46494L,46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,
8407246503L,46504L,46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,
8407346513L,46514L,46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,
8407446523L,46524L,46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,
8407546533L,46534L,46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,
8407646543L,46544L,46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,
8407746553L,46554L,46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,
8407846563L,46564L,46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,
8407946573L,46574L,46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,
8408046583L,46584L,46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,
8408146593L,46594L,46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,
8408246603L,46604L,46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,
8408346613L,46614L,46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,
8408446623L,46624L,46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,
8408546633L,46634L,46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,
8408646643L,46644L,46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,
8408746653L,46654L,46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,
8408846663L,46664L,46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,
8408946673L,46674L,46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,
8409046683L,46684L,46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,
8409146693L,46694L,46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,
8409246703L,46704L,46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,
8409346713L,46714L,46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,
8409446723L,46724L,46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,
8409546733L,46734L,46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,
8409646743L,46744L,46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,
8409746753L,46754L,46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,
8409846763L,46764L,46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,
8409946773L,46774L,46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,
8410046783L,46784L,46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,
8410146793L,46794L,46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,
8410246803L,46804L,46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,
8410346813L,46814L,46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,
8410446823L,46824L,46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,
8410546833L,46834L,46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,
8410646843L,46844L,46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,
8410746853L,46854L,46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,
8410846863L,46864L,46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,
8410946873L,46874L,46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,
8411046883L,46884L,46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,
8411146893L,46894L,46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,
8411246903L,46904L,46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,
8411346913L,46914L,46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,
8411446923L,46924L,46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,
8411546933L,46934L,46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,
8411646943L,46944L,46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,
8411746953L,46954L,46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,
8411846963L,46964L,46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,
8411946973L,46974L,46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,
8412046983L,46984L,46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,
8412146993L,46994L,46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,
8412247003L,47004L,47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,
8412347013L,47014L,47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,
8412447023L,47024L,47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,
8412547033L,47034L,47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,
8412647043L,47044L,47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,
8412747053L,47054L,47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,
8412847063L,47064L,47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,
8412947073L,47074L,47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,
8413047083L,47084L,47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,
8413147093L,47094L,47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,
8413247103L,47104L,47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,
8413347113L,47114L,47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,
8413447123L,47124L,47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,
8413547133L,47134L,47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,
8413647143L,47144L,47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,
8413747153L,47154L,47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,
8413847163L,47164L,47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,
8413947173L,47174L,47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,
8414047183L,47184L,47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,
8414147193L,47194L,47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,
8414247203L,47204L,47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,
8414347213L,47214L,47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,
8414447223L,47224L,47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,
8414547233L,47234L,47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,
8414647243L,47244L,47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,
8414747253L,47254L,47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,
8414847263L,47264L,47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,
8414947273L,47274L,47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,
8415047283L,47284L,47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,
8415147293L,47294L,47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,
8415247303L,47304L,47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,
8415347313L,47314L,47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,
8415447323L,47324L,47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,
8415547333L,47334L,47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,
8415647343L,47344L,47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,
8415747353L,47354L,47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,
8415847363L,47364L,47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,
8415947373L,47374L,47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,
8416047383L,47384L,47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,
8416147393L,47394L,47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,
8416247403L,47404L,47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,
8416347413L,47414L,47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,
8416447423L,47424L,47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,
8416547433L,47434L,47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,
8416647443L,47444L,47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,
8416747453L,47454L,47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,
8416847463L,47464L,47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,
8416947473L,47474L,47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,
8417047483L,47484L,47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,
8417147493L,47494L,47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,
8417247503L,47504L,47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,
8417347513L,47514L,47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,
8417447523L,47524L,47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,
8417547533L,47534L,47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,
8417647543L,47544L,47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,
8417747553L,47554L,47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,
8417847563L,47564L,47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,
8417947573L,47574L,47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,
8418047583L,47584L,47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,
8418147593L,47594L,47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,
8418247603L,47604L,47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,
8418347613L,47614L,47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,
8418447623L,47624L,47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,
8418547633L,47634L,47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,
8418647643L,47644L,47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,
8418747653L,47654L,47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,
8418847663L,47664L,47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,
8418947673L,47674L,47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,
8419047683L,47684L,47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,
8419147693L,47694L,47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,
8419247703L,47704L,47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,
8419347713L,47714L,47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,
8419447723L,47724L,47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,
8419547733L,47734L,47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,
8419647743L,47744L,47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,
8419747753L,47754L,47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,
8419847763L,47764L,47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,
8419947773L,47774L,47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,
8420047783L,47784L,47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,
8420147793L,47794L,47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,
8420247803L,47804L,47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,
8420347813L,47814L,47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,
8420447823L,47824L,47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,
8420547833L,47834L,47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,
8420647843L,47844L,47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,
8420747853L,47854L,47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,
8420847863L,47864L,47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,
8420947873L,47874L,47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,
8421047883L,47884L,47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,
8421147893L,47894L,47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,
8421247903L,47904L,47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,
8421347913L,47914L,47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,
8421447923L,47924L,47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,
8421547933L,47934L,47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,
8421647943L,47944L,47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,
8421747953L,47954L,47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,
8421847963L,47964L,47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,
8421947973L,47974L,47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,
8422047983L,47984L,47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,
8422147993L,47994L,47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,
8422248003L,48004L,48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,
8422348013L,48014L,48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,
8422448023L,48024L,48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,
8422548033L,48034L,48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,
8422648043L,48044L,48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,
8422748053L,48054L,48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,
8422848063L,48064L,48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,
8422948073L,48074L,48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,
8423048083L,48084L,48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,
8423148093L,48094L,48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,
8423248103L,48104L,48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,
8423348113L,48114L,48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,
8423448123L,48124L,48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,
8423548133L,48134L,48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,
8423648143L,48144L,48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,
8423748153L,48154L,48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,
8423848163L,48164L,48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,
8423948173L,48174L,48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,
8424048183L,48184L,48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,
8424148193L,48194L,48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,
8424248203L,48204L,48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,
8424348213L,48214L,48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,
8424448223L,48224L,48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,
8424548233L,48234L,48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,
8424648243L,48244L,48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,
8424748253L,48254L,48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,
8424848263L,48264L,48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,
8424948273L,48274L,48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,
8425048283L,48284L,48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,
8425148293L,48294L,48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,
8425248303L,48304L,48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,
8425348313L,48314L,48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,
8425448323L,48324L,48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,
8425548333L,48334L,48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,
8425648343L,48344L,48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,
8425748353L,48354L,48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,
8425848363L,48364L,48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,
8425948373L,48374L,48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,
8426048383L,48384L,48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,
8426148393L,48394L,48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,
8426248403L,48404L,48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,
8426348413L,48414L,48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,
8426448423L,48424L,48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,
8426548433L,48434L,48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,
8426648443L,48444L,48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,
8426748453L,48454L,48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,
8426848463L,48464L,48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,
8426948473L,48474L,48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,
8427048483L,48484L,48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,
8427148493L,48494L,48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,
8427248503L,48504L,48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,
8427348513L,48514L,48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,
8427448523L,48524L,48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,
8427548533L,48534L,48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,
8427648543L,48544L,48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,
8427748553L,48554L,48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,
8427848563L,48564L,48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,
8427948573L,48574L,48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,
8428048583L,48584L,48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,
8428148593L,48594L,48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,
8428248603L,48604L,48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,
8428348613L,48614L,48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,
8428448623L,48624L,48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,
8428548633L,48634L,48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,
8428648643L,48644L,48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,
8428748653L,48654L,48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,
8428848663L,48664L,48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,
8428948673L,48674L,48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,
8429048683L,48684L,48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,
8429148693L,48694L,48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,
8429248703L,48704L,48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,
8429348713L,48714L,48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,
8429448723L,48724L,48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,
8429548733L,48734L,48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,
8429648743L,48744L,48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,
8429748753L,48754L,48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,
8429848763L,48764L,48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,
8429948773L,48774L,48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,
8430048783L,48784L,48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,
8430148793L,48794L,48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,
8430248803L,48804L,48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,
8430348813L,48814L,48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,
8430448823L,48824L,48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,
8430548833L,48834L,48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,
8430648843L,48844L,48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,
8430748853L,48854L,48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,
8430848863L,48864L,48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,
8430948873L,48874L,48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,
8431048883L,48884L,48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,
8431148893L,48894L,48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,
8431248903L,48904L,48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,
8431348913L,48914L,48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,
8431448923L,48924L,48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,
8431548933L,48934L,48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,
8431648943L,48944L,48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,
8431748953L,48954L,48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,
8431848963L,48964L,48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,
8431948973L,48974L,48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,
8432048983L,48984L,48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,
8432148993L,48994L,48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,
8432249003L,49004L,49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,
8432349013L,49014L,49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,
8432449023L,49024L,49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,
8432549033L,49034L,49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,
8432649043L,49044L,49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,
8432749053L,49054L,49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,
8432849063L,49064L,49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,
8432949073L,49074L,49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,
8433049083L,49084L,49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,
8433149093L,49094L,49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,
8433249103L,49104L,49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,
8433349113L,49114L,49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,
8433449123L,49124L,49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,
8433549133L,49134L,49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,
8433649143L,49144L,49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,
8433749153L,49154L,49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,
8433849163L,49164L,49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,
8433949173L,49174L,49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,
8434049183L,49184L,49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,
8434149193L,49194L,49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,
8434249203L,49204L,49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,
8434349213L,49214L,49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,
8434449223L,49224L,49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,
8434549233L,49234L,49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,
8434649243L,49244L,49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,
8434749253L,49254L,49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,
8434849263L,49264L,49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,
8434949273L,49274L,49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,
8435049283L,49284L,49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,
8435149293L,49294L,49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,
8435249303L,49304L,49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,
8435349313L,49314L,49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,
8435449323L,49324L,49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,
8435549333L,49334L,49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,
8435649343L,49344L,49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,
8435749353L,49354L,49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,
8435849363L,49364L,49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,
8435949373L,49374L,49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,
8436049383L,49384L,49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,
8436149393L,49394L,49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,
8436249403L,49404L,49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,
8436349413L,49414L,49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,
8436449423L,49424L,49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,
8436549433L,49434L,49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,
8436649443L,49444L,49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,
8436749453L,49454L,49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,
8436849463L,49464L,49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,
8436949473L,49474L,49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,
8437049483L,49484L,49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,
8437149493L,49494L,49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,
8437249503L,49504L,49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,
8437349513L,49514L,49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,
8437449523L,49524L,49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,
8437549533L,49534L,49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,
8437649543L,49544L,49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,
8437749553L,49554L,49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,
8437849563L,49564L,49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,
8437949573L,49574L,49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,
8438049583L,49584L,49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,
8438149593L,49594L,49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,
8438249603L,49604L,49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,
8438349613L,49614L,49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,
8438449623L,49624L,49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,
8438549633L,49634L,49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,
8438649643L,49644L,49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,
8438749653L,49654L,49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,
8438849663L,49664L,49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,
8438949673L,49674L,49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,
8439049683L,49684L,49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,
8439149693L,49694L,49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,
8439249703L,49704L,49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,
8439349713L,49714L,49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,
8439449723L,49724L,49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,
8439549733L,49734L,49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,
8439649743L,49744L,49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,
8439749753L,49754L,49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,
8439849763L,49764L,49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,
8439949773L,49774L,49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,
8440049783L,49784L,49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,
8440149793L,49794L,49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,
8440249803L,49804L,49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,
8440349813L,49814L,49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,
8440449823L,49824L,49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,
8440549833L,49834L,49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,
8440649843L,49844L,49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,
8440749853L,49854L,49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,
8440849863L,49864L,49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,
8440949873L,49874L,49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,
8441049883L,49884L,49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,
8441149893L,49894L,49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,
8441249903L,49904L,49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,
8441349913L,49914L,49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,
8441449923L,49924L,49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,
8441549933L,49934L,49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,
8441649943L,49944L,49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,
8441749953L,49954L,49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,
8441849963L,49964L,49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,
8441949973L,49974L,49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,
8442049983L,49984L,49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,
8442149993L,49994L,49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,
8442250003L,50004L,50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,
8442350013L,50014L,50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,
8442450023L,50024L,50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,
8442550033L,50034L,50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,
8442650043L,50044L,50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,
8442750053L,50054L,50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,
8442850063L,50064L,50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,
8442950073L,50074L,50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,
8443050083L,50084L,50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,
8443150093L,50094L,50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,
8443250103L,50104L,50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,
8443350113L,50114L,50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,
8443450123L,50124L,50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,
8443550133L,50134L,50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,
8443650143L,50144L,50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,
8443750153L,50154L,50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,
8443850163L,50164L,50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,
8443950173L,50174L,50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,
8444050183L,50184L,50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,
8444150193L,50194L,50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,
8444250203L,50204L,50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,
8444350213L,50214L,50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,
8444450223L,50224L,50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,
8444550233L,50234L,50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,
8444650243L,50244L,50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,
8444750253L,50254L,50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,
8444850263L,50264L,50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,
8444950273L,50274L,50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,
8445050283L,50284L,50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,
8445150293L,50294L,50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,
8445250303L,50304L,50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,
8445350313L,50314L,50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,
8445450323L,50324L,50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,
8445550333L,50334L,50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,
8445650343L,50344L,50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,
8445750353L,50354L,50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,
8445850363L,50364L,50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,
8445950373L,50374L,50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,
8446050383L,50384L,50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,
8446150393L,50394L,50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,
8446250403L,50404L,50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,
8446350413L,50414L,50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,
8446450423L,50424L,50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,
8446550433L,50434L,50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,
8446650443L,50444L,50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,
8446750453L,50454L,50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,
8446850463L,50464L,50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,
8446950473L,50474L,50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,
8447050483L,50484L,50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,
8447150493L,50494L,50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,
8447250503L,50504L,50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,
8447350513L,50514L,50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,
8447450523L,50524L,50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,
8447550533L,50534L,50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,
8447650543L,50544L,50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,
8447750553L,50554L,50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,
8447850563L,50564L,50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,
8447950573L,50574L,50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,
8448050583L,50584L,50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,
8448150593L,50594L,50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,
8448250603L,50604L,50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,
8448350613L,50614L,50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,
8448450623L,50624L,50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,
8448550633L,50634L,50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,
8448650643L,50644L,50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,
8448750653L,50654L,50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,
8448850663L,50664L,50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,
8448950673L,50674L,50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,
8449050683L,50684L,50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,
8449150693L,50694L,50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,
8449250703L,50704L,50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,
8449350713L,50714L,50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,
8449450723L,50724L,50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,
8449550733L,50734L,50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,
8449650743L,50744L,50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,
8449750753L,50754L,50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,
8449850763L,50764L,50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,
8449950773L,50774L,50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,
8450050783L,50784L,50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,
8450150793L,50794L,50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,
8450250803L,50804L,50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,
8450350813L,50814L,50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,
8450450823L,50824L,50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,
8450550833L,50834L,50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,
8450650843L,50844L,50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,
8450750853L,50854L,50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,
8450850863L,50864L,50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,
8450950873L,50874L,50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,
8451050883L,50884L,50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,
8451150893L,50894L,50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,
8451250903L,50904L,50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,
8451350913L,50914L,50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,
8451450923L,50924L,50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,
8451550933L,50934L,50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,
8451650943L,50944L,50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,
8451750953L,50954L,50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,
8451850963L,50964L,50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,
8451950973L,50974L,50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,
8452050983L,50984L,50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,
8452150993L,50994L,50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,
8452251003L,51004L,51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,
8452351013L,51014L,51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,
8452451023L,51024L,51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,
8452551033L,51034L,51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,
8452651043L,51044L,51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,
8452751053L,51054L,51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,
8452851063L,51064L,51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,
8452951073L,51074L,51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,
8453051083L,51084L,51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,
8453151093L,51094L,51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,
8453251103L,51104L,51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,
8453351113L,51114L,51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,
8453451123L,51124L,51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,
8453551133L,51134L,51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,
8453651143L,51144L,51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,
8453751153L,51154L,51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,
8453851163L,51164L,51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,
8453951173L,51174L,51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,
8454051183L,51184L,51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,
8454151193L,51194L,51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,
8454251203L,51204L,51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,
8454351213L,51214L,51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,
8454451223L,51224L,51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,
8454551233L,51234L,51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,
8454651243L,51244L,51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,
8454751253L,51254L,51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,
8454851263L,51264L,51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,
8454951273L,51274L,51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,
8455051283L,51284L,51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,
8455151293L,51294L,51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,
8455251303L,51304L,51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,
8455351313L,51314L,51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,
8455451323L,51324L,51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,
8455551333L,51334L,51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,
8455651343L,51344L,51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,
8455751353L,51354L,51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,
8455851363L,51364L,51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,
8455951373L,51374L,51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,
8456051383L,51384L,51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,
8456151393L,51394L,51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,
8456251403L,51404L,51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,
8456351413L,51414L,51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,
8456451423L,51424L,51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,
8456551433L,51434L,51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,
8456651443L,51444L,51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,
8456751453L,51454L,51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,
8456851463L,51464L,51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,
8456951473L,51474L,51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,
8457051483L,51484L,51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,
8457151493L,51494L,51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,
8457251503L,51504L,51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,
8457351513L,51514L,51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,
8457451523L,51524L,51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,
8457551533L,51534L,51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,
8457651543L,51544L,51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,
8457751553L,51554L,51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,
8457851563L,51564L,51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,
8457951573L,51574L,51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,
8458051583L,51584L,51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,
8458151593L,51594L,51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,
8458251603L,51604L,51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,
8458351613L,51614L,51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,
8458451623L,51624L,51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,
8458551633L,51634L,51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,
8458651643L,51644L,51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,
8458751653L,51654L,51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,
8458851663L,51664L,51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,
8458951673L,51674L,51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,
8459051683L,51684L,51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,
8459151693L,51694L,51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,
8459251703L,51704L,51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,
8459351713L,51714L,51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,
8459451723L,51724L,51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,
8459551733L,51734L,51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,
8459651743L,51744L,51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,
8459751753L,51754L,51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,
8459851763L,51764L,51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,
8459951773L,51774L,51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,
8460051783L,51784L,51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,
8460151793L,51794L,51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,
8460251803L,51804L,51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,
8460351813L,51814L,51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,
8460451823L,51824L,51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,
8460551833L,51834L,51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,
8460651843L,51844L,51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,
8460751853L,51854L,51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,
8460851863L,51864L,51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,
8460951873L,51874L,51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,
8461051883L,51884L,51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,
8461151893L,51894L,51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,
8461251903L,51904L,51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,
8461351913L,51914L,51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,
8461451923L,51924L,51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,
8461551933L,51934L,51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,
8461651943L,51944L,51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,
8461751953L,51954L,51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,
8461851963L,51964L,51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,
8461951973L,51974L,51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,
8462051983L,51984L,51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,
8462151993L,51994L,51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,
8462252003L,52004L,52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,
8462352013L,52014L,52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,
8462452023L,52024L,52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,
8462552033L,52034L,52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,
8462652043L,52044L,52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,
8462752053L,52054L,52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,
8462852063L,52064L,52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,
8462952073L,52074L,52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,
8463052083L,52084L,52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,
8463152093L,52094L,52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,
8463252103L,52104L,52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,
8463352113L,52114L,52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,
8463452123L,52124L,52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,
8463552133L,52134L,52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,
8463652143L,52144L,52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,
8463752153L,52154L,52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,
8463852163L,52164L,52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,
8463952173L,52174L,52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,
8464052183L,52184L,52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,
8464152193L,52194L,52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,
8464252203L,52204L,52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,
8464352213L,52214L,52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,
8464452223L,52224L,52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,
8464552233L,52234L,52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,
8464652243L,52244L,52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,
8464752253L,52254L,52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,
8464852263L,52264L,52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,
8464952273L,52274L,52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,
8465052283L,52284L,52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,
8465152293L,52294L,52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,
8465252303L,52304L,52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,
8465352313L,52314L,52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,
8465452323L,52324L,52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,
8465552333L,52334L,52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,
8465652343L,52344L,52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,
8465752353L,52354L,52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,
8465852363L,52364L,52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,
8465952373L,52374L,52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,
8466052383L,52384L,52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,
8466152393L,52394L,52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,
8466252403L,52404L,52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,
8466352413L,52414L,52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,
8466452423L,52424L,52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,
8466552433L,52434L,52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,
8466652443L,52444L,52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,
8466752453L,52454L,52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,
8466852463L,52464L,52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,
8466952473L,52474L,52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,
8467052483L,52484L,52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,
8467152493L,52494L,52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,
8467252503L,52504L,52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,
8467352513L,52514L,52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,
8467452523L,52524L,52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,
8467552533L,52534L,52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,
8467652543L,52544L,52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,
8467752553L,52554L,52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,
8467852563L,52564L,52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,
8467952573L,52574L,52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,
8468052583L,52584L,52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,
8468152593L,52594L,52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,
8468252603L,52604L,52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,
8468352613L,52614L,52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,
8468452623L,52624L,52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,
8468552633L,52634L,52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,
8468652643L,52644L,52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,
8468752653L,52654L,52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,
8468852663L,52664L,52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,
8468952673L,52674L,52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,
8469052683L,52684L,52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,
8469152693L,52694L,52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,
8469252703L,52704L,52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,
8469352713L,52714L,52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,
8469452723L,52724L,52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,
8469552733L,52734L,52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,
8469652743L,52744L,52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,
8469752753L,52754L,52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,
8469852763L,52764L,52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,
8469952773L,52774L,52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,
8470052783L,52784L,52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,
8470152793L,52794L,52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,
8470252803L,52804L,52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,
8470352813L,52814L,52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,
8470452823L,52824L,52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,
8470552833L,52834L,52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,
8470652843L,52844L,52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,
8470752853L,52854L,52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,
8470852863L,52864L,52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,
8470952873L,52874L,52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,
8471052883L,52884L,52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,
8471152893L,52894L,52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,
8471252903L,52904L,52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,
8471352913L,52914L,52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,
8471452923L,52924L,52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,
8471552933L,52934L,52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,
8471652943L,52944L,52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,
8471752953L,52954L,52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,
8471852963L,52964L,52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,
8471952973L,52974L,52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,
8472052983L,52984L,52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,
8472152993L,52994L,52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,
8472253003L,53004L,53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,
8472353013L,53014L,53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,
8472453023L,53024L,53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,
8472553033L,53034L,53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,
8472653043L,53044L,53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,
8472753053L,53054L,53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,
8472853063L,53064L,53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,
8472953073L,53074L,53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,
8473053083L,53084L,53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,
8473153093L,53094L,53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,
8473253103L,53104L,53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,
8473353113L,53114L,53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,
8473453123L,53124L,53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,
8473553133L,53134L,53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,
8473653143L,53144L,53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,
8473753153L,53154L,53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,
8473853163L,53164L,53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,
8473953173L,53174L,53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,
8474053183L,53184L,53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,
8474153193L,53194L,53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,
8474253203L,53204L,53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,
8474353213L,53214L,53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,
8474453223L,53224L,53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,
8474553233L,53234L,53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,
8474653243L,53244L,53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,
8474753253L,53254L,53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,
8474853263L,53264L,53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,
8474953273L,53274L,53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,
8475053283L,53284L,53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,
8475153293L,53294L,53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,
8475253303L,53304L,53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,
8475353313L,53314L,53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,
8475453323L,53324L,53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,
8475553333L,53334L,53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,
8475653343L,53344L,53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,
8475753353L,53354L,53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,
8475853363L,53364L,53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,
8475953373L,53374L,53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,
8476053383L,53384L,53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,
8476153393L,53394L,53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,
8476253403L,53404L,53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,
8476353413L,53414L,53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,
8476453423L,53424L,53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,
8476553433L,53434L,53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,
8476653443L,53444L,53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,
8476753453L,53454L,53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,
8476853463L,53464L,53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,
8476953473L,53474L,53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,
8477053483L,53484L,53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,
8477153493L,53494L,53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,
8477253503L,53504L,53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,
8477353513L,53514L,53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,
8477453523L,53524L,53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,
8477553533L,53534L,53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,
8477653543L,53544L,53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,
8477753553L,53554L,53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,
8477853563L,53564L,53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,
8477953573L,53574L,53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,
8478053583L,53584L,53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,
8478153593L,53594L,53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,
8478253603L,53604L,53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,
8478353613L,53614L,53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,
8478453623L,53624L,53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,
8478553633L,53634L,53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,
8478653643L,53644L,53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,
8478753653L,53654L,53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,
8478853663L,53664L,53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,
8478953673L,53674L,53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,
8479053683L,53684L,53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,
8479153693L,53694L,53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,
8479253703L,53704L,53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,
8479353713L,53714L,53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,
8479453723L,53724L,53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,
8479553733L,53734L,53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,
8479653743L,53744L,53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,
8479753753L,53754L,53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,
8479853763L,53764L,53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,
8479953773L,53774L,53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,
8480053783L,53784L,53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,
8480153793L,53794L,53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,
8480253803L,53804L,53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,
8480353813L,53814L,53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,
8480453823L,53824L,53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,
8480553833L,53834L,53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,
8480653843L,53844L,53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,
8480753853L,53854L,53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,
8480853863L,53864L,53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,
8480953873L,53874L,53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,
8481053883L,53884L,53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,
8481153893L,53894L,53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,
8481253903L,53904L,53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,
8481353913L,53914L,53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,
8481453923L,53924L,53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,
8481553933L,53934L,53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,
8481653943L,53944L,53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,
8481753953L,53954L,53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,
8481853963L,53964L,53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,
8481953973L,53974L,53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,
8482053983L,53984L,53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,
8482153993L,53994L,53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,
8482254003L,54004L,54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,
8482354013L,54014L,54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,
8482454023L,54024L,54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,
8482554033L,54034L,54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,
8482654043L,54044L,54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,
8482754053L,54054L,54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,
8482854063L,54064L,54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,
8482954073L,54074L,54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,
8483054083L,54084L,54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,
8483154093L,54094L,54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,
8483254103L,54104L,54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,
8483354113L,54114L,54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,
8483454123L,54124L,54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,
8483554133L,54134L,54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,
8483654143L,54144L,54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,
8483754153L,54154L,54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,
8483854163L,54164L,54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,
8483954173L,54174L,54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,
8484054183L,54184L,54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,
8484154193L,54194L,54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,
8484254203L,54204L,54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,
8484354213L,54214L,54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,
8484454223L,54224L,54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,
8484554233L,54234L,54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,
8484654243L,54244L,54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,
8484754253L,54254L,54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,
8484854263L,54264L,54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,
8484954273L,54274L,54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,
8485054283L,54284L,54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,
8485154293L,54294L,54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,
8485254303L,54304L,54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,
8485354313L,54314L,54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,
8485454323L,54324L,54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,
8485554333L,54334L,54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,
8485654343L,54344L,54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,
8485754353L,54354L,54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,
8485854363L,54364L,54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,
8485954373L,54374L,54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,
8486054383L,54384L,54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,
8486154393L,54394L,54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,
8486254403L,54404L,54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,
8486354413L,54414L,54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,
8486454423L,54424L,54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,
8486554433L,54434L,54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,
8486654443L,54444L,54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,
8486754453L,54454L,54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,
8486854463L,54464L,54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,
8486954473L,54474L,54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,
8487054483L,54484L,54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,
8487154493L,54494L,54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,
8487254503L,54504L,54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,
8487354513L,54514L,54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,
8487454523L,54524L,54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,
8487554533L,54534L,54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,
8487654543L,54544L,54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,
8487754553L,54554L,54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,
8487854563L,54564L,54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,
8487954573L,54574L,54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,
8488054583L,54584L,54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,
8488154593L,54594L,54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,
8488254603L,54604L,54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,
8488354613L,54614L,54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,
8488454623L,54624L,54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,
8488554633L,54634L,54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,
8488654643L,54644L,54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,
8488754653L,54654L,54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,
8488854663L,54664L,54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,
8488954673L,54674L,54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,
8489054683L,54684L,54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,
8489154693L,54694L,54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,
8489254703L,54704L,54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,
8489354713L,54714L,54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,
8489454723L,54724L,54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,
8489554733L,54734L,54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,
8489654743L,54744L,54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,
8489754753L,54754L,54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,
8489854763L,54764L,54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,
8489954773L,54774L,54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,
8490054783L,54784L,54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,
8490154793L,54794L,54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,
8490254803L,54804L,54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,
8490354813L,54814L,54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,
8490454823L,54824L,54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,
8490554833L,54834L,54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,
8490654843L,54844L,54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,
8490754853L,54854L,54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,
8490854863L,54864L,54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,
8490954873L,54874L,54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,
8491054883L,54884L,54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,
8491154893L,54894L,54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,
8491254903L,54904L,54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,
8491354913L,54914L,54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,
8491454923L,54924L,54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,
8491554933L,54934L,54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,
8491654943L,54944L,54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,
8491754953L,54954L,54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,
8491854963L,54964L,54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,
8491954973L,54974L,54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,
8492054983L,54984L,54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,
8492154993L,54994L,54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,
8492255003L,55004L,55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,
8492355013L,55014L,55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,
8492455023L,55024L,55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,
8492555033L,55034L,55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,
8492655043L,55044L,55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,
8492755053L,55054L,55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,
8492855063L,55064L,55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,
8492955073L,55074L,55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,
8493055083L,55084L,55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,
8493155093L,55094L,55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,
8493255103L,55104L,55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,
8493355113L,55114L,55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,
8493455123L,55124L,55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,
8493555133L,55134L,55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,
8493655143L,55144L,55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,
8493755153L,55154L,55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,
8493855163L,55164L,55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,
8493955173L,55174L,55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,
8494055183L,55184L,55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,
8494155193L,55194L,55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,
8494255203L,55204L,55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,
8494355213L,55214L,55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,
8494455223L,55224L,55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,
8494555233L,55234L,55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,
8494655243L,55244L,55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,
8494755253L,55254L,55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,
8494855263L,55264L,55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,
8494955273L,55274L,55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,
8495055283L,55284L,55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,
8495155293L,55294L,55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,
8495255303L,55304L,55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,
8495355313L,55314L,55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,
8495455323L,55324L,55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,
8495555333L,55334L,55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,
8495655343L,55344L,55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,
8495755353L,55354L,55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,
8495855363L,55364L,55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,
8495955373L,55374L,55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,
8496055383L,55384L,55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,
8496155393L,55394L,55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,
8496255403L,55404L,55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,
8496355413L,55414L,55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,
8496455423L,55424L,55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,
8496555433L,55434L,55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,
8496655443L,55444L,55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,
8496755453L,55454L,55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,
8496855463L,55464L,55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,
8496955473L,55474L,55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,
8497055483L,55484L,55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,
8497155493L,55494L,55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,
8497255503L,55504L,55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,
8497355513L,55514L,55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,
8497455523L,55524L,55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,
8497555533L,55534L,55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,
8497655543L,55544L,55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,
8497755553L,55554L,55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,
8497855563L,55564L,55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,
8497955573L,55574L,55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,
8498055583L,55584L,55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,
8498155593L,55594L,55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,
8498255603L,55604L,55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,
8498355613L,55614L,55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,
8498455623L,55624L,55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,
8498555633L,55634L,55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,
8498655643L,55644L,55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,
8498755653L,55654L,55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,
8498855663L,55664L,55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,
8498955673L,55674L,55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,
8499055683L,55684L,55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,
8499155693L,55694L,55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,
8499255703L,55704L,55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,
8499355713L,55714L,55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,
8499455723L,55724L,55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,
8499555733L,55734L,55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,
8499655743L,55744L,55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,
8499755753L,55754L,55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,
8499855763L,55764L,55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,
8499955773L,55774L,55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,
8500055783L,55784L,55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,
8500155793L,55794L,55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,
8500255803L,55804L,55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,
8500355813L,55814L,55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,
8500455823L,55824L,55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,
8500555833L,55834L,55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,
8500655843L,55844L,55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,
8500755853L,55854L,55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,
8500855863L,55864L,55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,
8500955873L,55874L,55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,
8501055883L,55884L,55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,
8501155893L,55894L,55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,
8501255903L,55904L,55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,
8501355913L,55914L,55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,
8501455923L,55924L,55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,
8501555933L,55934L,55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,
8501655943L,55944L,55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,
8501755953L,55954L,55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,
8501855963L,55964L,55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,
8501955973L,55974L,55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,
8502055983L,55984L,55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,
8502155993L,55994L,55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,
8502256003L,56004L,56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,
8502356013L,56014L,56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,
8502456023L,56024L,56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,
8502556033L,56034L,56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,
8502656043L,56044L,56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,
8502756053L,56054L,56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,
8502856063L,56064L,56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,
8502956073L,56074L,56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,
8503056083L,56084L,56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,
8503156093L,56094L,56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,
8503256103L,56104L,56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,
8503356113L,56114L,56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,
8503456123L,56124L,56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,
8503556133L,56134L,56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,
8503656143L,56144L,56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,
8503756153L,56154L,56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,
8503856163L,56164L,56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,
8503956173L,56174L,56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,
8504056183L,56184L,56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,
8504156193L,56194L,56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,
8504256203L,56204L,56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,
8504356213L,56214L,56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,
8504456223L,56224L,56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,
8504556233L,56234L,56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,
8504656243L,56244L,56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,
8504756253L,56254L,56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,
8504856263L,56264L,56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,
8504956273L,56274L,56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,
8505056283L,56284L,56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,
8505156293L,56294L,56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,
8505256303L,56304L,56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,
8505356313L,56314L,56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,
8505456323L,56324L,56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,
8505556333L,56334L,56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,
8505656343L,56344L,56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,
8505756353L,56354L,56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,
8505856363L,56364L,56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,
8505956373L,56374L,56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,
8506056383L,56384L,56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,
8506156393L,56394L,56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,
8506256403L,56404L,56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,
8506356413L,56414L,56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,
8506456423L,56424L,56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,
8506556433L,56434L,56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,
8506656443L,56444L,56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,
8506756453L,56454L,56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,
8506856463L,56464L,56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,
8506956473L,56474L,56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,
8507056483L,56484L,56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,
8507156493L,56494L,56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,
8507256503L,56504L,56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,
8507356513L,56514L,56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,
8507456523L,56524L,56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,
8507556533L,56534L,56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,
8507656543L,56544L,56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,
8507756553L,56554L,56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,
8507856563L,56564L,56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,
8507956573L,56574L,56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,
8508056583L,56584L,56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,
8508156593L,56594L,56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,
8508256603L,56604L,56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,
8508356613L,56614L,56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,
8508456623L,56624L,56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,
8508556633L,56634L,56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,
8508656643L,56644L,56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,
8508756653L,56654L,56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,
8508856663L,56664L,56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,
8508956673L,56674L,56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,
8509056683L,56684L,56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,
8509156693L,56694L,56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,
8509256703L,56704L,56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,
8509356713L,56714L,56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,
8509456723L,56724L,56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,
8509556733L,56734L,56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,
8509656743L,56744L,56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,
8509756753L,56754L,56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,
8509856763L,56764L,56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,
8509956773L,56774L,56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,
8510056783L,56784L,56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,
8510156793L,56794L,56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,
8510256803L,56804L,56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,
8510356813L,56814L,56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,
8510456823L,56824L,56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,
8510556833L,56834L,56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,
8510656843L,56844L,56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,
8510756853L,56854L,56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,
8510856863L,56864L,56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,
8510956873L,56874L,56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,
8511056883L,56884L,56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,
8511156893L,56894L,56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,
8511256903L,56904L,56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,
8511356913L,56914L,56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,
8511456923L,56924L,56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,
8511556933L,56934L,56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,
8511656943L,56944L,56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,
8511756953L,56954L,56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,
8511856963L,56964L,56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,
8511956973L,56974L,56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,
8512056983L,56984L,56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,
8512156993L,56994L,56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,
8512257003L,57004L,57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,
8512357013L,57014L,57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,
8512457023L,57024L,57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,
8512557033L,57034L,57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,
8512657043L,57044L,57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,
8512757053L,57054L,57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,
8512857063L,57064L,57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,
8512957073L,57074L,57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,
8513057083L,57084L,57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,
8513157093L,57094L,57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,
8513257103L,57104L,57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,
8513357113L,57114L,57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,
8513457123L,57124L,57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,
8513557133L,57134L,57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,
8513657143L,57144L,57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,
8513757153L,57154L,57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,
8513857163L,57164L,57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,
8513957173L,57174L,57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,
8514057183L,57184L,57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,
8514157193L,57194L,57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,
8514257203L,57204L,57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,
8514357213L,57214L,57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,
8514457223L,57224L,57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,
8514557233L,57234L,57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,
8514657243L,57244L,57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,
8514757253L,57254L,57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,
8514857263L,57264L,57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,
8514957273L,57274L,57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,
8515057283L,57284L,57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,
8515157293L,57294L,57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,
8515257303L,57304L,57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,
8515357313L,57314L,57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,
8515457323L,57324L,57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,
8515557333L,57334L,57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,
8515657343L,57344L,57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,
8515757353L,57354L,57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,
8515857363L,57364L,57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,
8515957373L,57374L,57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,
8516057383L,57384L,57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,
8516157393L,57394L,57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,
8516257403L,57404L,57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,
8516357413L,57414L,57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,
8516457423L,57424L,57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,
8516557433L,57434L,57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,
8516657443L,57444L,57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,
8516757453L,57454L,57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,
8516857463L,57464L,57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,
8516957473L,57474L,57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,
8517057483L,57484L,57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,
8517157493L,57494L,57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,
8517257503L,57504L,57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,
8517357513L,57514L,57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,
8517457523L,57524L,57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,
8517557533L,57534L,57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,
8517657543L,57544L,57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,
8517757553L,57554L,57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,
8517857563L,57564L,57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,
8517957573L,57574L,57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,
8518057583L,57584L,57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,
8518157593L,57594L,57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,
8518257603L,57604L,57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,
8518357613L,57614L,57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,
8518457623L,57624L,57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,
8518557633L,57634L,57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,
8518657643L,57644L,57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,
8518757653L,57654L,57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,
8518857663L,57664L,57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,
8518957673L,57674L,57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,
8519057683L,57684L,57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,
8519157693L,57694L,57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,
8519257703L,57704L,57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,
8519357713L,57714L,57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,
8519457723L,57724L,57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,
8519557733L,57734L,57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,
8519657743L,57744L,57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,
8519757753L,57754L,57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,
8519857763L,57764L,57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,
8519957773L,57774L,57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,
8520057783L,57784L,57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,
8520157793L,57794L,57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,
8520257803L,57804L,57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,
8520357813L,57814L,57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,
8520457823L,57824L,57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,
8520557833L,57834L,57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,
8520657843L,57844L,57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,
8520757853L,57854L,57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,
8520857863L,57864L,57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,
8520957873L,57874L,57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,
8521057883L,57884L,57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,
8521157893L,57894L,57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,
8521257903L,57904L,57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,
8521357913L,57914L,57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,
8521457923L,57924L,57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,
8521557933L,57934L,57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,
8521657943L,57944L,57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,
8521757953L,57954L,57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,
8521857963L,57964L,57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,
8521957973L,57974L,57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,
8522057983L,57984L,57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,
8522157993L,57994L,57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,
8522258003L,58004L,58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,
8522358013L,58014L,58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,
8522458023L,58024L,58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,
8522558033L,58034L,58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,
8522658043L,58044L,58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,
8522758053L,58054L,58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,
8522858063L,58064L,58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,
8522958073L,58074L,58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,
8523058083L,58084L,58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,
8523158093L,58094L,58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,
8523258103L,58104L,58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,
8523358113L,58114L,58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,
8523458123L,58124L,58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,
8523558133L,58134L,58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,
8523658143L,58144L,58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,
8523758153L,58154L,58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,
8523858163L,58164L,58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,
8523958173L,58174L,58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,
8524058183L,58184L,58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,
8524158193L,58194L,58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,
8524258203L,58204L,58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,
8524358213L,58214L,58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,
8524458223L,58224L,58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,
8524558233L,58234L,58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,
8524658243L,58244L,58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,
8524758253L,58254L,58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,
8524858263L,58264L,58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,
8524958273L,58274L,58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,
8525058283L,58284L,58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,
8525158293L,58294L,58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,
8525258303L,58304L,58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,
8525358313L,58314L,58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,
8525458323L,58324L,58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,
8525558333L,58334L,58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,
8525658343L,58344L,58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,
8525758353L,58354L,58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,
8525858363L,58364L,58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,
8525958373L,58374L,58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,
8526058383L,58384L,58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,
8526158393L,58394L,58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,
8526258403L,58404L,58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,
8526358413L,58414L,58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,
8526458423L,58424L,58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,
8526558433L,58434L,58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,
8526658443L,58444L,58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,
8526758453L,58454L,58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,
8526858463L,58464L,58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,
8526958473L,58474L,58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,
8527058483L,58484L,58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,
8527158493L,58494L,58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,
8527258503L,58504L,58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,
8527358513L,58514L,58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,
8527458523L,58524L,58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,
8527558533L,58534L,58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,
8527658543L,58544L,58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,
8527758553L,58554L,58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,
8527858563L,58564L,58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,
8527958573L,58574L,58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,
8528058583L,58584L,58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,
8528158593L,58594L,58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,
8528258603L,58604L,58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,
8528358613L,58614L,58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,
8528458623L,58624L,58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,
8528558633L,58634L,58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,
8528658643L,58644L,58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,
8528758653L,58654L,58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,
8528858663L,58664L,58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,
8528958673L,58674L,58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,
8529058683L,58684L,58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,
8529158693L,58694L,58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,
8529258703L,58704L,58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,
8529358713L,58714L,58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,
8529458723L,58724L,58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,
8529558733L,58734L,58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,
8529658743L,58744L,58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,
8529758753L,58754L,58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,
8529858763L,58764L,58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,
8529958773L,58774L,58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,
8530058783L,58784L,58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,
8530158793L,58794L,58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,
8530258803L,58804L,58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,
8530358813L,58814L,58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,
8530458823L,58824L,58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,
8530558833L,58834L,58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,
8530658843L,58844L,58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,
8530758853L,58854L,58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,
8530858863L,58864L,58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,
8530958873L,58874L,58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,
8531058883L,58884L,58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,
8531158893L,58894L,58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,
8531258903L,58904L,58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,
8531358913L,58914L,58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,
8531458923L,58924L,58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,
8531558933L,58934L,58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,
8531658943L,58944L,58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,
8531758953L,58954L,58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,
8531858963L,58964L,58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,
8531958973L,58974L,58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,
8532058983L,58984L,58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,
8532158993L,58994L,58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,
8532259003L,59004L,59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,
8532359013L,59014L,59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,
8532459023L,59024L,59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,
8532559033L,59034L,59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,
8532659043L,59044L,59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,
8532759053L,59054L,59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,
8532859063L,59064L,59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,
8532959073L,59074L,59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,
8533059083L,59084L,59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,
8533159093L,59094L,59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,
8533259103L,59104L,59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,
8533359113L,59114L,59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,
8533459123L,59124L,59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,
8533559133L,59134L,59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,
8533659143L,59144L,59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,
8533759153L,59154L,59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,
8533859163L,59164L,59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,
8533959173L,59174L,59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,
8534059183L,59184L,59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,
8534159193L,59194L,59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,
8534259203L,59204L,59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,
8534359213L,59214L,59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,
8534459223L,59224L,59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,
8534559233L,59234L,59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,
8534659243L,59244L,59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,
8534759253L,59254L,59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,
8534859263L,59264L,59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,
8534959273L,59274L,59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,
8535059283L,59284L,59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,
8535159293L,59294L,59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,
8535259303L,59304L,59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,
8535359313L,59314L,59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,
8535459323L,59324L,59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,
8535559333L,59334L,59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,
8535659343L,59344L,59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,
8535759353L,59354L,59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,
8535859363L,59364L,59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,
8535959373L,59374L,59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,
8536059383L,59384L,59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,
8536159393L,59394L,59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,
8536259403L,59404L,59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,
8536359413L,59414L,59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,
8536459423L,59424L,59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,
8536559433L,59434L,59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,
8536659443L,59444L,59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,
8536759453L,59454L,59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,
8536859463L,59464L,59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,
8536959473L,59474L,59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,
8537059483L,59484L,59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,
8537159493L,59494L,59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,
8537259503L,59504L,59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,
8537359513L,59514L,59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,
8537459523L,59524L,59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,
8537559533L,59534L,59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,
8537659543L,59544L,59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,
8537759553L,59554L,59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,
8537859563L,59564L,59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,
8537959573L,59574L,59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,
8538059583L,59584L,59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,
8538159593L,59594L,59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,
8538259603L,59604L,59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,
8538359613L,59614L,59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,
8538459623L,59624L,59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,
8538559633L,59634L,59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,
8538659643L,59644L,59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,
8538759653L,59654L,59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,
8538859663L,59664L,59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,
8538959673L,59674L,59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,
8539059683L,59684L,59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,
8539159693L,59694L,59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,
8539259703L,59704L,59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,
8539359713L,59714L,59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,
8539459723L,59724L,59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,
8539559733L,59734L,59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,
8539659743L,59744L,59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,
8539759753L,59754L,59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,
8539859763L,59764L,59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,
8539959773L,59774L,59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,
8540059783L,59784L,59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,
8540159793L,59794L,59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,
8540259803L,59804L,59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,
8540359813L,59814L,59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,
8540459823L,59824L,59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,
8540559833L,59834L,59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,
8540659843L,59844L,59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,
8540759853L,59854L,59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,
8540859863L,59864L,59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,
8540959873L,59874L,59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,
8541059883L,59884L,59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,
8541159893L,59894L,59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,
8541259903L,59904L,59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,
8541359913L,59914L,59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,
8541459923L,59924L,59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,
8541559933L,59934L,59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,
8541659943L,59944L,59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,
8541759953L,59954L,59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,
8541859963L,59964L,59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,
8541959973L,59974L,59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,
8542059983L,59984L,59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,
8542159993L,59994L,59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,
8542260003L,60004L,60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,
8542360013L,60014L,60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,
8542460023L,60024L,60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,
8542560033L,60034L,60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,
8542660043L,60044L,60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,
8542760053L,60054L,60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,
8542860063L,60064L,60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,
8542960073L,60074L,60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,
8543060083L,60084L,60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,
8543160093L,60094L,60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,
8543260103L,60104L,60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,
8543360113L,60114L,60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,
8543460123L,60124L,60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,
8543560133L,60134L,60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,
8543660143L,60144L,60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,
8543760153L,60154L,60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,
8543860163L,60164L,60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,
8543960173L,60174L,60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,
8544060183L,60184L,60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,
8544160193L,60194L,60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,
8544260203L,60204L,60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,
8544360213L,60214L,60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,
8544460223L,60224L,60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,
8544560233L,60234L,60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,
8544660243L,60244L,60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,
8544760253L,60254L,60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,
8544860263L,60264L,60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,
8544960273L,60274L,60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,
8545060283L,60284L,60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,
8545160293L,60294L,60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,
8545260303L,60304L,60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,
8545360313L,60314L,60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,
8545460323L,60324L,60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,
8545560333L,60334L,60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,
8545660343L,60344L,60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,
8545760353L,60354L,60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,
8545860363L,60364L,60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,
8545960373L,60374L,60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,
8546060383L,60384L,60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,
8546160393L,60394L,60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,
8546260403L,60404L,60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,
8546360413L,60414L,60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,
8546460423L,60424L,60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,
8546560433L,60434L,60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,
8546660443L,60444L,60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,
8546760453L,60454L,60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,
8546860463L,60464L,60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,
8546960473L,60474L,60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,
8547060483L,60484L,60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,
8547160493L,60494L,60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,
8547260503L,60504L,60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,
8547360513L,60514L,60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,
8547460523L,60524L,60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,
8547560533L,60534L,60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,
8547660543L,60544L,60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,
8547760553L,60554L,60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,
8547860563L,60564L,60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,
8547960573L,60574L,60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,
8548060583L,60584L,60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,
8548160593L,60594L,60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,
8548260603L,60604L,60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,
8548360613L,60614L,60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,
8548460623L,60624L,60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,
8548560633L,60634L,60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,
8548660643L,60644L,60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,
8548760653L,60654L,60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,
8548860663L,60664L,60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,
8548960673L,60674L,60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,
8549060683L,60684L,60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,
8549160693L,60694L,60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,
8549260703L,60704L,60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,
8549360713L,60714L,60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,
8549460723L,60724L,60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,
8549560733L,60734L,60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,
8549660743L,60744L,60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,
8549760753L,60754L,60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,
8549860763L,60764L,60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,
8549960773L,60774L,60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,
8550060783L,60784L,60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,
8550160793L,60794L,60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,
8550260803L,60804L,60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,
8550360813L,60814L,60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,
8550460823L,60824L,60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,
8550560833L,60834L,60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,
8550660843L,60844L,60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,
8550760853L,60854L,60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,
8550860863L,60864L,60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,
8550960873L,60874L,60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,
8551060883L,60884L,60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,
8551160893L,60894L,60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,
8551260903L,60904L,60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,
8551360913L,60914L,60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,
8551460923L,60924L,60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,
8551560933L,60934L,60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,
8551660943L,60944L,60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,
8551760953L,60954L,60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,
8551860963L,60964L,60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,
8551960973L,60974L,60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,
8552060983L,60984L,60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,
8552160993L,60994L,60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,
8552261003L,61004L,61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,
8552361013L,61014L,61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,
8552461023L,61024L,61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,
8552561033L,61034L,61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,
8552661043L,61044L,61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,
8552761053L,61054L,61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,
8552861063L,61064L,61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,
8552961073L,61074L,61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,
8553061083L,61084L,61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,
8553161093L,61094L,61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,
8553261103L,61104L,61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,
8553361113L,61114L,61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,
8553461123L,61124L,61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,
8553561133L,61134L,61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,
8553661143L,61144L,61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,
8553761153L,61154L,61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,
8553861163L,61164L,61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,
8553961173L,61174L,61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,
8554061183L,61184L,61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,
8554161193L,61194L,61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,
8554261203L,61204L,61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,
8554361213L,61214L,61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,
8554461223L,61224L,61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,
8554561233L,61234L,61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,
8554661243L,61244L,61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,
8554761253L,61254L,61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,
8554861263L,61264L,61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,
8554961273L,61274L,61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,
8555061283L,61284L,61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,
8555161293L,61294L,61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,
8555261303L,61304L,61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,
8555361313L,61314L,61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,
8555461323L,61324L,61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,
8555561333L,61334L,61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,
8555661343L,61344L,61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,
8555761353L,61354L,61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,
8555861363L,61364L,61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,
8555961373L,61374L,61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,
8556061383L,61384L,61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,
8556161393L,61394L,61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,
8556261403L,61404L,61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,
8556361413L,61414L,61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,
8556461423L,61424L,61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,
8556561433L,61434L,61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,
8556661443L,61444L,61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,
8556761453L,61454L,61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,
8556861463L,61464L,61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,
8556961473L,61474L,61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,
8557061483L,61484L,61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,
8557161493L,61494L,61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,
8557261503L,61504L,61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,
8557361513L,61514L,61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,
8557461523L,61524L,61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,
8557561533L,61534L,61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,
8557661543L,61544L,61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,
8557761553L,61554L,61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,
8557861563L,61564L,61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,
8557961573L,61574L,61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,
8558061583L,61584L,61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,
8558161593L,61594L,61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,
8558261603L,61604L,61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,
8558361613L,61614L,61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,
8558461623L,61624L,61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,
8558561633L,61634L,61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,
8558661643L,61644L,61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,
8558761653L,61654L,61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,
8558861663L,61664L,61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,
8558961673L,61674L,61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,
8559061683L,61684L,61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,
8559161693L,61694L,61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,
8559261703L,61704L,61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,
8559361713L,61714L,61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,
8559461723L,61724L,61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,
8559561733L,61734L,61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,
8559661743L,61744L,61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,
8559761753L,61754L,61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,
8559861763L,61764L,61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,
8559961773L,61774L,61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,
8560061783L,61784L,61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,
8560161793L,61794L,61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,
8560261803L,61804L,61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,
8560361813L,61814L,61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,
8560461823L,61824L,61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,
8560561833L,61834L,61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,
8560661843L,61844L,61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,
8560761853L,61854L,61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,
8560861863L,61864L,61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,
8560961873L,61874L,61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,
8561061883L,61884L,61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,
8561161893L,61894L,61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,
8561261903L,61904L,61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,
8561361913L,61914L,61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,
8561461923L,61924L,61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,
8561561933L,61934L,61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,
8561661943L,61944L,61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,
8561761953L,61954L,61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,
8561861963L,61964L,61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,
8561961973L,61974L,61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,
8562061983L,61984L,61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,
8562161993L,61994L,61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,
8562262003L,62004L,62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,
8562362013L,62014L,62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,
8562462023L,62024L,62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,
8562562033L,62034L,62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,
8562662043L,62044L,62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,
8562762053L,62054L,62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,
8562862063L,62064L,62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,
8562962073L,62074L,62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,
8563062083L,62084L,62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,
8563162093L,62094L,62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,
8563262103L,62104L,62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,
8563362113L,62114L,62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,
8563462123L,62124L,62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,
8563562133L,62134L,62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,
8563662143L,62144L,62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,
8563762153L,62154L,62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,
8563862163L,62164L,62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,
8563962173L,62174L,62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,
8564062183L,62184L,62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,
8564162193L,62194L,62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,
8564262203L,62204L,62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,
8564362213L,62214L,62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,
8564462223L,62224L,62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,
8564562233L,62234L,62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,
8564662243L,62244L,62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,
8564762253L,62254L,62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,
8564862263L,62264L,62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,
8564962273L,62274L,62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,
8565062283L,62284L,62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,
8565162293L,62294L,62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,
8565262303L,62304L,62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,
8565362313L,62314L,62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,
8565462323L,62324L,62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,
8565562333L,62334L,62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,
8565662343L,62344L,62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,
8565762353L,62354L,62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,
8565862363L,62364L,62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,
8565962373L,62374L,62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,
8566062383L,62384L,62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,
8566162393L,62394L,62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,
8566262403L,62404L,62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,
8566362413L,62414L,62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,
8566462423L,62424L,62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,
8566562433L,62434L,62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,
8566662443L,62444L,62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,
8566762453L,62454L,62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,
8566862463L,62464L,62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,
8566962473L,62474L,62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,
8567062483L,62484L,62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,
8567162493L,62494L,62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,
8567262503L,62504L,62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,
8567362513L,62514L,62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,
8567462523L,62524L,62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,
8567562533L,62534L,62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,
8567662543L,62544L,62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,
8567762553L,62554L,62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,
8567862563L,62564L,62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,
8567962573L,62574L,62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,
8568062583L,62584L,62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,
8568162593L,62594L,62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,
8568262603L,62604L,62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,
8568362613L,62614L,62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,
8568462623L,62624L,62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,
8568562633L,62634L,62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,
8568662643L,62644L,62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,
8568762653L,62654L,62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,
8568862663L,62664L,62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,
8568962673L,62674L,62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,
8569062683L,62684L,62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,
8569162693L,62694L,62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,
8569262703L,62704L,62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,
8569362713L,62714L,62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,
8569462723L,62724L,62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,
8569562733L,62734L,62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,
8569662743L,62744L,62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,
8569762753L,62754L,62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,
8569862763L,62764L,62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,
8569962773L,62774L,62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,
8570062783L,62784L,62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,
8570162793L,62794L,62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,
8570262803L,62804L,62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,
8570362813L,62814L,62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,
8570462823L,62824L,62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,
8570562833L,62834L,62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,
8570662843L,62844L,62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,
8570762853L,62854L,62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,
8570862863L,62864L,62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,
8570962873L,62874L,62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,
8571062883L,62884L,62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,
8571162893L,62894L,62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,
8571262903L,62904L,62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,
8571362913L,62914L,62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,
8571462923L,62924L,62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,
8571562933L,62934L,62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,
8571662943L,62944L,62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,
8571762953L,62954L,62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,
8571862963L,62964L,62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,
8571962973L,62974L,62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,
8572062983L,62984L,62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,
8572162993L,62994L,62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,
8572263003L,63004L,63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,
8572363013L,63014L,63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,
8572463023L,63024L,63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,
8572563033L,63034L,63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,
8572663043L,63044L,63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,
8572763053L,63054L,63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,
8572863063L,63064L,63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,
8572963073L,63074L,63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,
8573063083L,63084L,63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,
8573163093L,63094L,63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,
8573263103L,63104L,63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,
8573363113L,63114L,63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,
8573463123L,63124L,63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,
8573563133L,63134L,63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,
8573663143L,63144L,63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,
8573763153L,63154L,63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,
8573863163L,63164L,63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,
8573963173L,63174L,63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,
8574063183L,63184L,63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,
8574163193L,63194L,63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,
8574263203L,63204L,63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,
8574363213L,63214L,63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,
8574463223L,63224L,63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,
8574563233L,63234L,63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,
8574663243L,63244L,63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,
8574763253L,63254L,63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,
8574863263L,63264L,63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,
8574963273L,63274L,63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,
8575063283L,63284L,63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,
8575163293L,63294L,63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,
8575263303L,63304L,63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,
8575363313L,63314L,63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,
8575463323L,63324L,63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,
8575563333L,63334L,63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,
8575663343L,63344L,63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,
8575763353L,63354L,63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,
8575863363L,63364L,63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,
8575963373L,63374L,63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,
8576063383L,63384L,63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,
8576163393L,63394L,63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,
8576263403L,63404L,63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,
8576363413L,63414L,63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,
8576463423L,63424L,63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,
8576563433L,63434L,63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,
8576663443L,63444L,63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,
8576763453L,63454L,63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,
8576863463L,63464L,63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,
8576963473L,63474L,63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,
8577063483L,63484L,63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,
8577163493L,63494L,63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,
8577263503L,63504L,63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,
8577363513L,63514L,63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,
8577463523L,63524L,63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,
8577563533L,63534L,63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,
8577663543L,63544L,63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,
8577763553L,63554L,63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,
8577863563L,63564L,63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,
8577963573L,63574L,63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,
8578063583L,63584L,63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,
8578163593L,63594L,63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,
8578263603L,63604L,63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,
8578363613L,63614L,63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,
8578463623L,63624L,63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,
8578563633L,63634L,63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,
8578663643L,63644L,63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,
8578763653L,63654L,63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,
8578863663L,63664L,63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,
8578963673L,63674L,63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,
8579063683L,63684L,63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,
8579163693L,63694L,63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,
8579263703L,63704L,63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,
8579363713L,63714L,63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,
8579463723L,63724L,63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,
8579563733L,63734L,63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,
8579663743L,63744L,63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,
8579763753L,63754L,63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,
8579863763L,63764L,63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,
8579963773L,63774L,63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,
8580063783L,63784L,63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,
8580163793L,63794L,63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,
8580263803L,63804L,63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,
8580363813L,63814L,63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,
8580463823L,63824L,63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,
8580563833L,63834L,63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,
8580663843L,63844L,63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,
8580763853L,63854L,63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,
8580863863L,63864L,63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,
8580963873L,63874L,63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,
8581063883L,63884L,63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,
8581163893L,63894L,63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,
8581263903L,63904L,63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,
8581363913L,63914L,63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,
8581463923L,63924L,63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,
8581563933L,63934L,63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,
8581663943L,63944L,63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,
8581763953L,63954L,63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,
8581863963L,63964L,63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,
8581963973L,63974L,63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,
8582063983L,63984L,63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,
8582163993L,63994L,63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,
8582264003L,64004L,64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,
8582364013L,64014L,64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,
8582464023L,64024L,64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,
8582564033L,64034L,64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,
8582664043L,64044L,64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,
8582764053L,64054L,64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,
8582864063L,64064L,64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,
8582964073L,64074L,64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,
8583064083L,64084L,64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,
8583164093L,64094L,64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,
8583264103L,64104L,64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,
8583364113L,64114L,64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,
8583464123L,64124L,64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,
8583564133L,64134L,64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,
8583664143L,64144L,64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,
8583764153L,64154L,64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,
8583864163L,64164L,64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,
8583964173L,64174L,64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,
8584064183L,64184L,64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,
8584164193L,64194L,64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,
8584264203L,64204L,64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,
8584364213L,64214L,64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,
8584464223L,64224L,64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,
8584564233L,64234L,64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,
8584664243L,64244L,64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,
8584764253L,64254L,64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,
8584864263L,64264L,64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,
8584964273L,64274L,64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,
8585064283L,64284L,64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,
8585164293L,64294L,64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,
8585264303L,64304L,64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,
8585364313L,64314L,64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,
8585464323L,64324L,64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,
8585564333L,64334L,64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,
8585664343L,64344L,64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,
8585764353L,64354L,64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,
8585864363L,64364L,64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,
8585964373L,64374L,64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,
8586064383L,64384L,64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,
8586164393L,64394L,64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,
8586264403L,64404L,64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,
8586364413L,64414L,64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,
8586464423L,64424L,64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,
8586564433L,64434L,64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,
8586664443L,64444L,64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,
8586764453L,64454L,64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,
8586864463L,64464L,64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,
8586964473L,64474L,64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,
8587064483L,64484L,64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,
8587164493L,64494L,64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,
8587264503L,64504L,64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,
8587364513L,64514L,64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,
8587464523L,64524L,64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,
8587564533L,64534L,64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,
8587664543L,64544L,64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,
8587764553L,64554L,64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,
8587864563L,64564L,64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,
8587964573L,64574L,64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,
8588064583L,64584L,64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,
8588164593L,64594L,64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,
8588264603L,64604L,64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,
8588364613L,64614L,64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,
8588464623L,64624L,64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,
8588564633L,64634L,64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,
8588664643L,64644L,64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,
8588764653L,64654L,64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,
8588864663L,64664L,64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,
8588964673L,64674L,64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,
8589064683L,64684L,64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,
8589164693L,64694L,64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,
8589264703L,64704L,64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,
8589364713L,64714L,64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,
8589464723L,64724L,64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,
8589564733L,64734L,64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,
8589664743L,64744L,64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,
8589764753L,64754L,64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,
8589864763L,64764L,64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,
8589964773L,64774L,64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,
8590064783L,64784L,64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,
8590164793L,64794L,64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,
8590264803L,64804L,64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,
8590364813L,64814L,64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,
8590464823L,64824L,64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,
8590564833L,64834L,64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,
8590664843L,64844L,64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,
8590764853L,64854L,64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,
8590864863L,64864L,64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,
8590964873L,64874L,64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,
8591064883L,64884L,64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,
8591164893L,64894L,64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,
8591264903L,64904L,64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,
8591364913L,64914L,64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,
8591464923L,64924L,64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,
8591564933L,64934L,64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,
8591664943L,64944L,64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,
8591764953L,64954L,64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,
8591864963L,64964L,64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,
8591964973L,64974L,64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,
8592064983L,64984L,64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,
8592164993L,64994L,64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,
8592265003L,65004L,65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,
8592365013L,65014L,65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,
8592465023L,65024L,65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,
8592565033L,65034L,65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,
8592665043L,65044L,65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,
8592765053L,65054L,65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,
8592865063L,65064L,65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,
8592965073L,65074L,65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,
8593065083L,65084L,65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,
8593165093L,65094L,65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,
8593265103L,65104L,65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,
8593365113L,65114L,65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,
8593465123L,65124L,65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,
8593565133L,65134L,65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,
8593665143L,65144L,65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,
8593765153L,65154L,65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,
8593865163L,65164L,65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,
8593965173L,65174L,65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,
8594065183L,65184L,65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,
8594165193L,65194L,65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,
8594265203L,65204L,65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,
8594365213L,65214L,65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,
8594465223L,65224L,65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,
8594565233L,65234L,65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,
8594665243L,65244L,65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,
8594765253L,65254L,65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,
8594865263L,65264L,65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,
8594965273L,65274L,65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,
8595065283L,65284L,65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,
8595165293L,65294L,65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,
8595265303L,65304L,65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,
8595365313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
8595465323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
8595565333L,65334L,65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,
8595665343L,65344L,65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,
8595765321L,65322L,65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,
8595865331L,65332L,65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,
8595965373L,65374L,65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,
8596065383L,65384L,65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,
8596165393L,65394L,65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,
8596265403L,65404L,65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,
8596365413L,65414L,65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,
8596465423L,65424L,65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,
8596565433L,65434L,65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,
8596665443L,65444L,65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,
8596765453L,65454L,65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,
8596865463L,65464L,65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,
8596965473L,65474L,65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,
8597065483L,65484L,65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,
8597165493L,65494L,65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,
8597265503L,65504L,65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,
8597365513L,65514L,65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,
8597465523L,65524L,65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,
8597565533L,65534L,65535L,
85976};
85977#endif
85978/*
85979 * Bitstream decoder.
85980 */
85981
85982/* include removed: duk_internal.h */
85983
85984/* Decode 'bits' bits from the input stream (bits must be 1...24).
85985 * When reading past bitstream end, zeroes are shifted in. The result
85986 * is signed to match duk_bd_decode_flagged.
85987 */
85989 duk_small_int_t shift;
85990 duk_uint32_t mask;
85991 duk_uint32_t tmp;
85992
85993 /* Note: cannot read more than 24 bits without possibly shifting top bits out.
85994 * Fixable, but adds complexity.
85995 */
85996 DUK_ASSERT(bits >= 1 && bits <= 24);
85997
85998 while (ctx->currbits < bits) {
85999#if 0
86000 DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
86001 (long) bits, (long) ctx->currbits));
86002#endif
86003 ctx->currval <<= 8;
86004 if (ctx->offset < ctx->length) {
86005 /* If ctx->offset >= ctx->length, we "shift zeroes in"
86006 * instead of croaking.
86007 */
86008 ctx->currval |= ctx->data[ctx->offset++];
86009 }
86010 ctx->currbits += 8;
86011 }
86012#if 0
86013 DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
86014 (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
86015#endif
86017 /* Extract 'top' bits of currval; note that the extracted bits do not need
86018 * to be cleared, we just ignore them on next round.
86019 */
86020 shift = ctx->currbits - bits;
86021 mask = (1 << bits) - 1;
86022 tmp = (ctx->currval >> shift) & mask;
86023 ctx->currbits = shift; /* remaining */
86025#if 0
86026 DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
86027 (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
86028#endif
86029
86030 return tmp;
86031}
86032
86034 return (duk_small_int_t) duk_bd_decode(ctx, 1);
86035}
86036
86037/* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
86038 * default value. Return value is signed so that negative marker value can be
86039 * used by caller as a "not present" value.
86040 */
86041DUK_INTERNAL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
86042 if (duk_bd_decode_flag(ctx)) {
86043 return (duk_int32_t) duk_bd_decode(ctx, bits);
86044 } else {
86045 return def_value;
86046 }
86047}
86048/*
86049 * Bitstream encoder.
86050 */
86051
86052/* include removed: duk_internal.h */
86053
86054DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
86055 duk_uint8_t tmp;
86056
86057 DUK_ASSERT(ctx != NULL);
86058 DUK_ASSERT(ctx->currbits < 8);
86059
86060 /* This limitation would be fixable but adds unnecessary complexity. */
86061 DUK_ASSERT(bits >= 1 && bits <= 24);
86063 ctx->currval = (ctx->currval << bits) | data;
86064 ctx->currbits += bits;
86065
86066 while (ctx->currbits >= 8) {
86067 if (ctx->offset < ctx->length) {
86068 tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
86069 ctx->data[ctx->offset++] = tmp;
86070 } else {
86071 /* If buffer has been exhausted, truncate bitstream */
86072 ctx->truncated = 1;
86073 }
86074
86075 ctx->currbits -= 8;
86076 }
86077}
86078
86080 duk_small_int_t npad;
86081
86082 DUK_ASSERT(ctx != NULL);
86083 DUK_ASSERT(ctx->currbits < 8);
86085 npad = (duk_small_int_t) (8 - ctx->currbits);
86086 if (npad > 0) {
86087 duk_be_encode(ctx, 0, npad);
86088 }
86089 DUK_ASSERT(ctx->currbits == 0);
86090}
86091/*
86092 * Fast buffer writer with spare management.
86093 */
86094
86095/* include removed: duk_internal.h */
86096
86097/*
86098 * Macro support functions (use only macros in calling code)
86099 */
86100
86101DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t curr_offset, duk_size_t new_length) {
86102 duk_uint8_t *p;
86103
86104 DUK_ASSERT(thr != NULL);
86105 DUK_ASSERT(bw_ctx != NULL);
86106 DUK_UNREF(thr);
86107
86108 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
86109 DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
86110 bw_ctx->p = p + curr_offset;
86111 bw_ctx->p_base = p;
86112 bw_ctx->p_limit = p + new_length;
86113}
86114
86116
86117 DUK_ASSERT(thr != NULL);
86118 DUK_ASSERT(bw_ctx != NULL);
86119 DUK_ASSERT(h_buf != NULL);
86120 DUK_UNREF(thr);
86121
86122 bw_ctx->buf = h_buf;
86123 duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
86125
86127 duk_context *ctx;
86128
86129 DUK_ASSERT(thr != NULL);
86130 DUK_ASSERT(bw_ctx != NULL);
86131 ctx = (duk_context *) thr;
86132
86133 (void) duk_push_dynamic_buffer(ctx, buf_size);
86134 bw_ctx->buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
86135 duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
86136}
86137
86138/* Resize target buffer for requested size. Called by the macro only when the
86139 * fast path test (= there is space) fails.
86140 */
86141DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
86142 duk_size_t curr_off;
86143 duk_size_t add_sz;
86144 duk_size_t new_sz;
86145
86146 DUK_ASSERT(thr != NULL);
86147 DUK_ASSERT(bw_ctx != NULL);
86148
86149 /* We could do this operation without caller updating bw_ctx->ptr,
86150 * but by writing it back here we can share code better.
86151 */
86152
86153 curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
86154 add_sz = (curr_off >> DUK_BW_SPARE_SHIFT) + DUK_BW_SPARE_ADD;
86155 new_sz = curr_off + sz + add_sz;
86156 if (new_sz < curr_off) {
86157 /* overflow */
86159 return NULL; /* not reachable */
86160 }
86161#if 0 /* for manual torture testing: tight allocation, useful with valgrind */
86162 new_sz = curr_off + sz;
86163#endif
86164
86165 /* This is important to ensure dynamic buffer data pointer is not
86166 * NULL (which is possible if buffer size is zero), which in turn
86167 * causes portability issues with e.g. memmove() and memcpy().
86168 */
86169 DUK_ASSERT(new_sz >= 1);
86170
86171 DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
86172
86173 duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
86174 duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
86175 return bw_ctx->p;
86176}
86177
86178/* Make buffer compact, matching current written size. */
86180 duk_size_t len;
86181
86182 DUK_ASSERT(thr != NULL);
86183 DUK_ASSERT(bw_ctx != NULL);
86184 DUK_UNREF(thr);
86185
86186 len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
86187 duk_hbuffer_resize(thr, bw_ctx->buf, len);
86188 duk__bw_update_ptrs(thr, bw_ctx, len, len);
86189}
86190
86192 duk_uint8_t *p_base;
86193
86194 DUK_ASSERT(thr != NULL);
86195 DUK_ASSERT(bw != NULL);
86196 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86197 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86198 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86199 DUK_UNREF(thr);
86200
86201 p_base = bw->p_base;
86202 DUK_MEMCPY((void *) bw->p,
86203 (const void *) (p_base + src_off),
86204 (size_t) len);
86205 bw->p += len;
86206}
86207
86209 DUK_ASSERT(thr != NULL);
86210 DUK_ASSERT(bw != NULL);
86211 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86212 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86213 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86214 DUK_UNREF(thr);
86215
86216 DUK_BW_ENSURE(thr, bw, len);
86217 duk_bw_write_raw_slice(thr, bw, src_off, len);
86218}
86219
86220DUK_INTERNAL 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) {
86221 duk_uint8_t *p_base;
86222 duk_size_t buf_sz, move_sz;
86223
86224 DUK_ASSERT(thr != NULL);
86225 DUK_ASSERT(bw != NULL);
86226 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86228 DUK_UNREF(thr);
86229
86230 p_base = bw->p_base;
86231 buf_sz = bw->p - p_base;
86232 move_sz = buf_sz - dst_off;
86233
86234 DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
86235 DUK_MEMMOVE((void *) (p_base + dst_off + len),
86236 (const void *) (p_base + dst_off),
86237 (size_t) move_sz);
86238 DUK_MEMCPY((void *) (p_base + dst_off),
86239 (const void *) buf,
86240 (size_t) len);
86241 bw->p += len;
86242}
86243
86244DUK_INTERNAL 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) {
86245 DUK_ASSERT(thr != NULL);
86246 DUK_ASSERT(bw != NULL);
86247 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86248 DUK_ASSERT(buf != NULL);
86249 DUK_UNREF(thr);
86250
86251 DUK_BW_ENSURE(thr, bw, len);
86252 duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
86253}
86254
86256 duk_uint8_t *p_base;
86257 duk_size_t buf_sz, move_sz;
86258
86259 DUK_ASSERT(thr != NULL);
86260 DUK_ASSERT(bw != NULL);
86261 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86262 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86263 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86264 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86265 DUK_UNREF(thr);
86266
86267 p_base = bw->p_base;
86268
86269 /* Don't support "straddled" source now. */
86270 DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
86271
86272 if (dst_off <= src_off) {
86273 /* Target is before source. Source offset is expressed as
86274 * a "before change" offset. Account for the memmove.
86276 src_off += len;
86277 }
86278
86279 buf_sz = bw->p - p_base;
86280 move_sz = buf_sz - dst_off;
86281
86282 DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
86283 DUK_MEMMOVE((void *) (p_base + dst_off + len),
86284 (const void *) (p_base + dst_off),
86285 (size_t) move_sz);
86286 DUK_MEMCPY((void *) (p_base + dst_off),
86287 (const void *) (p_base + src_off),
86288 (size_t) len);
86289 bw->p += len;
86290}
86293 DUK_ASSERT(thr != NULL);
86294 DUK_ASSERT(bw != NULL);
86295 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86296 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86297 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86298 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86299 DUK_UNREF(thr);
86300
86301 /* Don't support "straddled" source now. */
86302 DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
86303
86304 DUK_BW_ENSURE(thr, bw, len);
86305 duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
86306}
86307
86309 duk_uint8_t *p_base, *p_dst, *p_src;
86310 duk_size_t buf_sz, move_sz;
86311
86312 DUK_ASSERT(thr != NULL);
86313 DUK_ASSERT(bw != NULL);
86314 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86315 DUK_UNREF(thr);
86316
86317 p_base = bw->p_base;
86318 buf_sz = bw->p - p_base;
86319 move_sz = buf_sz - off;
86320 p_dst = p_base + off + len;
86321 p_src = p_base + off;
86322 DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);
86323 return p_src; /* point to start of 'reserved area' */
86324}
86325
86327 DUK_ASSERT(thr != NULL);
86328 DUK_ASSERT(bw != NULL);
86329 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86330 DUK_UNREF(thr);
86331
86332 DUK_BW_ENSURE(thr, bw, len);
86333 return duk_bw_insert_raw_area(thr, bw, off, len);
86334}
86335
86337 duk_size_t move_sz;
86338
86339 duk_uint8_t *p_base;
86340 duk_uint8_t *p_src;
86341 duk_uint8_t *p_dst;
86342
86343 DUK_ASSERT(thr != NULL);
86344 DUK_ASSERT(bw != NULL);
86345 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86346 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86347 DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
86348 DUK_UNREF(thr);
86349
86350 p_base = bw->p_base;
86351 p_dst = p_base + off;
86352 p_src = p_dst + len;
86353 move_sz = (duk_size_t) (bw->p - p_src);
86354 DUK_MEMMOVE((void *) p_dst,
86355 (const void *) p_src,
86356 (size_t) move_sz);
86357 bw->p -= len;
86358}
86359
86360/*
86361 * Macro support functions for reading/writing raw data.
86362 *
86363 * These are done using mempcy to ensure they're valid even for unaligned
86364 * reads/writes on platforms where alignment counts. On x86 at least gcc
86365 * is able to compile these into a bswap+mov. "Always inline" is used to
86366 * ensure these macros compile to minimal code.
86367 *
86368 * Not really bufwriter related, but currently used together.
86369 */
86370
86371DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
86372 union {
86373 duk_uint8_t b[2];
86374 duk_uint16_t x;
86375 } u;
86376
86377 DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);
86378 u.x = DUK_NTOH16(u.x);
86379 *p += 2;
86380 return u.x;
86381}
86382
86383DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
86384 union {
86385 duk_uint8_t b[4];
86386 duk_uint32_t x;
86387 } u;
86388
86389 DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
86390 u.x = DUK_NTOH32(u.x);
86391 *p += 4;
86392 return u.x;
86393}
86394
86397 union {
86398 duk_uint8_t b[4];
86399 duk_uint32_t x;
86400 } u;
86401
86402 DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
86403 u.x = DUK_NTOH32(u.x);
86404 du.ui[DUK_DBL_IDX_UI0] = u.x;
86405 DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);
86406 u.x = DUK_NTOH32(u.x);
86407 du.ui[DUK_DBL_IDX_UI1] = u.x;
86408 *p += 8;
86409
86410 return du.d;
86411}
86412
86413DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
86414 union {
86415 duk_uint8_t b[2];
86416 duk_uint16_t x;
86417 } u;
86419 u.x = DUK_HTON16(val);
86420 DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);
86421 *p += 2;
86422}
86423
86424DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
86425 union {
86426 duk_uint8_t b[4];
86427 duk_uint32_t x;
86428 } u;
86429
86430 u.x = DUK_HTON32(val);
86431 DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
86432 *p += 4;
86433}
86434
86437 union {
86438 duk_uint8_t b[4];
86439 duk_uint32_t x;
86440 } u;
86441
86442 du.d = val;
86443 u.x = du.ui[DUK_DBL_IDX_UI0];
86444 u.x = DUK_HTON32(u.x);
86445 DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
86446 u.x = du.ui[DUK_DBL_IDX_UI1];
86447 u.x = DUK_HTON32(u.x);
86448 DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);
86449 *p += 8;
86450}
86451/*
86452 * Hash function duk_util_hashbytes().
86453 *
86454 * Currently, 32-bit MurmurHash2.
86455 *
86456 * Don't rely on specific hash values; hash function may be endianness
86457 * dependent, for instance.
86458 */
86459
86460/* include removed: duk_internal.h */
86461
86462#if defined(DUK_USE_STRHASH_DENSE)
86463/* 'magic' constants for Murmurhash2 */
86464#define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL)
86465#define DUK__MAGIC_R 24
86466
86467DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
86468 duk_uint32_t h = seed ^ ((duk_uint32_t) len);
86469
86470 while (len >= 4) {
86471 /* Portability workaround is required for platforms without
86472 * unaligned access. The replacement code emulates little
86473 * endian access even on big endian architectures, which is
86474 * OK as long as it is consistent for a build.
86475 */
86476#ifdef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
86477 duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
86478#else
86479 duk_uint32_t k = ((duk_uint32_t) data[0]) |
86480 (((duk_uint32_t) data[1]) << 8) |
86481 (((duk_uint32_t) data[2]) << 16) |
86482 (((duk_uint32_t) data[3]) << 24);
86483#endif
86484
86485 k *= DUK__MAGIC_M;
86486 k ^= k >> DUK__MAGIC_R;
86487 k *= DUK__MAGIC_M;
86488 h *= DUK__MAGIC_M;
86489 h ^= k;
86490 data += 4;
86491 len -= 4;
86492 }
86493
86494 switch (len) {
86495 case 3: h ^= data[2] << 16;
86496 case 2: h ^= data[1] << 8;
86497 case 1: h ^= data[0];
86498 h *= DUK__MAGIC_M;
86499 }
86500
86501 h ^= h >> 13;
86502 h *= DUK__MAGIC_M;
86503 h ^= h >> 15;
86504
86505 return h;
86507#endif /* DUK_USE_STRHASH_DENSE */
86509 * A tiny random number generator.
86510 *
86511 * Currently used for Math.random().
86512 *
86513 * http://www.woodmann.com/forum/archive/index.php/t-3100.html
86514 */
86515
86516/* include removed: duk_internal.h */
86517
86518#define DUK__UPDATE_RND(rnd) do { \
86519 (rnd) += ((rnd) * (rnd)) | 0x05; \
86520 (rnd) = ((rnd) & 0xffffffffU); /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
86521 } while (0)
86522
86523#define DUK__RND_BIT(rnd) ((rnd) >> 31) /* only use the highest bit */
86524
86527 duk_uint32_t res = 0;
86528 duk_uint32_t rnd;
86529
86530 rnd = thr->heap->rnd_state;
86531
86532 for (i = 0; i < n; i++) {
86533 DUK__UPDATE_RND(rnd);
86534 res <<= 1;
86535 res += DUK__RND_BIT(rnd);
86536 }
86537
86538 thr->heap->rnd_state = rnd;
86539
86540 return res;
86541}
86542
86544 duk_double_t t;
86546 duk_uint32_t rnd;
86547
86548 /*
86549 * XXX: could make this a lot faster if we create the double memory
86550 * representation directly. Feasible easily (must be uniform random).
86551 */
86552
86553 rnd = thr->heap->rnd_state;
86554
86555 n = 53; /* enough to cover the whole mantissa */
86556 t = 0.0;
86557
86558 do {
86559 DUK__UPDATE_RND(rnd);
86560 t += DUK__RND_BIT(rnd);
86561 t /= 2.0;
86562 } while (--n);
86563
86564 thr->heap->rnd_state = rnd;
86565
86566 DUK_ASSERT(t >= (duk_double_t) 0.0);
86567 DUK_ASSERT(t < (duk_double_t) 1.0);
86568
86569 return t;
86570}
const char * proto
Definition civetweb.c:18378
CURL_EXTERN int void * arg
Definition curl.h:2622
guint depth
guint index
duk_uint16_t duk_uint_least16_t
duk_int32_t duk_int_fast32_t
#define DUK_USE_REGEXP_COMPILER_RECLIMIT
unsigned int duk_small_uint_t
duk_uint32_t duk_uint_least32_t
duk_uint_fast32_t duk_uint_fast_t
duk_small_int_t duk_ret_t
#define DUK_LOSE_CONST(src)
duk_int_fast32_t duk_int_fast_t
duk_uint_fast16_t duk_small_uint_fast_t
#define DUK_USE_NATIVE_CALL_RECLIMIT
duk_uint8_t duk_uint_fast8_t
#define DUK_USE_MARK_AND_SWEEP_RECLIMIT
#define DUK_VA_COPY(dest, src)
duk_int_fast32_t duk_int_t
#define DUK_NORETURN(decl)
duk_int_fast16_t duk_small_int_fast_t
duk_int32_t duk_int_least32_t
duk_int16_t duk_int_fast16_t
duk_uint8_t duk_uint_least8_t
duk_uint_fast32_t duk_uint_t
duk_int16_t duk_int_least16_t
#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT
duk_uint32_t duk_uintmax_t
#define DUK_MEMZERO(p, n)
#define DUK_USE_ESBC_MAX_LINENUMBER
duk_small_int_t duk_bool_t
duk_uint32_t duk_uint_fast32_t
#define DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE
duk_uint16_t duk_uint_fast16_t
#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)
DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags)
#define DUK__ISHEXDIGIT(x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx)
DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap)
DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count)
DUK_INTERNAL const char * duk_str_fmt_ptr
#define DUK_HOBJECT_CLASS_BOOLEAN
#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, x)
DUK_INTERNAL const char * duk_str_invalid_func_name
#define DUK_HEAPHDR_FLAGS_FLAG_MASK
#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)
DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
#define DUK_MS_FLAG_EMERGENCY
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp)
DUK_INTERNAL const char * duk_str_unsupported
#define DUK_ACT_FLAG_TAILCALLED
#define DUK__EMIT_FLAG_NO_SHUFFLE_B
#define DUK_DBG_CMD_APPREQUEST
#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED
#define DUK_HEAPHDR_CLEAR_FINALIZED(h)
DUK_INTERNAL_DECL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size)
#define DUK_TVAL_DECREF(thr, tv)
#define DUK_MS_FLAG_NO_OBJECT_COMPACTION
#define DUK_STRIDX_TO_LOCALE_STRING
#define DUK__FUNCTION_BODY_REQUIRE_SLOTS
#define DUK_RETOK_DISJUNCTION
#define DUK_HSTRING_GET_ARRIDX_FAST(h)
#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, x)
DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y)
#define DUK_STR_STRING_TOO_LONG
#define DUK_STRTAB_DELETED_MARKER(heap)
DUK_EXTERNAL void * duk_to_pointer(duk_context *ctx, duk_idx_t index)
#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE
DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t)
#define DUK_LABEL_FLAG_ALLOW_CONTINUE
DUK_LOCAL void duk__run_voluntary_gc(duk_heap *heap)
#define DUK_HEAPHDR_SET_REACHABLE(h)
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag)
#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap, h, v)
DUK_INTERNAL_DECL void duk_hthread_callstack_grow(duk_hthread *thr)
DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act)
#define DUK_TVAL_SET_TVAL(v, x)
#define DUK_BIDX_UINT8ARRAY_PROTOTYPE
#define DUK__LOCAL_TZOFFSET_MAXITER
DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags)
#define DUK_ACT_FLAG_PREVENT_YIELD
DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap)
DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx)
#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)
const duk_uint8_t duk_unicode_ids_m_let_noa[42]
#define DUK_STRIDX_INT_CALLEE
#define DUK_ERROR_RANGE(thr, msg)
DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val)
#define DUK_HOBJECT_FLAG_NEWENV
#define DUK_HSTRING_HAS_ASCII(x)
DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH
DUK_EXTERNAL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt,...)
#define DUK_TVAL_SET_NUMBER_UPDREF
DUK_INTERNAL_DECL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs)
#define DUK_ASSERT_CTX_VALID(ctx)
#define DUK_TVAL_SET_FASTINT_U32_UPDREF
#define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)
#define DUK_ENC_OP(op)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx)
struct duk_breakpoint duk_breakpoint
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx)
DUK_INTERNAL const char * duk_str_invalid_break_cont_label
#define DUK_COMPILER_MAX_BYTECODE_LENGTH
DUK_INTERNAL_DECL const char * duk_push_string_readable(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip)
#define DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i)
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)
#define DUK_HOBJECT_DECREF_ALLOWNULL(thr, h)
#define DUK_BW_WRITE_ENSURE_SLICE(thr, bw, dst_off, dst_len)
DUK_LOCAL void duk__coerce_effective_this_binding(duk_hthread *thr, duk_hobject *func, duk_idx_t idx_this)
DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_int_t prop_flags, duk_bool_t is_func_decl)
#define DUK_HBUFFER_SET_EXTERNAL(x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx)
DUK_INTERNAL_DECL duk_hstring * duk_to_hstring(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx)
#define DUK_STR_NUMBER_OUTSIDE_RANGE
#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)
DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k)
DUK_INTERNAL_DECL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx)
const duk_uint8_t duk_unicode_ids_noa[791]
DUK_EXTERNAL void * duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags)
#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap, h)
#define DUK_STRIDX_BYTE_OFFSET
DUK_LOCAL double duk__asin(double x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx)
DUK_INTERNAL_DECL duk_hstring * duk_js_typeof(duk_hthread *thr, duk_tval *tv_x)
DUK_EXTERNAL void duk_pop_2(duk_context *ctx)
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)
#define DUK_STRIDX_UINT8_CLAMPED_ARRAY
DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset)
#define DUK_BW_ADD_PTR(thr, bw_ctx, delta)
DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr)
#define DUK_TVAL_SET_NULL(tv)
DUK_EXTERNAL const char * duk_push_string(duk_context *ctx, const char *str)
DUK_INTERNAL const char * duk_str_invalid_arg_name
DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK__ADVANCEBYTES(lex_ctx, count)
DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx)
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24]
#define DUK_HOBJECT_ALIGN_TARGET
DUK_INTERNAL const char * duk_str_not_object_coercible
DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[]
#define DUK_STR_ARRAY_LENGTH_WRITE_FAILED
DUK_LOCAL double duk__pow_fixed(double x, double y)
DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length)
DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size)
#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)
DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p)
DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year)
DUK_INTERNAL const char * duk_str_catchstack_limit
#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT
DUK_INTERNAL_DECL duk_hthread * duk_require_hthread(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL const char * duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx)
#define DUK_TVAL_SET_FASTINT_UPDREF
DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_idx_t idx_start, duk_idx_t idx_end, duk_int_t *out_start_offset, duk_int_t *out_end_offset)
#define DUK_HSTRING_GET_DATA(x)
DUK_LOCAL duk_hobject * duk__nonbound_func_lookup(duk_context *ctx, duk_idx_t idx_func, duk_idx_t *out_num_stack_args, duk_tval **out_tv_func, duk_small_uint_t call_flags)
#define DUK_STR_CATCHSTACK_LIMIT
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year)
DUK_INTERNAL const char * duk_str_prototype_chain_limit
DUK_LOCAL void duk__sort_array_indices(duk_hthread *thr, duk_hobject *h_obj)
DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx)
#define DUK_HOBJECT_A_MIN_GROW_ADD
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx)
#define DUK_HSTRING_IS_ASCII(x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx)
#define DUK_HEAPHDR_SET_TEMPROOT(h)
DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr, duk_hobject *func, duk_hobject *varenv, duk_idx_t idx_argbase, duk_idx_t num_stack_args)
DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type)
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped)
#define DUK_REOP_ASSERT_WORD_BOUNDARY
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx)
DUK_INTERNAL const char * duk_str_invalid_switch
#define DUK_HOBJECT_CLASS_REGEXP
DUK_LOCAL duk_idx_t duk__get_idx_func(duk_hthread *thr, duk_idx_t num_stack_args)
DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder)
DUK_LOCAL void duk__clear_refzero_list_flags(duk_heap *heap)
#define DUK_TVAL_SET_FASTINT_U32(tv, val)
#define DUK_LABEL_FLAG_ALLOW_BREAK
DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv)
DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto)
#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)
DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z)
#define DUK__NARGS_VARARGS_MARKER
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx)
#define DUK_STRIDX_INT_REGBASE
#define DUK_STRIDX_BRACKETED_ELLIPSIS
#define DUK_STRIDX_ENUMERABLE
DUK_EXTERNAL void duk_throw(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index)
#define DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap, h)
#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)
#define DUK_JSON_ENC_LOOPARRAY
#define DUK_HEAPHDR_GET_TYPE(h)
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
DUK_INTERNAL_DECL duk_uint8_t * duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz)
#define DUK_S2N_FLAG_ALLOW_FRAC
#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY
#define DUK_BW_SET_PTR(thr, bw_ctx, ptr)
DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_idx_t *p_num_stack_args, duk_bool_t is_constructor_call)
#define DUK_HOBJECT_GET_PROTOTYPE(heap, h)
DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject(duk_context *ctx, duk_idx_t index)
DUK_LOCAL double duk__atan(double x)
#define DUK_TVAL_IS_NUMBER(tv)
DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256]
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)
#define DUK_STR_NOT_COMPILEDFUNCTION
DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top)
#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap, h, i)
#define DUK_STR_INVALID_ARG_NAME
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx)
#define DUK_VALSTACK_SHRINK_THRESHOLD
DUK_INTERNAL const char * duk_str_internal_error
DUK_INTERNAL const char * duk_str_cannot_delete_identifier
DUK_INTERNAL const char * duk_str_valstack_limit
#define DUK_HOBJECT_FLAG_CONSTRUCTABLE
#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap, h, v)
DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t index)
#define DUK_DBG_CMD_GETOBJPROPDESC
#define DUK_ERROR_TYPE(thr, msg)
DUK_EXTERNAL const char * duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags)
DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx)
DUK_INTERNAL const char * duk_str_invalid_label
DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags)
#define DUK_HOBJECT_HAS_BOUND(h)
#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap)
DUK_INTERNAL_DECL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size)
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)
DUK_LOCAL double duk__fmax_fixed(double x, double y)
#define DUK_HOBJECT_CLASS_BUFFER
#define DUK_ERROR_RAW_FMT1(thr, file, line, err, fmt, arg1)
DUK_EXTERNAL void duk_push_this(duk_context *ctx)
DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr)
#define DUK_PC2LINE_MAX_DIFF_LENGTH
#define DUK_BIDX_EVAL_ERROR_PROTOTYPE
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
#define DUK_STR_INVALID_LABEL
#define DUK_STR_DEFAULTVALUE_COERCE_FAILED
#define DUK_RETOK_ATOM_PERIOD
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)
#define DUK_HOBJECT_POSTINC_ENEXT(h)
#define DUK_DBG_CMD_GETBYTECODE
DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t index)
#define DUK_HBUFFER_INCREF(thr, h)
#define DUK_STRIDX_UC_ARGUMENTS
DUK_EXTERNAL void duk_push_true(duk_context *ctx)
DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx)
#define DUK__IEEE_DOUBLE_EXP_BIAS
#define DUK_STRIDX_LC_POINTER
DUK_LOCAL void duk__push_stash(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent, n_arr, n_hash)
DUK_LOCAL void duk__generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct)
DUK_LOCAL double duk__log(double x)
DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags)
DUK_INTERNAL const char * duk_str_temp_limit
DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key)
DUK_INTERNAL const char * duk_str_unexpected_end_of_pattern
#define DUK_RAW_WRITE_U16_BE(ptr, val)
#define DUK_ALLOC(heap, size)
#define DUK_STRIDX_MOD_LOADED
DUK_LOCAL_DECL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx)
#define DUK__EXPR_FLAG_REQUIRE_INIT
DUK_LOCAL duk_ret_t duk__math_minmax(duk_context *ctx, duk_double_t initial, duk__two_arg_func min_max)
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4]
DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_context *ctx)
#define DUK_STRIDX_INT_FORMALS
DUK_INTERNAL const char * duk_str_invalid_descriptor
DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_size_t act_idx, duk_size_t cat_idx)
#define DUK_STR_INVALID_EXPRESSION
#define DUK_STR_INVALID_ARRAY_LENGTH
DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key)
DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj)
DUK_INTERNAL const char * duk_str_pop_too_many
#define DUK_STR_INVALID_FUNC_NAME
DUK_LOCAL void duk__handle_executor_error(duk_heap *heap, duk_hthread *entry_thread, duk_size_t entry_callstack_top, duk_int_t entry_call_recursion_depth, duk_jmpbuf *entry_jmpbuf_ptr)
#define DUK_CALL_FLAG_CONSTRUCTOR_CALL
DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index)
DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata)
#define DUK_RE_EXECUTE_STEPS_LIMIT
DUK_INTERNAL duk_hbufferobject * duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags)
DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index)
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)
#define DUK_HOBJECT_FLAG_NAMEBINDING
#define DUK_HOBJECT_CMASK_BOOLEAN
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx)
#define DUK_IVAL_ARITH_EXTRAOP
#define DUK__SETTEMP_CHECKMAX(comp_ctx, x)
DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n)
#define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap)
DUK_INTERNAL const char * duk_str_empty_expr_not_allowed
#define DUK_CAT_GET_TYPE(c)
#define DUK_LEXER_BUFFER_SIZE
DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2)
#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING
DUK_INTERNAL const duk_uint8_t duk_initjs_data[204]
#define DUK_HEAPHDR_SET_NEXT(heap, h, val)
#define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)
DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index)
#define DUK_STRIDX_TO_UTC_STRING
#define DUK_LFUNC_NARGS_MAX
#define DUK_N2S_FLAG_FIXED_FORMAT
DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z)
#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)
#define DUK_STR_NO_SOURCECODE
#define DUK__MAX_RE_QUANT_DIGITS
DUK_INTERNAL_DECL void * duk_default_alloc_function(void *udata, duk_size_t size)
#define DUK_HEAPHDR_STRING_INIT_NULLS(h)
#define DUK__PACK_ARGS(classnum, protobidx, elemtype, elemshift, isview)
DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const char * duk_str_c_callstack_limit
DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict)
#define DUK_STRTAB_MIN_USED_DIVISOR
DUK_INTERNAL_DECL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h)
DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name)
#define DUK_HOBJECT_CLASS_INT32ARRAY
#define DUK_JS_COMPILE_FLAG_EVAL
DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index)
DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget)
#define DUK_VSRESIZE_FLAG_THROW
DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr, duk_hobject *func, duk_activation *act)
#define DUK_BW_WRITE_ENSURE_U8(thr, bw_ctx, val)
DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out)
DUK_EXTERNAL const char * duk_hex_encode(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk_idx_t nargs)
DUK_INTERNAL_DECL void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj)
#define DUK_BW_WRITE_RAW_U8_3(thr, bw_ctx, val1, val2, val3)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx)
DUK_LOCAL void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr)
#define DUK_HBUFFEROBJECT_ELEM_INT32
#define DUK_TVAL_INCREF_FAST(thr, tv)
DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval)
DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt,...)
DUK_EXTERNAL void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint)
#define DUK_STRIDX_LC_ARGUMENTS
DUK_INTERNAL const char * duk_str_property_is_virtual
DUK_INTERNAL_DECL void duk_hthread_catchstack_shrink_check(duk_hthread *thr)
DUK_LOCAL const duk_uint8_t duk__token_lbp[]
DUK_LOCAL double duk__sin(double x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx)
DUK_INTERNAL_DECL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr)
#define DUK_HSTRING_NO_ARRAY_INDEX
DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index)
#define DUK_GETDESC_FLAG_PUSH_VALUE
#define DUK_COMPARE_FLAG_NEGATE
#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap, h, i)
#define DUK__ADVTOK(advbytes, tok)
DUK_LOCAL int duk__bi_is_even(duk__bigint *x)
DUK_LOCAL void duk__adjust_valstack_and_top(duk_hthread *thr, duk_idx_t num_stack_args, duk_idx_t idx_args, duk_idx_t nregs, duk_idx_t nargs, duk_hobject *func)
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx)
DUK_INTERNAL_DECL void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags)
DUK_INTERNAL_DECL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n)
#define DUK_HTHREAD_STRING_BASE64(thr)
DUK_EXTERNAL void * duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
#define DUK_DELPROP_FLAG_THROW
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx)
DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len)
#define DUK__EMIT_2(js_ctx, ch1, ch2)
duk_int32_t duk_reg_t
DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t magic)
DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_size_t cat_idx, duk_small_uint_t lj_type)
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type)
DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name)
#define DUK_STRIDX_UC_BOOLEAN
#define DUK_TVAL_SET_OBJECT(tv, hptr)
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv)
#define DUK__MAX_OBJECT_INIT_PAIRS
#define DUK_STRDATA_MAX_STRLEN
#define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap)
#define DUK_STR_INVALID_SWITCH
DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx)
#define DUK_HOBJECT_CLASS_POINTER
#define DUK_HOBJECT_GET_ENEXT(h)
#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE
#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)
#define DUK_STRIDX_DATA_VIEW
#define DUK_STRIDX_BYTES_PER_ELEMENT
DUK_LOCAL duk_hbufferobject * duk__push_arraybuffer_with_length(duk_context *ctx, duk_uint_t len)
DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict)
#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x, v)
#define DUK__MAX_ARRAY_INIT_VALUES
#define DUK__JSON_DECSTR_CHUNKSIZE
DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx)
DUK_INTERNAL const char * duk_str_invalid_call_args
#define DUK__MAX_FORMATTED_LENGTH
DUK_INTERNAL_DECL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top)
DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx)
#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx)
DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h)
DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe(duk_heap *heap, duk_uint32_t new_used)
#define DUK_STRIDX_MINUS_INFINITY
#define DUK_HSTRING_HAS_RESERVED_WORD(x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx)
#define DUK_GET_HOBJECT_NEGIDX(ctx, idx)
#define DUK_BW_SET_SIZE(thr, bw_ctx, sz)
DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id)
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)
DUK_LOCAL duk_codepoint_t duk__hexval(duk_lexer_ctx *lex_ctx, duk_codepoint_t x)
#define DUK_TVAL_GET_OBJECT(tv)
#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)
DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index)
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval)
DUK_EXTERNAL const char * duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len)
DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx)
DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z)
#define DUK_HOBJECT_GET_PROPS(heap, h)
#define DUK_STR_INVALID_VAR_DECLARATION
DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h)
#define DUK_STRIDX_JSON_EXT_UNDEFINED
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx)
#define DUK_HEAPHDR_CHECK_FLAG_BITS(h, bits)
#define DUK__IVAL_FLAG_ALLOW_CONST
#define DUK_DBG_CMD_GETCALLSTACK
DUK_INTERNAL_DECL duk_hnativefunction * duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags)
DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr)
DUK_INTERNAL_DECL duk_hstring * duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj)
#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h)
DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size)
DUK_INTERNAL_DECL duk_hobject * duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t idx_bottom)
#define DUK_STRIDX_INT_HANDLER
DUK_EXTERNAL void duk_push_boolean(duk_context *ctx, duk_bool_t val)
DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins)
DUK_INTERNAL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message)
#define DUK_HOBJECT_FLAG_NOTAIL
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx)
#define duk_xdef_prop_stridx_wec(ctx, obj_index, stridx)
#define DUK_STR_DECODE_FAILED
DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size)
DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos)
#define DUK_LEXER_WINDOW_SIZE
#define DUK_BIDX_INT8ARRAY_PROTOTYPE
DUK_EXTERNAL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx)
#define DUK_HEAPHDR_FLAG_READONLY
#define DUK_RETOK_ATOM_WORD_CHAR
DUK_LOCAL void duk__bi_normalize(duk__bigint *x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx)
#define DUK__SETTEMP(comp_ctx, x)
#define DUK_RETOK_ATOM_START_CHARCLASS
DUK_INTERNAL_DECL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len)
#define DUK__GETTEMP(comp_ctx)
DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc)
#define DUK_HBUFFER_FIXED_GET_SIZE(x)
#define DUK_HOBJECT_CLASS_OBJECT
#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h, i)
DUK_LOCAL duk_uint8_t * duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func)
DUK_EXTERNAL duk_int_t duk_api_global_line
#define DUK_STR_SETTER_UNDEFINED
#define DUK_STRTAB_MIN_FREE_DIVISOR
DUK_INTERNAL const duk_uint8_t duk_strings_data[1049]
struct duk_hbuffer_dynamic duk_hbuffer_dynamic
DUK_EXTERNAL void duk_to_undefined(duk_context *ctx, duk_idx_t index)
#define DUK_STR_INVALID_CALL_ARGS
#define DUK_BIDX_OBJECT_PROTOTYPE
#define DUK_STR_STRICT_CALLER_READ
DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx)
#define DUK_COMPILER_TOKEN_LIMIT
#define DUK_STR_NOT_NATIVEFUNCTION
DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key)
DUK_INTERNAL_DECL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h)
#define DUK_HOBJECT_A_GET_BASE(heap, h)
DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset)
#define DUK_CAT_CLEAR_CATCH_ENABLED(c)
#define DUK_HOBJECT_A_ABANDON_LIMIT
#define DUK_DBG_PROPFLAG_INTERNAL
DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length)
#define DUK_STRIDX_FLOAT32_ARRAY
#define DUK_BIDX_TYPE_ERROR_PROTOTYPE
#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h, off)
DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx)
DUK_LOCAL void duk__push_hstring_readable_unicode(duk_context *ctx, duk_hstring *h_input)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx)
DUK_INTERNAL int duk_repl_isinf(double x)
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags)
DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx)
#define DUK_TVAL_IS_NULL(tv)
#define DUK_STRIDX_LINE_NUMBER
#define DUK_S2N_FLAG_ALLOW_MINUS
#define DUK_HBUFFER_MAX_BYTELEN
#define DUK_HOBJECT_FLAG_COMPILEDFUNCTION
DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap)
DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK__EMIT_CSTR(js_ctx, p)
#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)
DUK_LOCAL duk_tval * duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key)
#define DUK_STR_REDEFINE_VIRT_PROP
#define DUK_STRIDX_ERR_CREATE
#define duk_xdef_prop_index_wec(ctx, obj_index, arr_index)
DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h)
#define duk_xdef_prop_wec(ctx, obj_index)
DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value)
#define DUK__INITBUFFER(lex_ctx)
#define DUK_STRIDX_BYTE_LENGTH
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap, h)
DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_TVAL_IS_BUFFER(tv)
#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx)
#define DUK_STRIDX_UC_NUMBER
#define DUK_HEAPHDR_GET_PREV(heap, h)
DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr)
#define DUK__MK_LBP(bp)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx)
DUK_INTERNAL const char * duk_str_duplicate_label
DUK_LOCAL void duk__vm_arith_unary_op(duk_hthread *thr, duk_tval *tv_x, duk_idx_t idx_x, duk_small_uint_fast_t opcode)
#define DUK_HOBJECT_GET_CLASS_MASK(h)
#define DUK_PUSH_SPRINTF_SANITY_LIMIT
DUK_INTERNAL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message)
DUK_LOCAL_DECL duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival)
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx)
#define DUK__NUMCONV_CTX_BIGINTS_SIZE
static const duk_uint8_t duk__buffer_class_from_elemtype[9]
#define DUK_STRIDX_START_RESERVED
#define DUK_BIDX_DOUBLE_ERROR
#define DUK__ISOCTDIGIT(x)
DUK_INTERNAL_DECL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs)
DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask)
#define DUK__NUM_FUNC_PROPS_BITS
#define DUK_HEAPHDR_GET_FLAGS_RAW(h)
DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits)
#define DUK_LFUNC_LENGTH_MAX
DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv)
DUK_INTERNAL_DECL void * duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud)
#define DUK_TVAL_SET_UNUSED_UPDREF
DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags)
#define DUK_STR_VALSTACK_LIMIT
#define DUK__JSON_DECSTR_BUFSIZE
DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h)
#define DUK_BW_COMPACT(thr, bw_ctx)
DUK_LOCAL 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)
#define DUK_HEAPHDR_SET_PREV(heap, h, val)
#define DUK_HCOMPILEDFUNCTION_GET_CODE_END(heap, h)
#define DUK_HEAPHDR_SET_FINALIZABLE(h)
#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)
DUK_EXTERNAL void * duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size)
#define DUK__EMIT_FLAG_B_IS_TARGETSOURCE
DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z)
#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM
DUK_EXTERNAL void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs)
DUK_LOCAL void duk__refzero_free_pending(duk_hthread *thr)
#define DUK_STR_UNEXPECTED_REGEXP_TOKEN
DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx)
#define DUK_TVAL_IS_UNDEFINED(tv)
#define DUK__EXPR_FLAG_REJECT_IN
DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK__EXPR_FLAG_ALLOW_EMPTY
#define DUK_STRIDX_TO_GMT_STRING
#define DUK_BW_SETPTR_AND_COMPACT(thr, bw_ctx, ptr)
DUK_INTERNAL const char * duk_str_strict_caller_read
DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h)
#define DUK_TVAL_SET_UNUSED(tv)
DUK_LOCAL duk_hstring * duk__alloc_init_hstring(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash, const duk_uint8_t *extdata)
#define DUK_EQUALS_FLAG_SAMEVALUE
DUK_INTERNAL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt,...)
DUK_EXTERNAL void * duk_require_heapptr(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_IS_COMPILEDFUNCTION(h)
#define DUK_RE_FLAG_MULTILINE
#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx)
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)
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len)
DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx)
#define DUK_HEAP_MAX_BREAKPOINTS
DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs)
DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str)
DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx)
#define DUK__MKBITS(a, b, c, d, e, f, g, h)
DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val, duk_small_uint_t op_flags)
#define DUK_LEXER_GETPOINT(ctx, pt)
#define DUK_BIDX_POINTER_PROTOTYPE
#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx)
DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x)
DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx)
#define DUK_TVAL_SET_BUFFER(tv, hptr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx)
DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr, duk_hcompiledfunction *fun_temp, duk_hobject *outer_var_env, duk_hobject *outer_lex_env, duk_bool_t add_auto_proto)
#define DUK_TVAL_IS_OBJECT(tv)
#define DUK_HOBJECT_IS_OBJENV(h)
#define DUK_HOBJECT_CLASS_INT16ARRAY
DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index)
#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS
#define DUK_HEAPHDR_FLAG_TEMPROOT
#define DUK_JSON_FLAG_AVOID_KEY_QUOTES
DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res)
#define DUK_HOBJECT_SET_CREATEARGS(h)
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out)
DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p)
#define DUK_HOBJECT_HAS_CREATEARGS(h)
#define DUK_BW_ENSURE(thr, bw_ctx, sz)
#define DUK_JSON_ENC_REQSTACK
DUK_INTERNAL_DECL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length)
DUK_INTERNAL const char * duk_str_bound_chain_limit
DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[]
#define DUK_ERROR_SYNTAX(thr, msg)
DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr)
#define DUK_BIDX_FUNCTION_PROTOTYPE
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx)
DUK_LOCAL_DECL duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx, duk_small_uint_t new_key_flags)
#define DUK_PROPDESC_FLAGS_NONE
DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_context *ctx, duk_idx_t index, duk__toint_coercer coerce_func)
#define DUK__JSON_STRINGIFY_BUFSIZE
#define DUK_HOBJECT_CMASK_STRING
#define DUK_TVAL_GET_BUFFER(tv)
#define DUK_PROPDESC_FLAG_VIRTUAL
DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v)
DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t index, duk_uint_t flag_mask)
#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, hdr)
DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx)
double(* duk__two_arg_func)(double, double)
DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
DUK_EXTERNAL void * duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx)
#define DUK_BI_DATE_ISO8601_BUFSIZE
#define DUK_TVAL_SET_TVAL_UPDREF_FAST
DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_STR_BUFFER_TOO_LONG
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, duk_propdesc *temp_desc)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum)
#define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap)
DUK_LOCAL duk_hstring * duk__do_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash)
DUK_INTERNAL const char * duk_str_invalid_throw
#define DUK_TVAL_SET_NULL_UPDREF
#define DUK_BI_COMMONJS_MODULE_ID_LIMIT
DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_hthread *entry_thread, duk_size_t entry_callstack_top)
DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx)
#define DUK_STRIDX_INT_THREAD
DUK_LOCAL void duk__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)
#define DUK_STRIDX_WRITABLE
#define DUK_BIDX_DATAVIEW_PROTOTYPE
#define duk_push_size_t(ctx, val)
DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size)
DUK_EXTERNAL duk_bool_t duk_del_var(duk_context *ctx)
void(* duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16]
#define DUK__DELETED_MARKER(heap)
DUK_INTERNAL const char * duk_str_unterminated_stmt
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv)
DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap)
DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf)
#define DUK_HTHREAD_STRING___PROTO__(thr)
#define DUK_STRIDX_LC_FUNCTION
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp)
#define DUK_HBUFFEROBJECT_VALID_SLICE(h)
#define DUK_HOBJECT_CLASS_FUNCTION
DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x)
DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra)
#define DUK_HOBJECT_HASHIDX_UNUSED
#define DUK_HOBJECT_SET_PROPS(heap, h, x)
DUK_EXTERNAL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2)
#define DUK_ENC_OP_A_B_C(op, a, b, c)
DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname)
#define DUK_HEAPHDR_SET_FINALIZED(h)
DUK_EXTERNAL const char * duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len)
DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx)
DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap)
DUK_LOCAL void duk__vm_bitwise_not(duk_hthread *thr, duk_tval *tv_x, duk_uint_fast_t idx_z)
#define DUK_STRDATA_DATA_LENGTH
struct duk_compiler_instr duk_compiler_instr
#define DUK_HEAP_DBG_RATELIMIT_OPCODES
DUK_INTERNAL_DECL void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags)
DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key)
#define DUK_HEAPHDR_PREDEC_REFCOUNT(h)
#define DUK_TB_FLAG_NOBLAME_FILELINE
DUK_LOCAL int duk__bi_is_zero(duk__bigint *x)
#define DUK_HSTRING_GET_CHARLEN(x)
DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv)
DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256]
DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst)
DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16]
DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv)
#define duk_js_samevalue(tv_x, tv_y)
#define DUK_HTHREAD_STRING_INT_TARGET(thr)
#define DUK__GETCONST_MAX_CONSTS_CHECK
#define DUK_STR_ARRAY_LENGTH_NOT_WRITABLE
#define DUK_STRIDX_INT_FINALIZER
DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr)
#define DUK_HOBJECT_CLASS_ARRAY
#define DUK_STRIDX_CONSTRUCTOR
#define DUK_CALLSTACK_SHRINK_THRESHOLD
#define DUK_ERROR_API_INDEX(thr, index)
#define DUK__EMIT_STRIDX(js_ctx, i)
DUK_INTERNAL_DECL duk_hcompiledfunction * duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx)
#define DUK_HOBJECT_CLASS_DATE
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x)
DUK_LOCAL_DECL duk_compiler_instr * duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc)
DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2)
DUK_EXTERNAL void * duk_get_pointer(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_INCREF(thr, tv)
DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2)
const duk_uint8_t duk_unicode_caseconv_uc[1288]
#define DUK_DBG_CMD_GETOBJPROPDESCRANGE
#define DUK_CAT_HAS_FINALLY_ENABLED(c)
#define DUK__IVAL_FLAG_REQUIRE_TEMP
#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h, i)
DUK_INTERNAL const duk_uint8_t duk_lc_digits[36]
DUK_INTERNAL const char * duk_str_array_length_over_2g
#define DUK_REALLOC_INDIRECT(heap, cb, ud, newsize)
#define DUK_PROPDESC_FLAG_ACCESSOR
#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)
DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr)
DUK_INTERNAL void duk_default_panic_handler(duk_errcode_t code, const char *msg)
DUK_LOCAL duk_bool_t duk__getid_activation_regs(duk_hthread *thr, duk_hstring *name, duk_activation *act, duk__id_lookup_result *out)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx)
DUK_LOCAL void duk__free_stringtable(duk_heap *heap)
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, h)
#define DUK__PROP_TYPE_ACCESSOR
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i)
#define DUK_BW_RESET_SIZE(thr, bw_ctx)
#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap, h, v)
DUK_LOCAL duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key)
DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx)
#define DUK_HOBJECT_E_GET_KEY(heap, h, i)
#define DUK__FUNCTION_INIT_REQUIRE_SLOTS
DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj)
#define DUK_HOBJECT_CLASS_ARGUMENTS
#define DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h, len)
DUK_LOCAL duk_ret_t duk__pnew_helper(duk_context *ctx)
#define DUK_ERROR_INTERNAL_DEFMSG(thr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx)
#define DUK_STR_CANNOT_DELETE_IDENTIFIER
DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx)
#define DUK_TVAL_GET_TAG(tv)
DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_context *ctx, duk_small_uint_t stridx_key)
#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS
DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx)
DUK_EXTERNAL const char * duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len)
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx)
#define DUK_PROPDESC_FLAGS_WE
DUK_LOCAL_DECL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)
#define DUK_VSRESIZE_FLAG_SHRINK
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx)
DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256]
DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip)
#define DUK__ASSERT_LEFT(n)
DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx)
DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx)
DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h)
DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr)
DUK_EXTERNAL void * duk_alloc(duk_context *ctx, duk_size_t size)
DUK_INTERNAL_DECL duk_hcompiledfunction * duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index)
#define duk_push_idx(ctx, val)
#define DUK_CALLSTACK_SHRINK_SPARE
#define DUK_HTHREAD_STRING_YIELD(thr)
#define DUK_HBUFFEROBJECT_ELEM_INT16
DUK_LOCAL double duk__ceil(double x)
#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, p)
#define DUK_STRIDX_UC_STRING
#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx)
#define DUK_BIDX_STRING_PROTOTYPE
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx)
#define DUK_BW_WRITE_RAW_U8_6(thr, bw_ctx, val1, val2, val3, val4, val5, val6)
#define DUK_DBG_CMD_TRIGGERSTATUS
#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY
#define DUK_TVAL_IS_POINTER(tv)
#define DUK_STRIDX_LC_UNDEFINED
#define DUK_HOBJECT_GET_ASIZE(h)
DUK_INTERNAL_DECL duk_hnativefunction * duk_get_hnativefunction(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_CMASK_ALL
DUK_LOCAL duk_hbufferobject * duk__getrequire_bufobj_this(duk_context *ctx, duk_bool_t throw_flag)
#define DUK_ASSERT_HBUFFEROBJECT_VALID(h)
#define DUK__ADVANCECHARS(lex_ctx, count)
DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj)
DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx)
#define DUK_HTHREAD_STRING_INT_REGBASE(thr)
DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap)
DUK_INTERNAL const char * duk_str_setter_undefined
#define DUK_STR_JSONENC_RECLIMIT
#define DUK_TVAL_IS_UNUSED(tv)
#define DUK_HSTRING_GET_HASH(x)
#define DUK_FREE(heap, ptr)
#define DUK_HOBJECT_FLAG_BUFFEROBJECT
#define DUK_HTHREAD_STRING_INT_THREAD(thr)
#define DUK_HEAPHDR_HAS_TEMPROOT(h)
DUK_INTERNAL_DECL void * duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud)
#define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(heap, h)
DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr)
DUK_INTERNAL const char * duk_str_invalid_getset_name
DUK_INTERNAL_DECL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx)
#define DUK_BW_ENSURE_RAW(thr, bw_ctx, sz, ptr)
#define DUK_HOBJECT_E_SET_KEY(heap, h, i, k)
DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_hthread *entry_thread, duk_size_t entry_callstack_top)
#define DUK_HOBJECT_FLAG_CREATEARGS
DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16]
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val)
#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap, h, i)
DUK_LOCAL_DECL void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc)
DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx)
#define DUK_HOBJECT_GET_CLASS_STRING(heap, h)
#define DUK_HEAPHDR_HTYPE_VALID(h)
#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE
DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx)
DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs)
DUK_LOCAL duk_bool_t duk__resize_strtab_probe(duk_heap *heap)
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index)
#define DUK_HTHREAD_STRING_INT_VARENV(thr)
#define DUK_BIDX_INT32ARRAY_PROTOTYPE
#define DUK_MS_FLAG_NO_FINALIZERS
DUK_LOCAL duk_uint8_t * duk__load_string_raw(duk_context *ctx, duk_uint8_t *p)
#define DUK_HSTRING_FLAG_RESERVED_WORD
#define DUK_BW_GET_BASEPTR(thr, bw_ctx)
#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST
#define DUK__OUTPUT_TYPE_LINENUMBER
#define DUK_STR_NOT_OBJECT_COERCIBLE
#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)
DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key)
#define DUK_STRIDX_LC_BOOLEAN
#define DUK_ASSERT_DISABLE(x)
#define DUK__UNPACK_RULE(rule, var_nextidx, var_flags)
DUK_LOCAL void duk__recursion_decrease(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx)
DUK_EXTERNAL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags)
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2]
#define DUK_BIDX_LOGGER_CONSTRUCTOR
DUK_INTERNAL const char * duk_str_const_limit
DUK_EXTERNAL const char * duk_api_global_filename
#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)
DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap)
DUK_EXTERNAL void duk_push_null(duk_context *ctx)
#define DUK_HEAPHDR_PREINC_REFCOUNT(h)
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)
#define DUK_HOBJECT_IS_CALLABLE(h)
#define DUK_HOBJECT_SET_NOTAIL(h)
DUK_INTERNAL_DECL duk_hthread * duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags)
DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr)
DUK_LOCAL void duk__free_markandsweep_finalize_list(duk_heap *heap)
DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val)
DUK_LOCAL const duk_uint8_t * duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len)
#define DUK_CALL_FLAG_IS_RESUME
#define DUK_STRIDX_DEFINE_PROPERTY
#define DUK_ERROR_API(thr, msg)
#define DUK_HTHREAD_STRING_INT_LEXENV(thr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx)
DUK_EXTERNAL void duk_pop_3(duk_context *ctx)
DUK_EXTERNAL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index)
#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE
#define DUK_HOBJECT_CLASS_AS_FLAGS(v)
#define DUK_CALL_FLAG_IS_TAILCALL
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp)
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx)
DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[]
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen)
#define duk_push_i64(ctx, val)
duk_double_t(* duk__toint_coercer)(duk_hthread *thr, duk_tval *tv)
#define DUK_HOBJECT_SET_ESIZE(h, v)
#define DUK_HOBJECT_CLASS_NUMBER
DUK_EXTERNAL void duk_push_current_function(duk_context *ctx)
#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)
#define DUK__JSON_ENCSTR_CHUNKSIZE
static const duk_uint32_t duk__bufobj_flags_lookup[]
#define DUK_ERROR_ALLOC_DEFMSG(thr)
DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x)
#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC
DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy)
#define DUK_HSTRING_HAS_EXTDATA(x)
#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)
#define DUK_LFUNC_MAGIC_MIN
#define DUK_HTHREAD_STATE_INACTIVE
DUK_EXTERNAL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const duk_c_function duk_bi_native_functions[149]
duk_uint32_t duk_regconst_t
#define DUK_ACT_FLAG_DIRECT_EVAL
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)
DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata)
DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t check_object_coercible)
DUK_INTERNAL_DECL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx)
DUK_EXTERNAL void duk_dup_top(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx)
DUK_LOCAL void duk__to_regexp_helper(duk_context *ctx, duk_idx_t index, duk_bool_t force_new)
DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
#define DUK_HBUFFER_FLAG_EXTERNAL
DUK_EXTERNAL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx)
#define DUK__HASH_INITIAL(hash, h_size)
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10]
DUK_LOCAL void duk__array_sort_swap(duk_context *ctx, duk_int_t l, duk_int_t r)
#define DUK_HTHREAD_STRING_UC_NULL(thr)
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)
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)
#define DUK_HOBJECT_IS_ENV(h)
#define DUK_HEAPHDR_HAS_REACHABLE(h)
DUK_INTERNAL const char * duk_str_defaultvalue_coerce_failed
#define DUK_STRIDX_INT32_ARRAY
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, x, v)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset)
#define DUK_HOBJECT_SET_STRICT(h)
#define DUK_CAT_FLAG_LEXENV_ACTIVE
DUK_INTERNAL_DECL void duk_bi_json_stringify_helper(duk_context *ctx, duk_idx_t idx_value, duk_idx_t idx_replacer, duk_idx_t idx_space, duk_small_uint_t flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx)
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD
#define DUK_N2S_FLAG_FORCE_EXP
#define DUK_TVAL_SET_BOOLEAN_UPDREF
#define DUK_STR_INVALID_COUNT
struct duk_hbuffer_external duk_hbuffer_external
DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_size_t entry_valstack_bottom_index, duk_size_t entry_callstack_top, duk_size_t entry_catchstack_top, duk_jmpbuf *old_jmpbuf_ptr)
DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx)
#define DUK__DIGITCHAR(x)
#define DUK_HTHREAD_STRING_INT_VARMAP(thr)
DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p)
DUK_LOCAL_DECL duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg, duk_small_uint_t flags)
DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg)
#define DUK_LFUNC_NARGS_VARARGS
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)
#define DUK_HEAPHDR_GET_REFCOUNT(h)
DUK_INTERNAL_DECL duk_hobject * duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code)
#define DUK_TVAL_SET_DOUBLE(tv, d)
DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx)
#define DUK__ALLOCTEMP(comp_ctx)
#define DUK_LEXER_INITCTX(ctx)
DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value)
#define DUK__BYTECODE_INITIAL_ALLOC
#define DUK_HOBJECT_IS_THREAD(h)
#define DUK_TVAL_GET_STRING(tv)
DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv)
DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags)
DUK_LOCAL void duk__push_stridx(duk_context *ctx, duk_bitdecoder_ctx *bd)
DUK_INTERNAL const char * duk_str_invalid_object_literal
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key)
#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs)
DUK_LOCAL void duk__vm_logical_not(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_z)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx)
#define DUK_RE_COMPILE_TOKEN_LIMIT
DUK_LOCAL_DECL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj)
static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6]
DUK_INTERNAL_DECL void duk_bi_json_parse_helper(duk_context *ctx, duk_idx_t idx_value, duk_idx_t idx_reviver, duk_small_uint_t flags)
DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index)
#define DUK_STR_INTERNAL_ERROR
DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_constructor(duk_context *ctx)
#define DUK__BITPACK_UNDERSCORE
DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index)
#define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr)
DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx)
#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED
#define DUK_HOBJECT_CMASK_NUMBER
#define DUK_BC_DECLVAR_FLAG_UNDEF_VALUE
#define DUK_LEXER_SETPOINT(ctx, pt)
#define DUK_STR_UNEXPECTED_END_OF_PATTERN
DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep)
#define DUK_HTHREAD_STRING_RESUME(thr)
DUK_INTERNAL_DECL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top)
#define DUK_TVAL_SET_FASTINT(tv, val)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx)
DUK_INTERNAL const char * duk_str_compiler_recursion_limit
#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)
DUK_INTERNAL const char * duk_str_func_stmt_not_allowed
DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_INTERNAL const char * duk_str_jsondec_reclimit
static duk_uint8_t * duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end)
DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val)
#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)
#define DUK_HEAPHDR_SET_TYPE(h, val)
DUK_LOCAL void duk__free_refzero_list(duk_heap *heap)
DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline)
DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y)
DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_H_SIZE_DIVISOR
DUK_INTERNAL_DECL void * duk_heap_mem_alloc(duk_heap *heap, duk_size_t size)
DUK_LOCAL int duk__protected_compact_object(duk_context *ctx)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags)
#define DUK_STRTAB_HIGHEST_32BIT_PRIME
#define DUK_STR_NOT_EXTENSIBLE
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx)
DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr, duk_size_t act_idx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx)
#define DUK_STR_EXPECTED_IDENTIFIER
DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_HAS_ARRAY_PART(h)
#define DUK_HSTRING_DECREF(thr, h)
#define DUK_HEAPHDR_FLAG_FINALIZED
DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags)
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size)
DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64]
#define DUK_BIDX_ARRAY_PROTOTYPE
#define DUK_TVAL_SET_NUMBER_CHKFAST(tv, d)
#define DUK_HSTRING_INCREF(thr, h)
#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ
DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags, duk_idx_t idx_func)
DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size)
DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[]
#define DUK_HEAPHDR_FLAG_REACHABLE
DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx)
DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val)
DUK_INTERNAL const char * duk_str_callstack_limit
#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH
DUK_EXTERNAL void duk_require_stack_top(duk_context *ctx, duk_idx_t top)
#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)
#define DUK_STR_COMPILER_RECURSION_LIMIT
DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL const char * duk_str_quantifier_too_many_copies
#define DUK_HTHREAD_STATE_RESUMED
DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx)
#define DUK_ERROR_UNSUPPORTED(thr, msg)
DUK_EXTERNAL void * duk_require_pointer(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_SET_TVAL_UPDREF
DUK_INTERNAL_DECL duk_hobject * duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj)
#define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx)
#define DUK_HOBJECT_IS_NATIVEFUNCTION(h)
#define DUK_STR_ARRAY_LENGTH_OVER_2G
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_require(duk_context *ctx)
#define DUK_STRIDX_INVALID_DATE
#define DUK_GET_HOBJECT_POSIDX(ctx, idx)
DUK_LOCAL void duk__get_this_regexp(duk_context *ctx)
#define DUK_PUSH_SPRINTF_INITIAL_SIZE
DUK_LOCAL_DECL void duk__emit_extraop_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b, duk_regconst_t c)
#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)
DUK_EXTERNAL void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint)
DUK_EXTERNAL const char * duk_get_string(duk_context *ctx, duk_idx_t index)
#define DUK__PACK_RULE(partmask, sepmask, nextpart, flags)
DUK_LOCAL_DECL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx)
DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes)
DUK_LOCAL void duk__handle_call_error(duk_hthread *thr, duk_size_t entry_valstack_bottom_index, duk_size_t entry_valstack_end, duk_size_t entry_catchstack_top, duk_size_t entry_callstack_top, duk_int_t entry_call_recursion_depth, duk_hthread *entry_curr_thread, duk_uint_fast8_t entry_thread_state, duk_instr_t **entry_ptr_curr_pc, duk_idx_t idx_func, duk_jmpbuf *old_jmpbuf_ptr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx)
#define DUK_STR_FMT_INVALID_JSON
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx)
#define DUK_DBG_CMD_APPNOTIFY
void(* duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct)
#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)
DUK_LOCAL double duk__fmin_fixed(double x, double y)
DUK_LOCAL const duk_uint8_t duk__log_level_strings[]
DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size)
#define DUK_HTHREAD_INCREF(thr, h)
DUK_LOCAL duk_uint32_t duk__push_tval_to_hstring_arr_idx(duk_context *ctx, duk_tval *tv, duk_hstring **out_h)
DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic)
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)
#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT
#define DUK_ACT_FLAG_CONSTRUCT
DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__set_catcher_regs(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type)
#define DUK_BIDX_ERROR_PROTOTYPE
#define DUK_COMPILER_PEEPHOLE_MAXITER
#define DUK__IVAL_FLAG_REQUIRE_SHORT
DUK_LOCAL double duk__floor(double x)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc)
DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx)
DUK_LOCAL void duk__handle_safe_call_shared(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_uint_fast8_t entry_thread_state, duk_instr_t **entry_ptr_curr_pc)
DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags)
#define DUK_STRIDX_DELETE_PROPERTY
DUK_LOCAL const duk_int8_t duk__hash_size_corrections[]
static const duk_uint8_t duk__buffer_proto_from_elemtype[9]
#define DUK_HOBJECT_CLASS_OBJENV
DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top)
DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags)
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)
#define DUK_BW_INSERT_ENSURE_BYTES(thr, bw, dst_off, buf, len)
DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx)
#define DUK_TVAL_IS_STRING(tv)
#define DUK_STRIDX_INT_LEXENV
#define DUK_STR_NOT_CONSTRUCTABLE
DUK_INTERNAL_DECL duk_bool_t duk_valstack_resize_raw(duk_context *ctx, duk_size_t min_new_size, duk_small_uint_t flags)
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx)
#define DUK_PROPDESC_FLAG_NO_OVERWRITE
#define DUK_LFUNC_FLAGS_PACK(magic, length, nargs)
DUK_INTERNAL_DECL void * duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize)
#define DUK_HOBJECT_DECREF(thr, h)
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)
#define DUK_ALLOC_RAW(heap, size)
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)
DUK_INTERNAL_DECL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx)
#define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap, h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx)
DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK_HOBJECT_CLASS_ERROR
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x)
#define DUK_LEXER_TEMP_BUF_LIMIT
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr)
#define DUK_CAT_FLAG_CATCH_ENABLED
#define DUK_STR_INVALID_ARRAY_LITERAL
DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx)
#define DUK_VSRESIZE_FLAG_COMPACT
DUK_INTERNAL_DECL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags)
DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues)
#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx)
DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg)
DUK_INTERNAL int duk_repl_signbit(double x)
#define DUK_BIDX_URI_ERROR_PROTOTYPE
#define DUK_PROPDESC_FLAGS_MASK
DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
#define DUK_HOBJECT_CLASS_FLOAT32ARRAY
DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof)
DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap, h, i)
#define DUK_HOBJECT_GET_HSIZE(h)
#define DUK_RETOK_ATOM_END_GROUP
#define DUK_BIDX_TYPE_ERROR_THROWER
DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t)
#define DUK__TOKEN_LBP_GET_BP(x)
DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx)
#define DUK_CATCHSTACK_DEFAULT_MAX
#define DUK_HOBJECT_FLAG_BOUND
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index)
#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)
DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index)
DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length)
#define DUK_CAT_GET_LABEL(c)
DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x)
#define DUK_STRIDX_JSON_EXT_FUNCTION2
#define DUK_TVAL_SET_POINTER(tv, hptr)
#define DUK_RAW_READ_U8(ptr)
DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap)
DUK_INTERNAL const char * duk_str_invalid_expression
#define DUK_HEAP_STRING_INT_VALUE(heap)
DUK_INTERNAL const char * duk_str_bytecode_limit
#define DUK_HEAPHDR_HAS_READONLY(h)
#define DUK_STR_JSONDEC_RECLIMIT
DUK_EXTERNAL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_IS_BUFFEROBJECT(h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx)
#define DUK_BW_WRITE_RAW_U8(thr, bw_ctx, val)
DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type)
DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv)
DUK_EXTERNAL void * duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
#define DUK_ASSERT_VALSTACK_SPACE(thr, n)
#define DUK_TVAL_IS_LIGHTFUNC(tv)
DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t index)
#define DUK_HSTRING_GET_BYTELEN(x)
#define DUK_RETOK_ATOM_NOT_WHITE
DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr)
#define DUK_ENC_OP_A_BC(op, a, bc)
#define DUK_BW_GET_SIZE(thr, bw_ctx)
#define DUK_VALSTACK_GROW_STEP
#define DUK_BC_RETURN_FLAG_HAVE_RETVAL
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx)
#define DUK_HEAPHDR_GET_FLAGS(h)
DUK_INTERNAL_DECL duk_hbuffer * duk_require_hbuffer(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_CLASS_UINT8ARRAY
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen)
#define DUK_BIDX_NUMBER_PROTOTYPE
DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[]
DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags)
#define DUK__NUM_ISO8601_PARSER_PARTS
DUK_EXTERNAL duk_idx_t duk_push_object(duk_context *ctx)
#define DUK_STRIDX_EMPTY_STRING
#define DUK_DBG_CMD_GETLOCALS
#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE
DUK_INTERNAL_DECL void duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags)
DUK_EXTERNAL void duk_get_var(duk_context *ctx)
DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[]
DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index)
#define DUK_STRTAB_GROW_ST_SIZE(n)
#define DUK_HTHREAD_STATE_RUNNING
DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx)
#define DUK_BIDX_UINT32ARRAY_PROTOTYPE
#define DUK_HOBJECT_CLASS_GLOBAL
DUK_INTERNAL const char * duk_str_fmt_invalid_json
#define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC
DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_context *ctx)
DUK_INTERNAL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index)
DUK_LOCAL void duk__push_string(duk_context *ctx, duk_bitdecoder_ctx *bd)
#define DUK_STRIDX_INT_VARMAP
#define DUK_STRIDX_UC_OBJECT
DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem)
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)
#define DUK_STRTAB_CHAIN_SIZE
DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc)
#define DUK_RETOK_ASSERT_WORD_BOUNDARY
DUK_INTERNAL const char * duk_str_proxy_rejected
#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)
DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const char * duk_str_not_extensible
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)
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)
DUK_INTERNAL const char * duk_str_proxy_revoked
DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index)
#define DUK_JSON_FLAG_EXT_CUSTOM
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)
#define DUK_BIDX_REGEXP_CONSTRUCTOR
#define DUK_TVAL_CHKFAST_INPLACE(v)
DUK_EXTERNAL const char * duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap)
DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top)
DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_context *ctx)
DUK_INTERNAL const duk_int8_t duk_hex_dectab[256]
DUK_INTERNAL const char * duk_str_wrong_buffer_type
DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index)
DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx)
#define DUK_HSTRING_SET_CHARLEN(x, v)
#define DUK_STR_PROTOTYPE_CHAIN_LIMIT
DUK_EXTERNAL void * duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc)
#define DUK_HBUFFEROBJECT_ELEM_FLOAT64
#define DUK__VALSTACK_PROXY_LOOKUP
#define DUK_DBG_CMD_LISTBREAK
DUK_INTERNAL_DECL duk_hbuffer * duk_get_hbuffer(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_SET_BOOLEAN_TRUE(v)
#define DUK_HTHREAD_STRING_SET(thr)
DUK_LOCAL double duk__exp(double x)
DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx)
DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect)
DUK_EXTERNAL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t index)
#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
#define DUK_REALLOC_RAW(heap, ptr, newsize)
DUK_INTERNAL const char * duk_str_alloc_failed
#define DUK_ENC_OP_A(op, a)
#define DUK_BW_INIT_WITHBUF(thr, bw_ctx, buf)
#define DUK_HSTRING_FLAG_EXTDATA
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)
#define duk_push_hthread(ctx, h)
#define DUK_HBUFFEROBJECT_ELEM_UINT32
DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx)
DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x)
#define DUK_RETOK_ATOM_NOT_WORD_CHAR
#define DUK_STR_BYTECODE_LIMIT
#define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap)
DUK_EXTERNAL void duk_put_var(duk_context *ctx)
#define DUK_PROPDESC_FLAG_CONFIGURABLE
#define DUK_HTHREAD_STRING_JX(thr)
#define DUK_HOBJECT_H_GET_INDEX(heap, h, i)
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)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key)
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
DUK_INTERNAL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber)
DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst)
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx)
DUK_INTERNAL const char * duk_str_invalid_array_literal
#define DUK__ALLOW_AUTO_SEMI_ALWAYS
#define DUK_HBUFFEROBJECT_ELEM_UINT16
#define DUK__REGCONSTP(x)
#define DUK_STRIDX_MOD_SEARCH
#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap, h, i, v)
DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx)
DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr)
DUK_INTERNAL const char * duk_str_not_buffer
DUK_LOCAL duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t index, duk_small_uint_t tag)
#define DUK__HASH_PROBE_STEP(hash)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx)
#define DUK_TVAL_IS_DOUBLE(v)
DUK_INTERNAL const char * duk_str_invalid_return
#define DUK_CAT_FLAG_FINALLY_ENABLED
#define DUK_STR_UNTERMINATED_STMT
#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)
#define DUK_HTHREAD_STRING_INT_THIS(thr)
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val)
DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index)
#define DUK_STRIDX_ARRAY_BUFFER
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx)
#define DUK_HOBJECT_CLASS_UINT32ARRAY
#define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)
#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap, h)
#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)
DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x)
DUK_EXTERNAL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs)
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_bool_t require)
#define DUK__MK_LBP_FLAGS(bp, flags)
DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y)
DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt,...)
DUK_INTERNAL const char * duk_str_sprintf_too_long
#define DUK__TOKEN_LBP_FLAG_NO_REGEXP
#define DUK_CAT_SET_LEXENV_ACTIVE(c)
#define DUK_HEAPHDR_SET_FLAGS(h, val)
#define DUK_RETOK_ATOM_START_CAPTURE_GROUP
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp)
#define DUK_JS_COMPILE_FLAG_FUNCEXPR
#define DUK_STRTAB_INITIAL_SIZE
DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h)
#define DUK_HOBJECT_CLASS_THREAD
#define DUK_DBG_CMD_DETACHING
DUK_LOCAL double duk__round_fixed(double x)
DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv)
#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, expectname, lowmemstr)
#define DUK_STRIDX_UC_THREAD
DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index)
#define DUK_CAT_HAS_LEXENV_ACTIVE(c)
DUK_INTERNAL const char * duk_str_invalid_array_length
#define DUK_ASSERT_HOBJECT_VALID(h)
DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp)
#define DUK_HOBJECT_E_GET_KEY_PTR(heap, h, i)
DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_bool_t is_join)
#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)
#define DUK_HOBJECT_FLAG_STRICT
DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr)
#define DUK_HSTRING_MAX_BYTELEN
DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL const char * duk_str_invalid_regexp_flags
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)
#define DUK_RETOK_ASSERT_START
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx)
DUK_EXTERNAL const char * duk_base64_encode(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h)
#define DUK_HTHREAD_STRING_EVAL(thr)
DUK_INTERNAL const char * duk_str_number_outside_range
DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv)
DUK_INTERNAL const char * duk_str_unimplemented
DUK_LOCAL void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx)
duk_uint32_t duk_instr_t
#define DUK_HTHREAD_STRING_FILE_NAME(thr)
DUK_INTERNAL const char * duk_str_invalid_try
#define DUK_HOBJECT_CMASK_FUNCTION
#define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap)
#define DUK_HOBJECT_HAS_NATIVEFUNCTION(h)
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx)
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag)
#define DUK_STRIDX_UINT8_ARRAY
#define DUK_STRIDX_LAST_INDEX
#define DUK_RAW_WRITE_DOUBLE_BE(ptr, val)
#define DUK_STRIDX_START_STRICT_RESERVED
#define DUK__PREVENT_MS_SIDE_EFFECTS(heap)
const duk_uint8_t duk_unicode_caseconv_lc[616]
#define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx)
DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h)
DUK_INTERNAL const char * duk_str_encode_failed
DUK_INTERNAL_DECL void duk_to_object_class_string_top(duk_context *ctx)
#define DUK_STRIDX_UINT16_ARRAY
DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK__COMPILE_ENTRY_SLOTS
#define DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)
#define DUK_STR_INVALID_QUANTIFIER_VALUES
#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY
DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx)
DUK_LOCAL void duk__resolve_offset_opt_length(duk_context *ctx, duk_hbufferobject *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)
DUK_LOCAL duk_bool_t duk__delvar_helper(duk_hthread *thr, duk_hobject *env, duk_activation *act, duk_hstring *name)
DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year)
#define DUK__SYNC_AND_NULL_CURR_PC()
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_small_int_t expect_token)
DUK_EXTERNAL const char * duk_json_encode(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx)
#define DUK__ISTEMP(comp_ctx, x)
DUK_INTERNAL_DECL duk_hbufferobject * duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx)
DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key)
DUK_INTERNAL const char * duk_str_invalid_for
DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx)
DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets)
DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
DUK_LOCAL void duk__recursion_increase(duk_compiler_ctx *comp_ctx)
DUK_EXTERNAL void duk_load_function(duk_context *ctx)
#define DUK_BW_WRITE_ENSURE_HSTRING(thr, bw_ctx, val)
DUK_INTERNAL const char * duk_str_array_length_write_failed
#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)
#define DUK_HOBJECT_CLASS_DECENV
#define DUK__ISREG(comp_ctx, x)
DUK_LOCAL duk_bool_t duk__declvar_helper(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_small_int_t prop_flags, duk_bool_t is_func_decl)
DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val)
DUK_INTERNAL const char * duk_str_regexp_executor_recursion_limit
#define DUK_N2S_FLAG_FRACTION_DIGITS
#define DUK_HOBJECT_MAX_PROPERTIES
#define DUK_ERROR_FMT2(thr, err, fmt, arg1, arg2)
DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[]
#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx)
DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr, duk_hobject *func, duk_hobject *env, duk_idx_t num_stack_args)
#define DUK_DELPROP_FLAG_FORCE
#define DUK_HOBJECT_HAS_THREAD(h)
DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect)
DUK_EXTERNAL void * duk_get_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO
#define DUK__IEEE_DOUBLE_EXP_MIN
#define DUK_BW_REMOVE_ENSURE_SLICE(thr, bw, off, len)
DUK_INTERNAL_DECL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h)
DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx)
DUK_INTERNAL const char * duk_str_unexpected_type
DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind)
struct duk_hbuffer_fixed duk_hbuffer_fixed
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap, h)
DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc)
#define DUK_HOBJECT_IS_FUNCTION(h)
DUK_INTERNAL_DECL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h)
#define DUK_BW_INIT_PUSHBUF(thr, bw_ctx, sz)
DUK_EXTERNAL void duk_to_null(duk_context *ctx, duk_idx_t index)
#define DUK_BIDX_BOOLEAN_PROTOTYPE
#define DUK_STR_INVALID_BREAK_CONT_LABEL
DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_FLAG_ENVRECCLOSED
struct duk_tval_struct duk_tval
DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx)
#define DUK_PANIC(code, msg)
DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx)
DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx)
DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2)
DUK_LOCAL_DECL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx)
#define DUK_HOBJECT_SET_ENEXT(h, v)
#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap, x)
#define DUK_LFUNC_LENGTH_MIN
DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr)
DUK_LOCAL const duk_uint8_t * duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n)
#define DUK_HSTRING_SET_HASH(x, v)
DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags)
DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16]
#define DUK_HOBJECT_CLASS_MAX
DUK_EXTERNAL void * duk_get_heapptr(duk_context *ctx, duk_idx_t index)
#define DUK_STR_WRONG_BUFFER_TYPE
DUK_EXTERNAL void duk_push_undefined(duk_context *ctx)
#define DUK_DBG_ERR_UNSUPPORTED
#define DUK_STR_CONCAT_RESULT_TOO_LONG
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)
DUK_LOCAL double duk__fabs(double x)
DUK_LOCAL duk_int_t duk__count_used_probe(duk_heap *heap)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx)
DUK_LOCAL void duk__push_stridx_or_string(duk_context *ctx, duk_bitdecoder_ctx *bd)
DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx)
#define DUK_STRIDX_INT_TARGET
DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_STR_WITH_IN_STRICT_MODE
#define DUK_BW_GET_PTR(thr, bw_ctx)
#define DUK_HOBJECT_FLAG_THREAD
#define DUK__ISDIGIT03(x)
#define DUK_STR_NOT_CONFIGURABLE
DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256]
#define DUK_HSTRING_SET_ARRIDX(x)
#define DUK_HTHREAD_STRING_TO_JSON(thr)
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)
#define DUK_STR_C_CALLSTACK_LIMIT
DUK_INTERNAL_DECL duk_hstring * duk_push_this_coercible_to_string(duk_context *ctx)
DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc)
DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h)
DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256]
#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT
#define DUK_VALSTACK_INITIAL_SIZE
#define DUK_HSTRING_HAS_INTERNAL(x)
DUK_INTERNAL_DECL duk_hcompiledfunction * duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj)
DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget)
DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start)
#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags)
#define DUK_RETOK_ATOM_NOT_DIGIT
DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs)
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx)
#define DUK_HTHREAD_STRING_REQUIRE(thr)
#define DUK_STRIDX_INT_TRACEDATA
#define DUK__ALLOCTEMPS(comp_ctx, count)
DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, duk_idx_t num_stack_args, duk_idx_t num_stack_res)
DUK_EXTERNAL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_E_SET_FLAGS(heap, h, i, f)
DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg)
#define DUK__BI_PRINT(name, x)
DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx)
DUK_EXTERNAL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs)
#define DUK_STRIDX_UINT32_ARRAY
DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_and_maxnargs)
#define DUK_HOBJECT_SET_CONSTRUCTABLE(h)
DUK_LOCAL duk_uint8_t duk__date_equivyear[14]
#define DUK_S2N_FLAG_ALLOW_PLUS
DUK_LOCAL void duk__mark_finalizable(duk_heap *heap)
#define DUK_HEAPHDR_HAS_FINALIZED(h)
DUK_INTERNAL const char * duk_str_with_in_strict_mode
DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx)
DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx)
#define DUK_STR_INVALID_CONTEXT
#define DUK_HTHREAD_STRING_NAME(thr)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act)
#define DUK_PROPDESC_FLAGS_WC
DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key)
#define DUK_HOBJECT_E_MIN_GROW_DIVISOR
DUK_LOCAL void duk__push_double(duk_context *ctx, duk_bitdecoder_ctx *bd)
DUK_LOCAL void * duk__get_buffer_data_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag)
#define DUK_HTHREAD_GET_STRING(thr, idx)
#define DUK_HOBJECT_IS_DECENV(h)
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year)
#define DUK_PROPDESC_FLAG_WRITABLE
#define DUK_HSTRING_SET_RESERVED_WORD(x)
DUK_LOCAL_DECL void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags)
#define DUK_HEAP_GET_STRING(heap, idx)
DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index)
#define DUK_HOBJECT_SET_ENVRECCLOSED(h)
DUK_EXTERNAL void duk_set_global_object(duk_context *ctx)
#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT
DUK_EXTERNAL const char * duk_push_sprintf(duk_context *ctx, const char *fmt,...)
#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING
DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx)
DUK_EXTERNAL void duk_swap_top(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx)
#define duk_js_equals(thr, tv_x, tv_y)
#define DUK_BIDX_THREAD_PROTOTYPE
#define DUK_REOP_BACKREFERENCE
DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx)
#define DUK_STR_PUSH_BEYOND_ALLOC_STACK
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx)
#define DUK_STR_CALLSTACK_LIMIT
#define DUK__ISDIGIT47(x)
#define DUK__ARRAY_MID_JOIN_LIMIT
#define DUK__RECURSION_INCREASE(comp_ctx, thr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx)
#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP
DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char *str)
DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info)
DUK_EXTERNAL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompiledfunction *f)
DUK_EXTERNAL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr)
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)
DUK_INTERNAL const char * duk_str_func_name_required
DUK_LOCAL void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id)
DUK_INTERNAL const char * duk_str_not_writable
#define DUK_BIDX_BUFFER_PROTOTYPE
#define DUK_TVAL_GET_POINTER(tv)
#define DUK_HOBJECT_CLASS_INT8ARRAY
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)
#define DUK_HNATIVEFUNCTION_NARGS_VARARGS
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx)
DUK_INTERNAL const char * duk_str_not_constructable
DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx)
#define DUK_HSTRING_SET_ASCII(x)
DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
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)
DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags)
DUK_EXTERNAL void duk_push_number(duk_context *ctx, duk_double_t val)
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx)
DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags)
DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count)
DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr)
DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx)
#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags)
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)
DUK_INTERNAL int duk_repl_isnan(double x)
DUK_INTERNAL_DECL duk_tval * duk_require_tval(duk_context *ctx, duk_idx_t index)
#define DUK_HTHREAD_STRING_INT_CALLEE(thr)
#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ
DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch)
DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg)
DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z)
#define DUK_HOBJECT_A_MIN_GROW_DIVISOR
DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t index)
#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h, tval, fval)
#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)
#define DUK_HEAP_STRCACHE_SIZE
DUK_INTERNAL_DECL duk_hbuffer * duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata)
DUK_EXTERNAL void duk_require_function(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap)
#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)
#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr)
#define DUK_GET_TVAL_NEGIDX(ctx, idx)
DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16]
DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
#define DUK_ASSERT_TOP(ctx, n)
DUK_EXTERNAL void duk_push_false(duk_context *ctx)
#define DUK__PARSE_STATEMENTS_SLOTS
DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)
DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg)
#define DUK_BW_WRITE_RAW_XUTF8(thr, bw_ctx, cp)
DUK_LOCAL duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr, duk_hstring *name, duk_hobject *env, duk__id_lookup_result *out)
#define DUK__EMIT_FLAG_NO_SHUFFLE_A
#define DUK_BC_CALL_FLAG_EVALCALL
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags)
#define DUK_STRIDX_IGNORE_CASE
#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE
DUK_INTERNAL_DECL void duk_hthread_callstack_shrink_check(duk_hthread *thr)
#define DUK_HTHREAD_STRING_INT_FORMALS(thr)
#define DUK_HOBJECT_CMASK_POINTER
DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx)
#define DUK_HOBJECT_BOUND_CHAIN_SANITY
#define duk_push_i32(ctx, val)
#define DUK_STRIDX_JSON_EXT_NEGINF
#define DUK_CALLSTACK_DEFAULT_MAX
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(duk_context *ctx)
DUK_LOCAL duk_uint8_t * duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p)
#define DUK_JS_COMPILE_FLAG_STRICT
DUK_EXTERNAL void duk_push_global_stash(duk_context *ctx)
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8]
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(heap, h)
DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt,...)
DUK_EXTERNAL const char * duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len)
#define DUK_HOBJECT_SET_PROTOTYPE(heap, h, x)
#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)
DUK_INTERNAL const char * duk_str_invalid_count
#define DUK_STR_PROPERTY_IS_VIRTUAL
#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY
#define DUK_HOBJECT_FLAG_EXTENSIBLE
#define DUK_REOP_ASSERT_START
#define DUK_STR_INVALID_REGEXP_FLAGS
DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global)
#define DUK_STRIDX_INT16_ARRAY
DUK_INTERNAL const char * duk_str_cyclic_input
DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx)
#define DUK_RE_QUANTIFIER_INFINITE
#define duk_push_uarridx(ctx, val)
DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset)
#define DUK__EMIT_HSTR(js_ctx, h)
DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx)
#define DUK_N2S_FLAG_NO_ZERO_PAD
#define DUK_PROPDESC_IS_ENUMERABLE(p)
#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD
#define DUK_HOBJECT_SET_ASIZE(h, v)
#define DUK_ENC_OP_ABC(op, abc)
DUK_EXTERNAL void * duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size)
DUK_LOCAL duk_codepoint_t duk__decode_uniesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx)
#define DUK_PROPDESC_FLAGS_WEC
#define DUK_STRIDX_TO_TOK(x)
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)
DUK_INTERNAL_DECL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf)
DUK_LOCAL duk_hstring * duk__find_matching_string_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash)
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)
DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs)
#define DUK__CHECK_BITMASK(table, cp)
DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_context *ctx, 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)
DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf)
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx)
DUK_LOCAL duk_hbufferobject * duk__get_bufobj_this(duk_context *ctx)
#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx)
#define DUK_STRIDX_TO_LOG_STRING
DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx)
DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK_HOBJECT_FLAG_NATIVEFUNCTION
DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv)
DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_context *ctx, duk_int_t idx1, duk_int_t idx2)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx)
#define DUK_STRIDX_INT_VARENV
DUK_INTERNAL_DECL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj)
#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags)
#define DUK_HEAPHDR_INCREF(thr, h)
#define DUK_STRIDX_JSON_EXT_NAN
#define DUK_ALLOC_ZEROED(heap, size)
DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_INTERNAL_DECL duk_hthread * duk_get_hthread(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx)
DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers)
#define DUK_STR_INVALID_GETSET_NAME
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx)
DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst)
#define DUK_STRIDX_FLOAT64_ARRAY
#define duk_js_strict_equals(tv_x, tv_y)
#define DUK_BIDX_REGEXP_PROTOTYPE
DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const char * duk_str_jsonenc_reclimit
#define DUK_BIDX_OBJECT_CONSTRUCTOR
DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags)
#define DUK_HOBJECT_CLASS_UINT16ARRAY
#define DUK__BITPACK_LETTER_LIMIT
DUK_INTERNAL_DECL duk_idx_t duk_push_compiledfunction(duk_context *ctx)
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)
#define DUK_RAW_READ_DOUBLE_BE(ptr)
#define DUK_HOBJECT_HAS_NEWENV(h)
DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs)
DUK_INTERNAL const char * duk_str_invalid_quantifier_values
DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key)
#define DUK_HOBJECT_CLEAR_ARRAY_PART(h)
#define DUK_HSTRING_HAS_ARRIDX(x)
DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc)
DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx)
#define DUK_STRIDX_MINUS_ZERO
DUK_INTERNAL_DECL duk_idx_t duk_push_object_internal(duk_context *ctx)
#define DUK_CATCHSTACK_SHRINK_THRESHOLD
#define DUK__VOLUNTARY_PERIODIC_GC(heap)
DUK_LOCAL void duk__free_allocated(duk_heap *heap)
#define DUK_STRIDX_INT_PC2LINE
#define DUK_STR_FUNC_NAME_REQUIRED
#define DUK_VALSTACK_API_ENTRY_MINIMUM
#define DUK_TVAL_SET_BOOLEAN_FALSE(v)
DUK_INTERNAL const char * duk_str_concat_result_too_long
#define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap)
DUK_EXTERNAL void duk_push_global_object(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx)
DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc)
#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, x, v)
DUK_INTERNAL int duk_repl_isfinite(double x)
DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t index)
#define DUK_LFUNC_NARGS_MIN
DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg)
DUK_LOCAL const duk_uint16_t duk__bufferobject_virtual_props[]
DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_context *ctx)
void *(* duk_mem_getptr)(duk_heap *heap, void *ud)
#define DUK_PROPDESC_FLAG_ENUMERABLE
DUK_INTERNAL duk_uint8_t duk_util_probe_steps[32]
DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p)
#define DUK_HBUFFEROBJECT_ELEM_FLOAT32
#define DUK__LOOKUP(lex_ctx, index)
DUK_LOCAL void duk__mark_refzero_list(duk_heap *heap)
DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_size_t act_idx, duk_tval *tv_val_unstable)
DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len)
#define DUK_TVAL_SET_FASTINT_I32(tv, val)
#define DUK_STR_FUNC_STMT_NOT_ALLOWED
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx)
DUK_INTERNAL_DECL duk_int_t duk_handle_call_protected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx)
#define DUK_STRIDX_INT8_ARRAY
#define DUK_HEAPHDR_CLEAR_REACHABLE(h)
DUK_INTERNAL int duk_repl_fpclassify(double x)
#define DUK_HSTRING_SET_INTERNAL(x)
#define DUK_PROPDESC_IS_ACCESSOR(p)
#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT
#define DUK_TVAL_GET_BOOLEAN(tv)
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)
#define DUK_CATCHSTACK_GROW_STEP
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx)
DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx)
DUK_INTERNAL_DECL void duk_hobject_define_property_helper(duk_context *ctx, duk_uint_t defprop_flags, duk_hobject *obj, duk_hstring *key, duk_idx_t idx_value, duk_hobject *get, duk_hobject *set)
DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_context *ctx, duk_small_int_t output_type)
#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap, h)
DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs)
static duk_uint16_t duk__buffer_elemtype_copy_compatible[9]
#define DUK_STRIDX_UC_POINTER
#define DUK_VALSTACK_DEFAULT_MAX
#define DUK_HOBJECT_E_USE_HASH_LIMIT
DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth)
DUK_EXTERNAL const char * duk_to_string(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_INTERNAL_DECL duk_tval * duk_get_borrowed_this_tval(duk_context *ctx)
DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx)
#define DUK_BC_DECLVAR_FLAG_FUNC_DECL
DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx)
#define DUK_RE_FLAG_IGNORE_CASE
DUK_INTERNAL_DECL void * duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud)
DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc)
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx)
#define DUK_STRIDX_TO_ISO_STRING
#define DUK_BW_WRITE_ENSURE_U8_2(thr, bw_ctx, val1, val2)
#define DUK_PROPDESC_IS_WRITABLE(p)
#define DUK_DBG_CMD_BASICINFO
DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const char * duk_str_reg_limit
#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap, h, i, v)
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP
DUK_LOCAL double duk__acos(double x)
DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp)
#define DUK_BW_INSERT_ENSURE_SLICE(thr, bw, dst_off, src_off, len)
#define DUK_TVAL_SET_BOOLEAN(tv, val)
#define DUK_GET_TVAL_POSIDX(ctx, idx)
#define DUK_HBUFFER_GET_DATA_PTR(heap, x)
#define DUK_HOBJECT_INCREF(thr, h)
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)
#define DUK_BW_WRITE_ENSURE_BYTES(thr, bw_ctx, valptr, valsz)
DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val)
DUK_INTERNAL const char * duk_str_invalid_var_declaration
#define DUK_CATCHSTACK_INITIAL_SIZE
DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, const void *udata)
#define DUK_S2N_FLAG_ALLOW_INF
DUK_INTERNAL const char * duk_str_string_too_long
struct duk_activation duk_activation
#define DUK_REALLOC(heap, ptr, newsize)
#define DUK_STRIDX_CONFIGURABLE
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx)
DUK_INTERNAL const char * duk_str_not_callable
#define DUK_STR_INVALID_THROW
#define DUK_STR_INVALID_LVALUE
#define DUK_ACT_GET_FUNC(act)
#define DUK__INTERNAL_ERROR(msg)
#define DUK__EMIT_FLAG_A_IS_SOURCE
#define DUK_HSTRING_SET_BYTELEN(x, v)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx)
DUK_EXTERNAL void duk_pop(duk_context *ctx)
#define DUK_STRIDX_INT_BYTECODE
DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32)
#define DUK_HBUFFER_FLAG_DYNAMIC
#define DUK_TVAL_SET_LIGHTFUNC(tv, fp, flags)
#define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap)
DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv)
#define DUK_HOBJECT_E_GET_VALUE(heap, h, i)
#define DUK_HOBJECT_SET_NAMEBINDING(h)
DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2)
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)
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx)
DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags)
DUK_INTERNAL_DECL void duk_push_hobject(duk_context *ctx, duk_hobject *h)
#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)
DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra)
#define DUK_STR_INVALID_DESCRIPTOR
#define DUK_TVAL_SET_UNDEFINED_UPDREF
#define DUK_HTHREAD_STRING_EMPTY_STRING(thr)
#define DUK_HEAPHDR_FLAG_FINALIZABLE
#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT
DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx)
DUK_LOCAL double duk__tan(double x)
#define DUK_HOBJECT_SET_HSIZE(h, v)
DUK_INTERNAL_DECL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags)
DUK_INTERNAL const char * duk_str_decode_failed
#define DUK_CAT_HAS_CATCH_ENABLED(c)
#define DUK_HTHREAD_STATE_YIELDED
#define DUK_HOBJECT_HASHIDX_DELETED
#define DUK_HOBJECT_HAS_ENVRECCLOSED(h)
DUK_INTERNAL_DECL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx)
DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256]
DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val)
DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx)
#define DUK__EMIT_FLAG_B_IS_TARGET
DUK_LOCAL duk_uint8_t duk__days_in_month[12]
DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y)
#define DUK_TVAL_GET_NUMBER(tv)
DUK_EXTERNAL void duk_debugger_attach_custom(duk_context *ctx, 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)
DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day)
DUK_EXTERNAL void * duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_uint_t mode)
#define DUK_HOBJECT_GET_CLASS_NUMBER(h)
#define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h)
#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags)
DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx)
DUK_INTERNAL const char * duk_str_not_configurable
#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags)
#define DUK__MAX_RE_DECESC_DIGITS
DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx)
#define DUK_FREE_RAW(heap, ptr)
DUK_INTERNAL_DECL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h)
#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)
static duk_uint16_t duk__date_magics[]
#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT
DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size)
DUK_INTERNAL const char * duk_str_invalid_quantifier_no_atom
DUK_LOCAL duk_hstring * duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash)
DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp)
DUK_EXTERNAL void duk_push_nan(duk_context *ctx)
#define DUK_CALL_FLAG_DIRECT_EVAL
#define DUK_TVAL_GET_HEAPHDR(tv)
#define DUK_HTHREAD_STRING_HEX(thr)
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)
#define DUK_STRIDX_VALUE_OF
DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count)
#define DUK_STRIDX_END_RESERVED
DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap)
#define DUK__READABLE_STRING_MAXCHARS
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx)
DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags)
DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx)
DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr)
DUK_INTERNAL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message)
#define DUK_DBG_CMD_GETHEAPOBJINFO
DUK_INTERNAL_DECL void duk_hthread_catchstack_grow(duk_hthread *thr)
DUK_EXTERNAL void duk_dump_function(duk_context *ctx)
#define DUK_HOBJECT_E_GET_FLAGS(heap, h, i)
#define DUK_LFUNC_MAGIC_MAX
DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap)
#define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED
DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx)
#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY
#define DUK_RAW_READ_U16_BE(ptr)
#define DUK_STR_SPRINTF_TOO_LONG
#define DUK_RETOK_ATOM_BACKREFERENCE
DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg)
DUK_INTERNAL const char * duk_str_parse_error
DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr)
DUK_INTERNAL const char * duk_str_redefine_virt_prop
DUK_INTERNAL_DECL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx)
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_small_int_t noblame_fileline, duk_hobject *obj)
DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags)
DUK_LOCAL void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_idx_t idx_z, duk_small_uint_fast_t opcode)
DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7]
#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)
#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h, i)
DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx)
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h)
DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags)
#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx)
DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL void * duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud)
#define DUK_CALLSTACK_GROW_STEP
DUK_LOCAL duk_codepoint_t duk__decode_hexesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset)
DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str)
#define DUK_JSON_FLAG_EXT_COMPATIBLE
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx)
#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)
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)
DUK_INTERNAL_DECL void duk_push_hstring(duk_context *ctx, duk_hstring *h)
DUK_INTERNAL_DECL duk_hstring * duk_get_hstring(duk_context *ctx, duk_idx_t index)
#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap, h)
#define DUK_ERROR(thr, err, msg)
DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx)
DUK_EXTERNAL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top)
DUK_INTERNAL_DECL duk_hobject * duk_push_this_coercible_to_object(duk_context *ctx)
DUK_INTERNAL const char * duk_str_array_length_not_writable
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)
#define DUK_BIDX_RANGE_ERROR_PROTOTYPE
#define DUK_STRTAB_U32_MAX_STRLEN
DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx)
#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)
DUK_INTERNAL const char * duk_str_invalid_base
#define DUK_S2N_FLAG_TRIM_WHITE
DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y)
#define DUK_BW_PUSH_AS_STRING(thr, bw_ctx)
DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr, duk_safe_call_function func, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_size_t entry_valstack_bottom_index, duk_size_t entry_callstack_top, duk_size_t entry_catchstack_top)
DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern)
DUK_LOCAL void duk__handle_break_or_continue(duk_hthread *thr, duk_uint_t label_id, duk_small_uint_t lj_type)
DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val)
DUK_LOCAL duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx)
#define DUK_STR_ENCODE_FAILED
DUK_INTERNAL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber)
#define DUK_CALLSTACK_INITIAL_SIZE
#define DUK_ERROR_RAW_FMT3(thr, file, line, err, fmt, arg1, arg2, arg3)
DUK_INTERNAL const char * duk_str_expected_identifier
DUK_INTERNAL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message)
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx)
DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type)
#define duk_hobject_get_internal_value_tval_ptr(heap, obj)
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)
DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index)
#define DUK_HEAP_SWITCH_THREAD(heap, newthr)
#define DUK_STR_BOUND_CHAIN_LIMIT
DUK_INTERNAL const char * duk_str_push_beyond_alloc_stack
DUK_INTERNAL_DECL duk_hstring * duk_require_hstring(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const char * duk_str_unexpected_regexp_token
DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg)
DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp)
DUK_LOCAL duk_uint8_t * duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h)
DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags)
DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16]
#define DUK_HTHREAD_STRING_LENGTH(thr)
#define DUK_BW_WRITE_ENSURE_CSTRING(thr, bw_ctx, val)
#define DUK_HOBJECT_GET_ESIZE(h)
DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx)
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)
#define DUK_HBUFFER_SET_SIZE(x, v)
#define DUK_HEAPHDR_HAS_FINALIZABLE(h)
#define DUK_TVAL_SET_UNDEFINED(tv)
#define DUK_STR_NOT_UNDEFINED
#define DUK_STRIDX_UC_ERROR
DUK_INTERNAL_DECL duk_hnativefunction * duk_require_hnativefunction(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t index, duk_small_int_t func_stridx)
const duk_uint8_t duk_unicode_idp_m_ids_noa[397]
#define DUK_STR_UNEXPECTED_TYPE
DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size)
#define DUK_PROPDESC_IS_CONFIGURABLE(p)
DUK_EXTERNAL duk_context * duk_get_context(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix)
DUK_INTERNAL_DECL void duk_heap_force_strtab_resize(duk_heap *heap)
DUK_LOCAL void duk__compact_objects(duk_heap *heap)
#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD
DUK_EXTERNAL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index)
#define DUK_HTHREAD_STRING_INT_FINALIZER(thr)
#define DUK_HEAPHDR_GET_NEXT(heap, h)
#define DUK_RE_MAX_ATOM_COPIES
#define DUK_HSTRING_FLAG_ARRIDX
DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep)
#define DUK_HTHREAD_STATE_TERMINATED
DUK_INTERNAL const char * duk_str_regexp_executor_step_limit
#define DUK_JSON_DEC_REQSTACK
#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x, v)
DUK_EXTERNAL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index)
DUK_LOCAL double duk__cos(double x)
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp)
DUK_LOCAL void duk__array_qsort(duk_context *ctx, duk_int_t lo, duk_int_t hi)
#define DUK__NUM_NORMAL_PROPS_BITS
#define DUK_HOBJECT_HAS_EXTENSIBLE(h)
DUK_INTERNAL const char * duk_str_no_sourcecode
DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_context *ctx, duk_idx_t index, duk_bool_t require)
DUK_INTERNAL const char * duk_str_invalid_lvalue
DUK_EXTERNAL void duk_get_prototype(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const char * duk_str_unexpected_closing_paren
DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst)
DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size)
#define DUK_HTHREAD_STRING_GET(thr)
#define DUK_HBUFFER_SET_DYNAMIC(x)
DUK_LOCAL duk_hbufferobject * duk__require_bufobj_value(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_uint8_t * duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func)
#define DUK_ERROR_INTERNAL(thr, msg)
DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase)
#define DUK_HOBJECT_H_GET_BASE(heap, h)
DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx)
#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO
#define DUK_DBG_ERR_APPLICATION
#define DUK_HTHREAD_STRING_INT_HANDLER(thr)
#define DUK_HOBJECT_CLASS_STRING
#define DUK_HBUFFER_HAS_EXTERNAL(x)
DUK_LOCAL_DECL void duk__emit_extraop_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b)
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT
#define DUK_RAW_WRITE_U32_BE(ptr, val)
DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx)
DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx, duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags, duk_small_int_t neg)
DUK_LOCAL duk_hthread * duk__get_temp_hthread(duk_heap *heap)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler)
DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs)
DUK_INTERNAL_DECL void * duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize)
#define DUK_HNATIVEFUNCTION_NARGS_MAX
DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32]
#define DUK_HBUFFER_HAS_DYNAMIC(x)
DUK_EXTERNAL const char * duk_require_string(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_CLASS_ARRAYBUFFER
DUK_INTERNAL_DECL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj)
#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP
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)
DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs)
#define DUK__UNEMIT_1(js_ctx)
#define DUK__UPDATE_RND(rnd)
DUK_EXTERNAL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap)
DUK_INTERNAL_DECL const char * duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv)
#define DUK_CAT_CLEAR_FINALLY_ENABLED(c)
DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_HAS_STRICT(h)
#define DUK_HTHREAD_STRING_INFINITY(thr)
#define DUK__RE_INITIAL_BUFSIZE
#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE
DUK_LOCAL void * duk__get_buffer_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag)
#define DUK_HTHREAD_STRING_INT_MAP(thr)
#define DUK_STR_INVALID_RETURN
double(* duk__one_arg_func)(double)
#define DUK_S2N_FLAG_ALLOW_EXP
#define DUK_HOBJECT_A_FAST_RESIZE_LIMIT
#define DUK_HOBJECT_CMASK_ARRAY
DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val)
DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h)
#define DUK_BW_ENSURE_GETPTR(thr, bw_ctx, sz)
DUK_EXTERNAL void duk_debugger_pause(duk_context *ctx)
DUK_LOCAL duk_uint8_t * duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst)
#define DUK_HOBJECT_CLASS_DATAVIEW
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx)
#define DUK_STRIDX_INT_SOURCE
#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap, h)
#define DUK_HOBJECT_P_ALLOC_SIZE(h)
DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index)
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap, x)
struct duk_lexer_codepoint duk_lexer_codepoint
DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata)
#define DUK_STR_DUPLICATE_LABEL
#define DUK_HOBJECT_E_MIN_GROW_ADD
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)
DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx)
DUK_EXTERNAL void * duk_realloc(duk_context *ctx, void *ptr, duk_size_t size)
DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr)
DUK_INTERNAL_DECL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits)
#define DUK_STR_INVALID_OBJECT_LITERAL
#define DUK_STR_UNEXPECTED_CLOSING_PAREN
#define DUK_HOBJECT_HAS_NOTAIL(h)
DUK_LOCAL_DECL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase)
DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap)
DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p)
DUK_LOCAL double duk__atan2(double x, double y)
DUK_INTERNAL_DECL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h)
#define DUK_HOBJECT_SET_NEWENV(h)
#define DUK_HOBJECT_SET_CLASS_NUMBER(h, v)
#define DUK_STR_PROXY_REVOKED
#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap, h, i)
DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr)
DUK_INTERNAL const duk_int8_t duk_base64_dectab[256]
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx)
#define DUK_RAW_READ_U32_BE(ptr)
DUK_LOCAL_DECL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num)
#define DUK_HEAP_DBG_RATELIMIT_MILLISECS
DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x)
#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT
DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_context *ctx)
#define DUK__EMIT_FLAG_C_IS_TARGET
DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size)
#define DUK_JSON_FLAG_ASCII_ONLY
#define DUK_MS_FLAG_SKIP_FINALIZERS
DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes)
DUK_INTERNAL_DECL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags)
#define DUK_STRIDX_NEWLINE_4SPACE
#define DUK__MKESC(nybbles, esc1, esc2)
DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr)
DUK_LOCAL duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x)
DUK_INTERNAL const char * duk_str_regexp_compiler_recursion_limit
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg, duk_small_uint_t flags)
#define DUK_CATCHSTACK_SHRINK_SPARE
DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val)
DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x)
#define DUK_EQUALS_FLAG_STRICT
DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr)
#define DUK_HSTRING_GET_ARRIDX_SLOW(h)
#define DUK_TVAL_GET_DOUBLE(tv)
#define DUK_BIDX_DATE_PROTOTYPE
DUK_LOCAL duk_hbufferobject * duk__require_bufobj_this(duk_context *ctx)
DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next)
DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb)
DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h)
DUK_EXTERNAL duk_context * 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)
DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n)
#define DUK_HOBJECT_INCREF_ALLOWNULL(thr, h)
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags)
#define DUK_VALSTACK_SHRINK_SPARE
DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, va_list ap)
#define DUK__PROP_TYPE_BOOLEAN_FALSE
DUK_EXTERNAL duk_context * duk_require_context(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128]
DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_idx_t idx_start, duk_idx_t idx_end, duk_int_t *out_start_offset, duk_int_t *out_end_offset)
#define DUK__PROP_TYPE_BOOLEAN_TRUE
#define duk_push_u32(ctx, val)
#define DUK_HTHREAD_STRING_CALLER(thr)
#define DUK_HTHREAD_STRING_JC(thr)
struct duk_catcher duk_catcher
#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, preinc_idx, x)
DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx)
DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt,...)
#define DUK__OUTPUT_TYPE_TRACEBACK
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx)
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)
#define DUK__RND_BIT(rnd)
#define DUK_BIDX_INT16ARRAY_PROTOTYPE
DUK_INTERNAL const char * duk_str_func_limit
#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY
#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap, h, i)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx)
DUK_LOCAL void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z)
DUK_EXTERNAL void duk_config_buffer(duk_context *ctx, duk_idx_t index, void *ptr, duk_size_t len)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx)
DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size)
DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x)
#define DUK__STRING_LENGTH_BITS
#define DUK_TVAL_SET_STRING(tv, hptr)
DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx)
DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index)
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)
DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx)
DUK_INTERNAL const char * duk_str_invalid_context
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx)
#define DUK__EMIT_1(js_ctx, ch)
DUK_LOCAL void duk__set_bufobj_buffer(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_hbuffer *h_val)
#define DUK_ERROR_FMT1(thr, err, fmt, arg1)
DUK_LOCAL double duk__sqrt(double x)
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)
#define DUK__RE_BUFLEN(re_ctx)
DUK_INTERNAL const char * duk_str_invalid_backrefs
#define DUK_STR_UNIMPLEMENTED
DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx)
DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b)
static duk_uint8_t * duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p)
#define DUK_UNICODE_MAX_XUTF8_LENGTH
#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES
#define DUK__EMIT_FLAG_NO_SHUFFLE_C
#define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)
#define DUK_STR_INVALID_BACKREFS
#define DUK__ISCONST(comp_ctx, x)
#define DUK_TVAL_IS_BOOLEAN(tv)
#define DUK_BIDX_UINT16ARRAY_PROTOTYPE
DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv)
DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t index)
#define DUK_HSTRING_FLAG_INTERNAL
#define DUK__APPENDBUFFER(lex_ctx, x)
#define DUK__RECURSION_DECREASE(comp_ctx, thr)
#define DUK_TVAL_SET_NUMBER(tv, val)
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)
DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze)
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)
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)
DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx)
#define DUK_HBUFFER_GET_SIZE(x)
#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)
DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx)
DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count)
DUK_LOCAL duk_bool_t duk__key_is_lightfunc_ownprop(duk_hthread *thr, duk_hstring *key)
#define DUK_HBUFFEROBJECT_ELEM_INT8
DUK_INTERNAL_DECL duk_hobject * duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags)
#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx)
#define DUK__PROP_TYPE_UNDEFINED
#define DUK_BW_WRITE_ENSURE_XUTF8(thr, bw_ctx, cp)
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)
#define DUK_TVAL_SET_FASTINT_I32_UPDREF
#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap, h)
#define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap, h)
#define DUK_HBUFFEROBJECT_ELEM_UINT8
DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value)
#define DUK_HOBJECT_CLASS_FLOAT64ARRAY
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x)
#define DUK_VALSTACK_INTERNAL_EXTRA
DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline)
DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to)
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx)
DUK_INTERNAL_DECL void * duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize)
#define DUK_HOBJECT_FLAG_ARRAY_PART
#define DUK_BW_WRITE_ENSURE_CESU8(thr, bw_ctx, cp)
DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index)
DUK_EXTERNAL void * duk_alloc_raw(duk_context *ctx, duk_size_t size)
#define DUK_S2N_FLAG_ALLOW_GARBAGE
#define DUK_ERROR_RAW(thr, file, line, err, msg)
#define DUK_ASSERT_HEAPHDR_LINKS(heap, h)
DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr)
DUK_INTERNAL_DECL duk_tval * duk_get_tval(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
#define DUK_RAW_WRITE_XUTF8(ptr, val)
#define DUK_CALL_FLAG_IGNORE_RECLIMIT
DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname)
DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx)
DUK_LOCAL const duk_uint8_t * duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n)
#define DUK_STRIDX_UC_FUNCTION
#define DUK_HEAPHDR_CLEAR_TEMPROOT(h)
#define DUK_HOBJECT_HAS_NAMEBINDING(h)
DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags)
#define DUK__OUTPUT_TYPE_FILENAME
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx)
DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg)
DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx)
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)
#define DUK_BC_CALL_FLAG_TAILCALL
DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst)
#define DUK_STRIDX_JSON_EXT_POSINF
DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_context *ctx)
DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv)
DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx)
DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t idx_key)
DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len)
DUK_INTERNAL const char * duk_str_buffer_too_long
#define DUK_STRIDX_JSON_EXT_FUNCTION1
#define DUK_BW_INSERT_ENSURE_AREA(thr, bw, off, len)
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22]
#define DUK_STRIDX_UC_BUFFER
DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx)
#define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS
DUK_LOCAL_DECL duk_heaphdr * duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag)
DUK_INTERNAL_DECL duk_activation * duk_hthread_get_current_activation(duk_hthread *thr)
DUK_LOCAL duk_uint8_t * duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h)
#define DUK_STR_PROXY_REJECTED
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx)
#define DUK_DATE_FLAG_SUB1900
#define DUK_ENUM_ARRAY_INDICES_ONLY
#define DUK_STRING_PUSH_SAFE
#define duk_to_buffer(ctx, index, out_size)
duk_size_t(* duk_debug_read_function)(void *udata, char *buffer, duk_size_t length)
#define DUK_TYPE_MASK_STRING
#define DUK_DEFPROP_HAVE_GETTER
#define DUK_DBLUNION_SET_NAN(u)
void *(* duk_alloc_function)(void *udata, duk_size_t size)
#define DUK_ENUM_SORT_ARRAY_INDICES
#define DUK_DBLUNION_GET_LOW32(u)
#define DUK_BUF_FLAG_NOZERO
#define duk_is_primitive(ctx, index)
#define duk_push_thread(ctx)
#define DUK_ENUM_NO_PROXY_BEHAVIOR
void(* duk_debug_write_flush_function)(void *udata)
#define DUK_DBLUNION_SET_DOUBLE(u, v)
#define DUK_DATE_FLAG_TOSTRING_DATE
#define DUK_DEBUG_PROTOCOL_VERSION
void(* duk_fatal_function)(duk_context *ctx, duk_errcode_t code, const char *msg)
#define DUK_DATE_MSEC_100M_DAYS
#define DUK_DATE_FLAG_EQUIVYEAR
#define DUK_RET_UNCAUGHT_ERROR
#define duk_push_fixed_buffer(ctx, size)
#define DUK_TYPE_MASK_OBJECT
duk_codepoint_t(* duk_map_char_function)(void *udata, duk_codepoint_t codepoint)
#define DUK_BUF_MODE_DONTCARE
#define duk_require_callable(ctx, index)
#define DUK_DATE_MSEC_100M_DAYS_LEEWAY
#define duk_safe_to_string(ctx, index)
#define DUK_BUF_MODE_DYNAMIC
void(* duk_debug_detached_function)(void *udata)
#define DUK_DBLUNION_GET_DOUBLE(u)
#define DUK_DEFPROP_HAVE_VALUE
#define DUK_DBLUNION_IS_NORMALIZED(u)
#define DUK_DATE_MIN_ECMA_YEAR
#define DUK_DBLUNION_SET_HIGH32(u, v)
#define DUK_BUF_FLAG_DYNAMIC
#define DUK_RET_ALLOC_ERROR
void(* duk_free_function)(void *udata, void *ptr)
void(* duk_debug_read_flush_function)(void *udata)
#define DUK_COMPILE_NORESULT
void *(* duk_realloc_function)(void *udata, void *ptr, duk_size_t size)
#define DUK_TYPE_MASK_BUFFER
#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)
#define DUK_DATE_FLAG_LOCALTIME
#define DUK_DATE_FLAG_TIMESETTER
#define duk_eval_string(ctx, src)
#define DUK_TYPE_MASK_LIGHTFUNC
#define DUK_DEFPROP_CONFIGURABLE
#define DUK_BUF_FLAG_EXTERNAL
#define DUK_ERR_ALLOC_ERROR
#define DUK_DATE_FLAG_TOSTRING_LOCALE
#define DUK_DATE_FLAG_TOSTRING_TIME
#define DUK_DBLUNION_DOUBLE_NTOH(u)
#define DUK_RET_RANGE_ERROR
#define DUK_DEFPROP_HAVE_WRITABLE
#define DUK_RET_REFERENCE_ERROR
#define DUK_COMPILE_FUNCTION
#define DUK_ERR_INTERNAL_ERROR
duk_idx_t(* duk_debug_request_function)(duk_context *ctx, void *udata, duk_idx_t nvalues)
#define DUK_DBLUNION_GET_HIGH32(u)
#define DUK_RET_SYNTAX_ERROR
#define DUK_COMPILE_NOSOURCE
#define DUK_TYPE_MASK_NUMBER
#define DUK_RET_UNIMPLEMENTED_ERROR
#define DUK_ENUM_OWN_PROPERTIES_ONLY
#define DUK_BUFOBJ_CREATE_ARRBUF
duk_size_t(* duk_debug_peek_function)(void *udata)
#define DUK_ERR_SYNTAX_ERROR
#define duk_require_object_coercible(ctx, index)
#define DUK_ERR_RANGE_ERROR
#define duk_is_error(ctx, index)
#define DUK_ERR_UNIMPLEMENTED_ERROR
#define duk_push_buffer(ctx, size, dynamic)
#define DUK_TYPE_MASK_BOOLEAN
#define DUK_DATE_FLAG_NAN_TO_RANGE_ERROR
#define DUK_ERR_UNCAUGHT_ERROR
#define DUK_DBLUNION_SET_LOW32(u, v)
#define DUK_DATE_IDX_MILLISECOND
#define DUK_ENUM_INCLUDE_INTERNAL
#define DUK_TYPE_MASK_THROW
duk_size_t(* duk_debug_write_function)(void *udata, const char *buffer, duk_size_t length)
#define DUK_DEFPROP_HAVE_SETTER
#define DUK_DBLUNION_BSWAP64(u)
#define duk_to_fixed_buffer(ctx, index, out_size)
duk_ret_t(* duk_c_function)(duk_context *ctx)
#define DUK_DEFPROP_HAVE_CONFIGURABLE
#define DUK_DEFPROP_ENUMERABLE
#define DUK_THREAD_NEW_GLOBAL_ENV
#define DUK_ERR_ASSERTION_ERROR
#define DUK_RET_INTERNAL_ERROR
#define DUK_TYPE_MASK_POINTER
#define DUK_ERR_REFERENCE_ERROR
#define DUK_DEFPROP_HAVE_ENUMERABLE
#define DUK_DATE_IDX_NUM_PARTS
#define duk_is_callable(ctx, index)
#define duk_push_dynamic_buffer(ctx, size)
#define DUK_COMPILE_NOFILENAME
#define DUK_DATE_FLAG_YEAR_FIXUP
#define DUK_DATE_FLAG_NAN_TO_ZERO
#define DUK_ERR_UNSUPPORTED_ERROR
#define DUK_TYPE_MASK_UNDEFINED
#define DUK_DEFPROP_WRITABLE
void(* duk_decode_char_function)(void *udata, duk_codepoint_t codepoint)
#define duk_require_type_mask(ctx, index, mask)
#define DUK_RET_ASSERTION_ERROR
#define DUK_DATE_FLAG_ONEBASED
#define duk_eval_string_noresult(ctx, src)
duk_ret_t(* duk_safe_call_function)(duk_context *ctx)
#define DUK_RET_UNSUPPORTED_ERROR
#define DUK_DATE_MAX_ECMA_YEAR
#define DUK_ENUM_INCLUDE_NONENUMERABLE
#define DUK_DATE_FLAG_VALUE_SHIFT
#define DUK_ERROR_UNSUPPORTED_DEFMSG(thr)
DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h)
DUK_INTERNAL_DECL const char * duk_str_anon
const duk_uint8_t duk_unicode_ids_m_let_noabmp[24]
const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348]
const duk_uint8_t duk_unicode_ids_noabmp[611]
#define DUK_LEXER_BUFFER_SIZE
duk_int32_t duk_reg_t
#define DUK_HEAP_NUM_STRINGS
#define DUK_LEXER_WINDOW_SIZE
#define DUK_HEAP_MAX_BREAKPOINTS
duk_uint32_t duk_regconst_t
#define DUK_STRTAB_CHAIN_SIZE
duk_uint32_t duk_instr_t
#define DUK_HEAP_STRCACHE_SIZE
#define DUK_NUM_BUILTINS
#define NULL
Definition gmacros.h:924
json_t format(printf, 1, 2)))
const char * name
Definition lsqlite3.c:2154
int value
Definition lsqlite3.c:2155
#define next(ls)
lu_byte left
static int funcname(LexState *ls, expdesc *v)
#define curr_func(L)
static int str_len(lua_State *L)
static const char * match(MatchState *ms, const char *s, const char *p)
static void fatal(const char *message)
static void error(LoadState *S, const char *why)
#define mask(n)
static const luaL_Reg funcs[]
CURL_EXTERN CURLMcode curl_socket_t s
Definition multi.h:318
duk_uint32_t v[DUK__BI_MAX_PARTS]
duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS]
duk_idx_t nargs
duk_c_function value
const char * key
struct duk_hbuffer_fixed::@19::@20 s
union duk_hbuffer_fixed::@19 u
duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE]
duk_fatal_function fatal_func
duk_realloc_function realloc_func
duk_small_uint_t mark_and_sweep_base_flags
duk_hstring * strs[DUK_HEAP_NUM_STRINGS]
duk_alloc_function alloc_func
duk_hobject * builtins[DUK_NUM_BUILTINS]
duk_hobject * visiting[DUK_JSON_ENC_LOOPARRAY]
duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE]
duk_double_t value
const char * key
duk_hstring * str
duk_size_t listlen
duk_hstring ** strlist
union duk_strtab_entry::@21 u
union duk_tval_struct::@18 v
duk_hnativefunction * hnativefunction
duk_hcompiledfunction * hcompiledfunction