Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duktape-1.5.2/src/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#line 1 "duk_internal.h"
115/*
116 * Top-level include file to be used for all (internal) source files.
117 *
118 * Source files should not include individual header files, as they
119 * have not been designed to be individually included.
120 */
121
122#ifndef DUK_INTERNAL_H_INCLUDED
123#define DUK_INTERNAL_H_INCLUDED
124
125/*
126 * The 'duktape.h' header provides the public API, but also handles all
127 * compiler and platform specific feature detection, Duktape feature
128 * resolution, inclusion of system headers, etc. These have been merged
129 * because the public API is also dependent on e.g. detecting appropriate
130 * C types which is quite platform/compiler specific especially for a non-C99
131 * build. The public API is also dependent on the resolved feature set.
132 *
133 * Some actions taken by the merged header (such as including system headers)
134 * are not appropriate for building a user application. The define
135 * DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
136 * sections depending on what is being built.
137 */
138
139#define DUK_COMPILING_DUKTAPE
140#include "duktape.h"
141
142/*
143 * User declarations, e.g. prototypes for user functions used by Duktape
144 * macros. Concretely, if DUK_USE_PANIC_HANDLER is used and the macro
145 * value calls a user function, it needs to be declared for Duktape
146 * compilation to avoid warnings.
147 */
148
150
151/*
152 * Duktape includes (other than duk_features.h)
153 *
154 * The header files expect to be included in an order which satisfies header
155 * dependencies correctly (the headers themselves don't include any other
156 * includes). Forward declarations are used to break circular struct/typedef
157 * dependencies.
158 */
159
160#line 1 "duk_replacements.h"
161#ifndef DUK_REPLACEMENTS_H_INCLUDED
162#define DUK_REPLACEMENTS_H_INCLUDED
163
164#if !defined(DUK_SINGLE_FILE)
165#if defined(DUK_USE_COMPUTED_INFINITY)
166DUK_INTERNAL_DECL double duk_computed_infinity;
167#endif
168#if defined(DUK_USE_COMPUTED_NAN)
169DUK_INTERNAL_DECL double duk_computed_nan;
170#endif
171#if defined(DUK_USE_REPL_FPCLASSIFY)
173#endif
174#if defined(DUK_USE_REPL_SIGNBIT)
176#endif
177#if defined(DUK_USE_REPL_ISFINITE)
179#endif
180#if defined(DUK_USE_REPL_ISNAN)
182#endif
183#if defined(DUK_USE_REPL_ISINF)
185#endif
186#endif /* !DUK_SINGLE_FILE */
187
188#endif /* DUK_REPLACEMENTS_H_INCLUDED */
189#line 1 "duk_jmpbuf.h"
190/*
191 * Wrapper for jmp_buf.
192 *
193 * This is used because jmp_buf is an array type for backward compatibility.
194 * Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
195 * behave more intuitively.
196 *
197 * http://en.wikipedia.org/wiki/Setjmp.h#Member_types
198 */
199
200#ifndef DUK_JMPBUF_H_INCLUDED
201#define DUK_JMPBUF_H_INCLUDED
202
203#if defined(DUK_USE_CPP_EXCEPTIONS)
204struct duk_jmpbuf {
205 duk_small_int_t dummy; /* unused */
206};
207#else
208struct duk_jmpbuf {
210};
211#endif
212
213#endif /* DUK_JMPBUF_H_INCLUDED */
214#line 1 "duk_exception.h"
215/*
216 * Exception for Duktape internal throws when C++ exceptions are used
217 * for long control transfers.
218 *
219 * Doesn't inherit from any exception base class to minimize the chance
220 * that user code would accidentally catch this exception.
221 */
222
223#ifndef DUK_EXCEPTION_H_INCLUDED
224#define DUK_EXCEPTION_H_INCLUDED
225
226#if defined(DUK_USE_CPP_EXCEPTIONS)
227class duk_internal_exception {
228 /* intentionally empty */
229};
230#endif
231
232#endif /* DUK_EXCEPTION_H_INCLUDED */
233#line 1 "duk_forwdecl.h"
234/*
235 * Forward declarations for all Duktape structures.
236 */
237
238#ifndef DUK_FORWDECL_H_INCLUDED
239#define DUK_FORWDECL_H_INCLUDED
240
241/*
242 * Forward declarations
243 */
244
245#if defined(DUK_USE_CPP_EXCEPTIONS)
246class duk_internal_exception;
247#else
248struct duk_jmpbuf;
249#endif
250
251/* duk_tval intentionally skipped */
252struct duk_heaphdr;
253struct duk_heaphdr_string;
254struct duk_hstring;
256struct duk_hobject;
259struct duk_hthread;
260struct duk_hbufferobject;
261struct duk_hbuffer;
262struct duk_hbuffer_fixed;
265
266struct duk_propaccessor;
267union duk_propvalue;
268struct duk_propdesc;
269
270struct duk_heap;
271struct duk_breakpoint;
272
273struct duk_activation;
274struct duk_catcher;
275struct duk_strcache;
276struct duk_ljstate;
277struct duk_strtab_entry;
278
279#ifdef DUK_USE_DEBUG
280struct duk_fixedbuffer;
281#endif
282
283struct duk_bitdecoder_ctx;
284struct duk_bitencoder_ctx;
285struct duk_bufwriter_ctx;
286
287struct duk_token;
288struct duk_re_token;
289struct duk_lexer_point;
290struct duk_lexer_ctx;
292
293struct duk_compiler_instr;
294struct duk_compiler_func;
295struct duk_compiler_ctx;
296
297struct duk_re_matcher_ctx;
299
300#if defined(DUK_USE_CPP_EXCEPTIONS)
301/* no typedef */
302#else
303typedef struct duk_jmpbuf duk_jmpbuf;
304#endif
305
306/* duk_tval intentionally skipped */
320
324
325typedef struct duk_heap duk_heap;
327
333
334#ifdef DUK_USE_DEBUG
335typedef struct duk_fixedbuffer duk_fixedbuffer;
336#endif
337
341
342typedef struct duk_token duk_token;
347
351
354
355#endif /* DUK_FORWDECL_H_INCLUDED */
356#line 1 "duk_tval.h"
357/*
358 * Tagged type definition (duk_tval) and accessor macros.
359 *
360 * Access all fields through the accessor macros, as the representation
361 * is quite tricky.
362 *
363 * There are two packed type alternatives: an 8-byte representation
364 * based on an IEEE double (preferred for compactness), and a 12-byte
365 * representation (portability). The latter is needed also in e.g.
366 * 64-bit environments (it usually pads to 16 bytes per value).
367 *
368 * Selecting the tagged type format involves many trade-offs (memory
369 * use, size and performance of generated code, portability, etc),
370 * see doc/types.rst for a detailed discussion (especially of how the
371 * IEEE double format is used to pack tagged values).
372 *
373 * NB: because macro arguments are often expressions, macros should
374 * avoid evaluating their argument more than once.
375 */
376
377#ifndef DUK_TVAL_H_INCLUDED
378#define DUK_TVAL_H_INCLUDED
379
380/* sanity */
381#if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
382#error unsupported: cannot determine byte order variant
383#endif
384
385#if defined(DUK_USE_PACKED_TVAL)
386/* ======================================================================== */
387
388/*
389 * Packed 8-byte representation
390 */
391
392/* use duk_double_union as duk_tval directly */
393typedef union duk_double_union duk_tval;
394
395/* tags */
396#define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
397/* avoid tag 0xfff0, no risk of confusion with negative infinity */
398#if defined(DUK_USE_FASTINT)
399#define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
400#endif
401#define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */
402#define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */
403#define DUK_TAG_NULL 0xfff4UL /* embed: nothing */
404#define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */
405/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
406#define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */
407#define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */
408#define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */
409#define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */
410#define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */
411
412/* for convenience */
413#define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL
414#define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL
415
416/* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
417#if defined(DUK_USE_64BIT_OPS)
418#if defined(DUK_USE_DOUBLE_ME)
419#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
420 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
421 } while (0)
422#else
423#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
424 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
425 } while (0)
426#endif
427#else /* DUK_USE_64BIT_OPS */
428#define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag) do { \
429 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
430 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
431 } while (0)
432#endif /* DUK_USE_64BIT_OPS */
433
434#if defined(DUK_USE_64BIT_OPS)
435/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
436#if defined(DUK_USE_DOUBLE_ME)
437#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
438 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
439 ((duk_uint64_t) (flags)) | \
440 (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
441 } while (0)
442#else
443#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
444 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
445 (((duk_uint64_t) (flags)) << 32) | \
446 ((duk_uint64_t) (duk_uint32_t) (fp)); \
447 } while (0)
448#endif
449#else /* DUK_USE_64BIT_OPS */
450#define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags) do { \
451 (v)->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
452 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
453 } while (0)
454#endif /* DUK_USE_64BIT_OPS */
455
456#if defined(DUK_USE_FASTINT)
457/* Note: masking is done for 'i' to deal with negative numbers correctly */
458#if defined(DUK_USE_DOUBLE_ME)
459#define DUK__TVAL_SET_FASTINT(v,i) do { \
460 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
461 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
462 } while (0)
463#define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
464 (v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
465 (v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
466 } while (0)
467#else
468#define DUK__TVAL_SET_FASTINT(v,i) do { \
469 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & 0x0000ffffffffffffULL); \
470 } while (0)
471#define DUK__TVAL_SET_FASTINT_U32(v,i) do { \
472 (v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
473 } while (0)
474#endif
475
476#define DUK__TVAL_SET_FASTINT_I32(v,i) do { \
477 duk_int64_t duk__tmp = (duk_int64_t) (i); \
478 DUK_TVAL_SET_FASTINT((v), duk__tmp); \
479 } while (0)
480
481/* XXX: clumsy sign extend and masking of 16 topmost bits */
482#if defined(DUK_USE_DOUBLE_ME)
483#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)
484#else
485#define DUK__TVAL_GET_FASTINT(v) ((((duk_int64_t) (v)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
486#endif
487#define DUK__TVAL_GET_FASTINT_U32(v) ((v)->ui[DUK_DBL_IDX_UI1])
488#define DUK__TVAL_GET_FASTINT_I32(v) ((duk_int32_t) (v)->ui[DUK_DBL_IDX_UI1])
489#endif /* DUK_USE_FASTINT */
490
491#define DUK_TVAL_SET_UNDEFINED(v) do { \
492 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
493 } while (0)
494#define DUK_TVAL_SET_UNUSED(v) do { \
495 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
496 } while (0)
497#define DUK_TVAL_SET_NULL(v) do { \
498 (v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
499 } while (0)
500
501#define DUK_TVAL_SET_BOOLEAN(v,val) DUK_DBLUNION_SET_HIGH32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
502
503#define DUK_TVAL_SET_NAN(v) DUK_DBLUNION_SET_NAN_FULL((v))
504
505/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
506#if defined(DUK_USE_FASTINT)
507#define DUK_TVAL_SET_DOUBLE(v,d) do { \
508 duk_double_t duk__dblval; \
509 duk__dblval = (d); \
510 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
511 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
512 } while (0)
513#define DUK_TVAL_SET_FASTINT(v,i) DUK__TVAL_SET_FASTINT((v), (i))
514#define DUK_TVAL_SET_FASTINT_I32(v,i) DUK__TVAL_SET_FASTINT_I32((v), (i))
515#define DUK_TVAL_SET_FASTINT_U32(v,i) DUK__TVAL_SET_FASTINT_U32((v), (i))
516#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) duk_tval_set_number_chkfast((v), (d))
517#define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
518#define DUK_TVAL_CHKFAST_INPLACE(v) do { \
519 duk_tval *duk__tv; \
520 duk_double_t duk__d; \
521 duk__tv = (v); \
522 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
523 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
524 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
525 } \
526 } while (0)
527#else
528#define DUK_TVAL_SET_DOUBLE(v,d) do { \
529 duk_double_t duk__dblval; \
530 duk__dblval = (d); \
531 DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
532 DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
533 } while (0)
534#define DUK_TVAL_SET_FASTINT(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i)) /* XXX: fast int-to-double */
535#define DUK_TVAL_SET_FASTINT_I32(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
536#define DUK_TVAL_SET_FASTINT_U32(v,i) DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
537#define DUK_TVAL_SET_NUMBER_CHKFAST(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
538#define DUK_TVAL_SET_NUMBER(v,d) DUK_TVAL_SET_DOUBLE((v), (d))
539#define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
540#endif
541
542#define DUK_TVAL_SET_LIGHTFUNC(v,fp,flags) DUK__TVAL_SET_LIGHTFUNC((v), (fp), (flags))
543#define DUK_TVAL_SET_STRING(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_STRING)
544#define DUK_TVAL_SET_OBJECT(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_OBJECT)
545#define DUK_TVAL_SET_BUFFER(v,h) DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_BUFFER)
546#define DUK_TVAL_SET_POINTER(v,p) DUK__TVAL_SET_TAGGEDPOINTER((v), (p), DUK_TAG_POINTER)
547
548#define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
549
550/* getters */
551#define DUK_TVAL_GET_BOOLEAN(v) ((int) (v)->us[DUK_DBL_IDX_US1])
552#if defined(DUK_USE_FASTINT)
553#define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
554#define DUK_TVAL_GET_FASTINT(v) DUK__TVAL_GET_FASTINT((v))
555#define DUK_TVAL_GET_FASTINT_U32(v) DUK__TVAL_GET_FASTINT_U32((v))
556#define DUK_TVAL_GET_FASTINT_I32(v) DUK__TVAL_GET_FASTINT_I32((v))
557#define DUK_TVAL_GET_NUMBER(v) duk_tval_get_number_packed((v))
558#else
559#define DUK_TVAL_GET_NUMBER(v) ((v)->d)
560#define DUK_TVAL_GET_DOUBLE(v) ((v)->d)
561#endif
562#define DUK_TVAL_GET_LIGHTFUNC(v,out_fp,out_flags) do { \
563 (out_flags) = (v)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
564 (out_fp) = (duk_c_function) (v)->ui[DUK_DBL_IDX_UI1]; \
565 } while (0)
566#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(v) ((duk_c_function) ((v)->ui[DUK_DBL_IDX_UI1]))
567#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(v) (((int) (v)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
568#define DUK_TVAL_GET_STRING(v) ((duk_hstring *) (v)->vp[DUK_DBL_IDX_VP1])
569#define DUK_TVAL_GET_OBJECT(v) ((duk_hobject *) (v)->vp[DUK_DBL_IDX_VP1])
570#define DUK_TVAL_GET_BUFFER(v) ((duk_hbuffer *) (v)->vp[DUK_DBL_IDX_VP1])
571#define DUK_TVAL_GET_POINTER(v) ((void *) (v)->vp[DUK_DBL_IDX_VP1])
572#define DUK_TVAL_GET_HEAPHDR(v) ((duk_heaphdr *) (v)->vp[DUK_DBL_IDX_VP1])
573
574/* decoding */
575#define DUK_TVAL_GET_TAG(v) ((duk_small_uint_t) (v)->us[DUK_DBL_IDX_US0])
576
577#define DUK_TVAL_IS_UNDEFINED(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNDEFINED)
578#define DUK_TVAL_IS_UNUSED(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNUSED)
579#define DUK_TVAL_IS_NULL(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_NULL)
580#define DUK_TVAL_IS_BOOLEAN(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BOOLEAN)
581#define DUK_TVAL_IS_BOOLEAN_TRUE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
582#define DUK_TVAL_IS_BOOLEAN_FALSE(v) ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
583#define DUK_TVAL_IS_LIGHTFUNC(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_LIGHTFUNC)
584#define DUK_TVAL_IS_STRING(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_STRING)
585#define DUK_TVAL_IS_OBJECT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_OBJECT)
586#define DUK_TVAL_IS_BUFFER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BUFFER)
587#define DUK_TVAL_IS_POINTER(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_POINTER)
588#if defined(DUK_USE_FASTINT)
589/* 0xfff0 is -Infinity */
590#define DUK_TVAL_IS_DOUBLE(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
591#define DUK_TVAL_IS_FASTINT(v) (DUK_TVAL_GET_TAG((v)) == DUK_TAG_FASTINT)
592#define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff1UL)
593#else
594#define DUK_TVAL_IS_NUMBER(v) (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
595#define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
596#endif
597
598/* This is performance critical because it appears in every DECREF. */
599#define DUK_TVAL_IS_HEAP_ALLOCATED(v) (DUK_TVAL_GET_TAG((v)) >= DUK_TAG_STRING)
600
601#if defined(DUK_USE_FASTINT)
602DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
603#endif
604
605#else /* DUK_USE_PACKED_TVAL */
606/* ======================================================================== */
607
608/*
609 * Portable 12-byte representation
610 */
611
612/* Note: not initializing all bytes is normally not an issue: Duktape won't
613 * read or use the uninitialized bytes so valgrind won't issue warnings.
614 * In some special cases a harmless valgrind warning may be issued though.
615 * For example, the DumpHeap debugger command writes out a compiled function's
616 * 'data' area as is, including any uninitialized bytes, which causes a
617 * valgrind warning.
618 */
619
621
622struct duk_tval_struct {
625 union {
628#if defined(DUK_USE_FASTINT)
629 duk_int64_t fi; /* if present, forces 16-byte duk_tval */
630#endif
631 void *voidptr;
640 } v;
641};
642
643#define DUK__TAG_NUMBER 0 /* not exposed */
644#if defined(DUK_USE_FASTINT)
645#define DUK_TAG_FASTINT 1
646#endif
647#define DUK_TAG_UNDEFINED 2
648#define DUK_TAG_NULL 3
649#define DUK_TAG_BOOLEAN 4
650#define DUK_TAG_POINTER 5
651#define DUK_TAG_LIGHTFUNC 6
652#define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */
653#define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */
654#define DUK_TAG_OBJECT 9
655#define DUK_TAG_BUFFER 10
656
657/* DUK__TAG_NUMBER is intentionally first, as it is the default clause in code
658 * to support the 8-byte representation. Further, it is a non-heap-allocated
659 * type so it should come before DUK_TAG_STRING. Finally, it should not break
660 * the tag value ranges covered by case-clauses in a switch-case.
661 */
662
663/* setters */
664#define DUK_TVAL_SET_UNDEFINED(tv) do { \
665 (tv)->t = DUK_TAG_UNDEFINED; \
666 } while (0)
667
668#define DUK_TVAL_SET_UNUSED(tv) do { \
669 (tv)->t = DUK_TAG_UNUSED; \
670 } while (0)
671
672#define DUK_TVAL_SET_NULL(tv) do { \
673 (tv)->t = DUK_TAG_NULL; \
674 } while (0)
675
676#define DUK_TVAL_SET_BOOLEAN(tv,val) do { \
677 (tv)->t = DUK_TAG_BOOLEAN; \
678 (tv)->v.i = (val); \
679 } while (0)
680
681#if defined(DUK_USE_FASTINT)
682#define DUK_TVAL_SET_DOUBLE(tv,val) do { \
683 (tv)->t = DUK__TAG_NUMBER; \
684 (tv)->v.d = (val); \
685 } while (0)
686#define DUK_TVAL_SET_FASTINT(tv,val) do { \
687 (tv)->t = DUK_TAG_FASTINT; \
688 (tv)->v.fi = (val); \
689 } while (0)
690#define DUK_TVAL_SET_FASTINT_U32(tv,val) do { \
691 (tv)->t = DUK_TAG_FASTINT; \
692 (tv)->v.fi = (duk_int64_t) (val); \
693 } while (0)
694#define DUK_TVAL_SET_FASTINT_I32(tv,val) do { \
695 (tv)->t = DUK_TAG_FASTINT; \
696 (tv)->v.fi = (duk_int64_t) (val); \
697 } while (0)
698#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
699 duk_tval_set_number_chkfast((tv), (d))
700#define DUK_TVAL_SET_NUMBER(tv,val) \
701 DUK_TVAL_SET_DOUBLE((tv), (val))
702#define DUK_TVAL_CHKFAST_INPLACE(v) do { \
703 duk_tval *duk__tv; \
704 duk_double_t duk__d; \
705 duk__tv = (v); \
706 if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
707 duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
708 DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
709 } \
710 } while (0)
711#else
712#define DUK_TVAL_SET_DOUBLE(tv,d) \
713 DUK_TVAL_SET_NUMBER((tv), (d))
714#define DUK_TVAL_SET_FASTINT(tv,val) \
715 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */
716#define DUK_TVAL_SET_FASTINT_U32(tv,val) \
717 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
718#define DUK_TVAL_SET_FASTINT_I32(tv,val) \
719 DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
720#define DUK_TVAL_SET_NUMBER(tv,val) do { \
721 (tv)->t = DUK__TAG_NUMBER; \
722 (tv)->v.d = (val); \
723 } while (0)
724#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
725 DUK_TVAL_SET_NUMBER((tv), (d))
726#define DUK_TVAL_CHKFAST_INPLACE(v) do { } while (0)
727#endif /* DUK_USE_FASTINT */
728
729#define DUK_TVAL_SET_POINTER(tv,hptr) do { \
730 (tv)->t = DUK_TAG_POINTER; \
731 (tv)->v.voidptr = (hptr); \
732 } while (0)
733
734#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
735 (tv)->t = DUK_TAG_LIGHTFUNC; \
736 (tv)->v_extra = (flags); \
737 (tv)->v.lightfunc = (duk_c_function) (fp); \
738 } while (0)
739
740#define DUK_TVAL_SET_STRING(tv,hptr) do { \
741 (tv)->t = DUK_TAG_STRING; \
742 (tv)->v.hstring = (hptr); \
743 } while (0)
744
745#define DUK_TVAL_SET_OBJECT(tv,hptr) do { \
746 (tv)->t = DUK_TAG_OBJECT; \
747 (tv)->v.hobject = (hptr); \
748 } while (0)
749
750#define DUK_TVAL_SET_BUFFER(tv,hptr) do { \
751 (tv)->t = DUK_TAG_BUFFER; \
752 (tv)->v.hbuffer = (hptr); \
753 } while (0)
754
755#define DUK_TVAL_SET_NAN(tv) do { \
756 /* in non-packed representation we don't care about which NaN is used */ \
757 (tv)->t = DUK__TAG_NUMBER; \
758 (tv)->v.d = DUK_DOUBLE_NAN; \
759 } while (0)
760
761#define DUK_TVAL_SET_TVAL(v,x) do { *(v) = *(x); } while (0)
762
763/* getters */
764#define DUK_TVAL_GET_BOOLEAN(tv) ((tv)->v.i)
765#if defined(DUK_USE_FASTINT)
766#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
767#define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
768#define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
769#define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
770#if 0
771#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
772 (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
773 DUK_TVAL_GET_DOUBLE((tv)))
774#define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
775#else
776/* This seems reasonable overall. */
777#define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
778 duk_tval_get_number_unpacked_fastint((tv)) : \
779 DUK_TVAL_GET_DOUBLE((tv)))
780#endif
781#else
782#define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
783#define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
784#endif /* DUK_USE_FASTINT */
785#define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
786#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
787 (out_flags) = (duk_uint32_t) (tv)->v_extra; \
788 (out_fp) = (tv)->v.lightfunc; \
789 } while (0)
790#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
791#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) ((duk_uint32_t) ((tv)->v_extra))
792#define DUK_TVAL_GET_STRING(tv) ((tv)->v.hstring)
793#define DUK_TVAL_GET_OBJECT(tv) ((tv)->v.hobject)
794#define DUK_TVAL_GET_BUFFER(tv) ((tv)->v.hbuffer)
795#define DUK_TVAL_GET_HEAPHDR(tv) ((tv)->v.heaphdr)
796
797/* decoding */
798#define DUK_TVAL_GET_TAG(tv) ((tv)->t)
799#define DUK_TVAL_IS_UNDEFINED(tv) ((tv)->t == DUK_TAG_UNDEFINED)
800#define DUK_TVAL_IS_UNUSED(tv) ((tv)->t == DUK_TAG_UNUSED)
801#define DUK_TVAL_IS_NULL(tv) ((tv)->t == DUK_TAG_NULL)
802#define DUK_TVAL_IS_BOOLEAN(tv) ((tv)->t == DUK_TAG_BOOLEAN)
803#define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
804#define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
805#if defined(DUK_USE_FASTINT)
806#define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK__TAG_NUMBER)
807#define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
808#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER || \
809 (tv)->t == DUK_TAG_FASTINT)
810#else
811#define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK__TAG_NUMBER)
812#define DUK_TVAL_IS_DOUBLE(v) DUK_TVAL_IS_NUMBER((v))
813#endif /* DUK_USE_FASTINT */
814#define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
815#define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
816#define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
817#define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
818#define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
819
820/* This is performance critical because it's needed for every DECREF.
821 * Take advantage of the fact that the first heap allocated tag is 8,
822 * so that bit 3 is set for all heap allocated tags (and never set for
823 * non-heap-allocated tags).
824 */
825#if 0
826#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
827#endif
828#define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08)
829
830#if defined(DUK_USE_FASTINT)
831#if 0
832DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
833#endif
834DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
835#endif
836
837#endif /* DUK_USE_PACKED_TVAL */
838
839/*
840 * Convenience (independent of representation)
841 */
842
843#define DUK_TVAL_SET_BOOLEAN_TRUE(v) DUK_TVAL_SET_BOOLEAN(v, 1)
844#define DUK_TVAL_SET_BOOLEAN_FALSE(v) DUK_TVAL_SET_BOOLEAN(v, 0)
845
846/* Lightfunc flags packing and unpacking. */
847/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss## */
848#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
849 ((((duk_int32_t) (lf_flags)) << 16) >> 24)
850#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
851 (((lf_flags) >> 4) & 0x0f)
852#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
853 ((lf_flags) & 0x0f)
854#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
855 (((magic) & 0xff) << 8) | ((length) << 4) | (nargs)
856
857#define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
858#define DUK_LFUNC_NARGS_MIN 0x00
859#define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
860#define DUK_LFUNC_LENGTH_MIN 0x00
861#define DUK_LFUNC_LENGTH_MAX 0x0f
862#define DUK_LFUNC_MAGIC_MIN (-0x80)
863#define DUK_LFUNC_MAGIC_MAX 0x7f
864
865/* fastint constants etc */
866#if defined(DUK_USE_FASTINT)
867#define DUK_FASTINT_MIN (-0x800000000000LL)
868#define DUK_FASTINT_MAX 0x7fffffffffffLL
869#define DUK_FASTINT_BITS 48
870
871DUK_INTERNAL_DECL void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x);
872#endif
873
874#endif /* DUK_TVAL_H_INCLUDED */
875#line 1 "duk_builtins.h"
876/*
877 * Automatically generated by genbuiltins.py, do not edit!
878 */
879
880#ifndef DUK_BUILTINS_H_INCLUDED
881#define DUK_BUILTINS_H_INCLUDED
882
883#if defined(DUK_USE_ROM_STRINGS)
884#error ROM support not enabled, rerun make_dist.py with --rom-support
885#else /* DUK_USE_ROM_STRINGS */
886#define DUK_STRIDX_UC_UNDEFINED 0 /* 'Undefined' */
887#define DUK_HEAP_STRING_UC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
888#define DUK_HTHREAD_STRING_UC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
889#define DUK_STRIDX_UC_NULL 1 /* 'Null' */
890#define DUK_HEAP_STRING_UC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
891#define DUK_HTHREAD_STRING_UC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
892#define DUK_STRIDX_UC_ARGUMENTS 2 /* 'Arguments' */
893#define DUK_HEAP_STRING_UC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
894#define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
895#define DUK_STRIDX_UC_OBJECT 3 /* 'Object' */
896#define DUK_HEAP_STRING_UC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
897#define DUK_HTHREAD_STRING_UC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
898#define DUK_STRIDX_UC_FUNCTION 4 /* 'Function' */
899#define DUK_HEAP_STRING_UC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
900#define DUK_HTHREAD_STRING_UC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
901#define DUK_STRIDX_ARRAY 5 /* 'Array' */
902#define DUK_HEAP_STRING_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
903#define DUK_HTHREAD_STRING_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
904#define DUK_STRIDX_UC_STRING 6 /* 'String' */
905#define DUK_HEAP_STRING_UC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
906#define DUK_HTHREAD_STRING_UC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
907#define DUK_STRIDX_UC_BOOLEAN 7 /* 'Boolean' */
908#define DUK_HEAP_STRING_UC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
909#define DUK_HTHREAD_STRING_UC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
910#define DUK_STRIDX_UC_NUMBER 8 /* 'Number' */
911#define DUK_HEAP_STRING_UC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
912#define DUK_HTHREAD_STRING_UC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
913#define DUK_STRIDX_DATE 9 /* 'Date' */
914#define DUK_HEAP_STRING_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
915#define DUK_HTHREAD_STRING_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
916#define DUK_STRIDX_REG_EXP 10 /* 'RegExp' */
917#define DUK_HEAP_STRING_REG_EXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
918#define DUK_HTHREAD_STRING_REG_EXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
919#define DUK_STRIDX_UC_ERROR 11 /* 'Error' */
920#define DUK_HEAP_STRING_UC_ERROR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
921#define DUK_HTHREAD_STRING_UC_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
922#define DUK_STRIDX_MATH 12 /* 'Math' */
923#define DUK_HEAP_STRING_MATH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
924#define DUK_HTHREAD_STRING_MATH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
925#define DUK_STRIDX_JSON 13 /* 'JSON' */
926#define DUK_HEAP_STRING_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
927#define DUK_HTHREAD_STRING_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
928#define DUK_STRIDX_EMPTY_STRING 14 /* '' */
929#define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
930#define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
931#define DUK_STRIDX_ARRAY_BUFFER 15 /* 'ArrayBuffer' */
932#define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
933#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
934#define DUK_STRIDX_DATA_VIEW 16 /* 'DataView' */
935#define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
936#define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
937#define DUK_STRIDX_INT8_ARRAY 17 /* 'Int8Array' */
938#define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
939#define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
940#define DUK_STRIDX_UINT8_ARRAY 18 /* 'Uint8Array' */
941#define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
942#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
943#define DUK_STRIDX_UINT8_CLAMPED_ARRAY 19 /* 'Uint8ClampedArray' */
944#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
945#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
946#define DUK_STRIDX_INT16_ARRAY 20 /* 'Int16Array' */
947#define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
948#define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
949#define DUK_STRIDX_UINT16_ARRAY 21 /* 'Uint16Array' */
950#define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
951#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
952#define DUK_STRIDX_INT32_ARRAY 22 /* 'Int32Array' */
953#define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
954#define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
955#define DUK_STRIDX_UINT32_ARRAY 23 /* 'Uint32Array' */
956#define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
957#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
958#define DUK_STRIDX_FLOAT32_ARRAY 24 /* 'Float32Array' */
959#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
960#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
961#define DUK_STRIDX_FLOAT64_ARRAY 25 /* 'Float64Array' */
962#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
963#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
964#define DUK_STRIDX_GLOBAL 26 /* 'global' */
965#define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
966#define DUK_HTHREAD_STRING_GLOBAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
967#define DUK_STRIDX_OBJ_ENV 27 /* 'ObjEnv' */
968#define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
969#define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
970#define DUK_STRIDX_DEC_ENV 28 /* 'DecEnv' */
971#define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
972#define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
973#define DUK_STRIDX_UC_BUFFER 29 /* 'Buffer' */
974#define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
975#define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
976#define DUK_STRIDX_UC_POINTER 30 /* 'Pointer' */
977#define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
978#define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
979#define DUK_STRIDX_UC_THREAD 31 /* 'Thread' */
980#define DUK_HEAP_STRING_UC_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
981#define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
982#define DUK_STRIDX_EVAL 32 /* 'eval' */
983#define DUK_HEAP_STRING_EVAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
984#define DUK_HTHREAD_STRING_EVAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
985#define DUK_STRIDX_DEFINE_PROPERTY 33 /* 'defineProperty' */
986#define DUK_HEAP_STRING_DEFINE_PROPERTY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFINE_PROPERTY)
987#define DUK_HTHREAD_STRING_DEFINE_PROPERTY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFINE_PROPERTY)
988#define DUK_STRIDX_VALUE 34 /* 'value' */
989#define DUK_HEAP_STRING_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
990#define DUK_HTHREAD_STRING_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
991#define DUK_STRIDX_WRITABLE 35 /* 'writable' */
992#define DUK_HEAP_STRING_WRITABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
993#define DUK_HTHREAD_STRING_WRITABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
994#define DUK_STRIDX_CONFIGURABLE 36 /* 'configurable' */
995#define DUK_HEAP_STRING_CONFIGURABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
996#define DUK_HTHREAD_STRING_CONFIGURABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
997#define DUK_STRIDX_ENUMERABLE 37 /* 'enumerable' */
998#define DUK_HEAP_STRING_ENUMERABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
999#define DUK_HTHREAD_STRING_ENUMERABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1000#define DUK_STRIDX_JOIN 38 /* 'join' */
1001#define DUK_HEAP_STRING_JOIN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1002#define DUK_HTHREAD_STRING_JOIN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1003#define DUK_STRIDX_TO_LOCALE_STRING 39 /* 'toLocaleString' */
1004#define DUK_HEAP_STRING_TO_LOCALE_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1005#define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1006#define DUK_STRIDX_VALUE_OF 40 /* 'valueOf' */
1007#define DUK_HEAP_STRING_VALUE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1008#define DUK_HTHREAD_STRING_VALUE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1009#define DUK_STRIDX_TO_UTC_STRING 41 /* 'toUTCString' */
1010#define DUK_HEAP_STRING_TO_UTC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1011#define DUK_HTHREAD_STRING_TO_UTC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1012#define DUK_STRIDX_TO_ISO_STRING 42 /* 'toISOString' */
1013#define DUK_HEAP_STRING_TO_ISO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1014#define DUK_HTHREAD_STRING_TO_ISO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1015#define DUK_STRIDX_TO_GMT_STRING 43 /* 'toGMTString' */
1016#define DUK_HEAP_STRING_TO_GMT_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1017#define DUK_HTHREAD_STRING_TO_GMT_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1018#define DUK_STRIDX_SOURCE 44 /* 'source' */
1019#define DUK_HEAP_STRING_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1020#define DUK_HTHREAD_STRING_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1021#define DUK_STRIDX_IGNORE_CASE 45 /* 'ignoreCase' */
1022#define DUK_HEAP_STRING_IGNORE_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1023#define DUK_HTHREAD_STRING_IGNORE_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1024#define DUK_STRIDX_MULTILINE 46 /* 'multiline' */
1025#define DUK_HEAP_STRING_MULTILINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1026#define DUK_HTHREAD_STRING_MULTILINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1027#define DUK_STRIDX_LAST_INDEX 47 /* 'lastIndex' */
1028#define DUK_HEAP_STRING_LAST_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1029#define DUK_HTHREAD_STRING_LAST_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1030#define DUK_STRIDX_ESCAPED_EMPTY_REGEXP 48 /* '(?:)' */
1031#define DUK_HEAP_STRING_ESCAPED_EMPTY_REGEXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ESCAPED_EMPTY_REGEXP)
1032#define DUK_HTHREAD_STRING_ESCAPED_EMPTY_REGEXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ESCAPED_EMPTY_REGEXP)
1033#define DUK_STRIDX_INDEX 49 /* 'index' */
1034#define DUK_HEAP_STRING_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1035#define DUK_HTHREAD_STRING_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1036#define DUK_STRIDX_PROTOTYPE 50 /* 'prototype' */
1037#define DUK_HEAP_STRING_PROTOTYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1038#define DUK_HTHREAD_STRING_PROTOTYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1039#define DUK_STRIDX_CONSTRUCTOR 51 /* 'constructor' */
1040#define DUK_HEAP_STRING_CONSTRUCTOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1041#define DUK_HTHREAD_STRING_CONSTRUCTOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1042#define DUK_STRIDX_MESSAGE 52 /* 'message' */
1043#define DUK_HEAP_STRING_MESSAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1044#define DUK_HTHREAD_STRING_MESSAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1045#define DUK_STRIDX_LC_BOOLEAN 53 /* 'boolean' */
1046#define DUK_HEAP_STRING_LC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1047#define DUK_HTHREAD_STRING_LC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1048#define DUK_STRIDX_LC_NUMBER 54 /* 'number' */
1049#define DUK_HEAP_STRING_LC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1050#define DUK_HTHREAD_STRING_LC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1051#define DUK_STRIDX_LC_STRING 55 /* 'string' */
1052#define DUK_HEAP_STRING_LC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1053#define DUK_HTHREAD_STRING_LC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1054#define DUK_STRIDX_LC_OBJECT 56 /* 'object' */
1055#define DUK_HEAP_STRING_LC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1056#define DUK_HTHREAD_STRING_LC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1057#define DUK_STRIDX_LC_UNDEFINED 57 /* 'undefined' */
1058#define DUK_HEAP_STRING_LC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1059#define DUK_HTHREAD_STRING_LC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1060#define DUK_STRIDX_NAN 58 /* 'NaN' */
1061#define DUK_HEAP_STRING_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1062#define DUK_HTHREAD_STRING_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1063#define DUK_STRIDX_INFINITY 59 /* 'Infinity' */
1064#define DUK_HEAP_STRING_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1065#define DUK_HTHREAD_STRING_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1066#define DUK_STRIDX_MINUS_INFINITY 60 /* '-Infinity' */
1067#define DUK_HEAP_STRING_MINUS_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1068#define DUK_HTHREAD_STRING_MINUS_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1069#define DUK_STRIDX_MINUS_ZERO 61 /* '-0' */
1070#define DUK_HEAP_STRING_MINUS_ZERO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1071#define DUK_HTHREAD_STRING_MINUS_ZERO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1072#define DUK_STRIDX_COMMA 62 /* ',' */
1073#define DUK_HEAP_STRING_COMMA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1074#define DUK_HTHREAD_STRING_COMMA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1075#define DUK_STRIDX_SPACE 63 /* ' ' */
1076#define DUK_HEAP_STRING_SPACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SPACE)
1077#define DUK_HTHREAD_STRING_SPACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SPACE)
1078#define DUK_STRIDX_NEWLINE_4SPACE 64 /* '\n ' */
1079#define DUK_HEAP_STRING_NEWLINE_4SPACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1080#define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1081#define DUK_STRIDX_BRACKETED_ELLIPSIS 65 /* '[...]' */
1082#define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1083#define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1084#define DUK_STRIDX_INVALID_DATE 66 /* 'Invalid Date' */
1085#define DUK_HEAP_STRING_INVALID_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1086#define DUK_HTHREAD_STRING_INVALID_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1087#define DUK_STRIDX_LC_ARGUMENTS 67 /* 'arguments' */
1088#define DUK_HEAP_STRING_LC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1089#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1090#define DUK_STRIDX_CALLEE 68 /* 'callee' */
1091#define DUK_HEAP_STRING_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1092#define DUK_HTHREAD_STRING_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1093#define DUK_STRIDX_CALLER 69 /* 'caller' */
1094#define DUK_HEAP_STRING_CALLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1095#define DUK_HTHREAD_STRING_CALLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1096#define DUK_STRIDX_HAS 70 /* 'has' */
1097#define DUK_HEAP_STRING_HAS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1098#define DUK_HTHREAD_STRING_HAS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1099#define DUK_STRIDX_GET 71 /* 'get' */
1100#define DUK_HEAP_STRING_GET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1101#define DUK_HTHREAD_STRING_GET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1102#define DUK_STRIDX_DELETE_PROPERTY 72 /* 'deleteProperty' */
1103#define DUK_HEAP_STRING_DELETE_PROPERTY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1104#define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1105#define DUK_STRIDX_ENUMERATE 73 /* 'enumerate' */
1106#define DUK_HEAP_STRING_ENUMERATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERATE)
1107#define DUK_HTHREAD_STRING_ENUMERATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERATE)
1108#define DUK_STRIDX_OWN_KEYS 74 /* 'ownKeys' */
1109#define DUK_HEAP_STRING_OWN_KEYS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1110#define DUK_HTHREAD_STRING_OWN_KEYS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1111#define DUK_STRIDX_SET_PROTOTYPE_OF 75 /* 'setPrototypeOf' */
1112#define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1113#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1114#define DUK_STRIDX___PROTO__ 76 /* '__proto__' */
1115#define DUK_HEAP_STRING___PROTO__(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1116#define DUK_HTHREAD_STRING___PROTO__(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1117#define DUK_STRIDX_REQUIRE 77 /* 'require' */
1118#define DUK_HEAP_STRING_REQUIRE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE)
1119#define DUK_HTHREAD_STRING_REQUIRE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REQUIRE)
1120#define DUK_STRIDX_ID 78 /* 'id' */
1121#define DUK_HEAP_STRING_ID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID)
1122#define DUK_HTHREAD_STRING_ID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID)
1123#define DUK_STRIDX_EXPORTS 79 /* 'exports' */
1124#define DUK_HEAP_STRING_EXPORTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS)
1125#define DUK_HTHREAD_STRING_EXPORTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS)
1126#define DUK_STRIDX_FILENAME 80 /* 'filename' */
1127#define DUK_HEAP_STRING_FILENAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILENAME)
1128#define DUK_HTHREAD_STRING_FILENAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILENAME)
1129#define DUK_STRIDX_TO_STRING 81 /* 'toString' */
1130#define DUK_HEAP_STRING_TO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1131#define DUK_HTHREAD_STRING_TO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1132#define DUK_STRIDX_TO_JSON 82 /* 'toJSON' */
1133#define DUK_HEAP_STRING_TO_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1134#define DUK_HTHREAD_STRING_TO_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1135#define DUK_STRIDX_TYPE 83 /* 'type' */
1136#define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1137#define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1138#define DUK_STRIDX_DATA 84 /* 'data' */
1139#define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1140#define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1141#define DUK_STRIDX_LENGTH 85 /* 'length' */
1142#define DUK_HEAP_STRING_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1143#define DUK_HTHREAD_STRING_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1144#define DUK_STRIDX_BYTE_LENGTH 86 /* 'byteLength' */
1145#define DUK_HEAP_STRING_BYTE_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH)
1146#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH)
1147#define DUK_STRIDX_BYTE_OFFSET 87 /* 'byteOffset' */
1148#define DUK_HEAP_STRING_BYTE_OFFSET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET)
1149#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET)
1150#define DUK_STRIDX_BYTES_PER_ELEMENT 88 /* 'BYTES_PER_ELEMENT' */
1151#define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT)
1152#define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT)
1153#define DUK_STRIDX_SET 89 /* 'set' */
1154#define DUK_HEAP_STRING_SET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1155#define DUK_HTHREAD_STRING_SET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1156#define DUK_STRIDX_STACK 90 /* 'stack' */
1157#define DUK_HEAP_STRING_STACK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1158#define DUK_HTHREAD_STRING_STACK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1159#define DUK_STRIDX_PC 91 /* 'pc' */
1160#define DUK_HEAP_STRING_PC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1161#define DUK_HTHREAD_STRING_PC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1162#define DUK_STRIDX_LINE_NUMBER 92 /* 'lineNumber' */
1163#define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1164#define DUK_HTHREAD_STRING_LINE_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1165#define DUK_STRIDX_INT_TRACEDATA 93 /* '\xffTracedata' */
1166#define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1167#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1168#define DUK_STRIDX_NAME 94 /* 'name' */
1169#define DUK_HEAP_STRING_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1170#define DUK_HTHREAD_STRING_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1171#define DUK_STRIDX_FILE_NAME 95 /* 'fileName' */
1172#define DUK_HEAP_STRING_FILE_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1173#define DUK_HTHREAD_STRING_FILE_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1174#define DUK_STRIDX_LC_BUFFER 96 /* 'buffer' */
1175#define DUK_HEAP_STRING_LC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
1176#define DUK_HTHREAD_STRING_LC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
1177#define DUK_STRIDX_LC_POINTER 97 /* 'pointer' */
1178#define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1179#define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1180#define DUK_STRIDX_INT_VALUE 98 /* '\xffValue' */
1181#define DUK_HEAP_STRING_INT_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1182#define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1183#define DUK_STRIDX_INT_NEXT 99 /* '\xffNext' */
1184#define DUK_HEAP_STRING_INT_NEXT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1185#define DUK_HTHREAD_STRING_INT_NEXT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1186#define DUK_STRIDX_INT_BYTECODE 100 /* '\xffBytecode' */
1187#define DUK_HEAP_STRING_INT_BYTECODE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1188#define DUK_HTHREAD_STRING_INT_BYTECODE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1189#define DUK_STRIDX_INT_FORMALS 101 /* '\xffFormals' */
1190#define DUK_HEAP_STRING_INT_FORMALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1191#define DUK_HTHREAD_STRING_INT_FORMALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1192#define DUK_STRIDX_INT_VARMAP 102 /* '\xffVarmap' */
1193#define DUK_HEAP_STRING_INT_VARMAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1194#define DUK_HTHREAD_STRING_INT_VARMAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1195#define DUK_STRIDX_INT_LEXENV 103 /* '\xffLexenv' */
1196#define DUK_HEAP_STRING_INT_LEXENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_LEXENV)
1197#define DUK_HTHREAD_STRING_INT_LEXENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_LEXENV)
1198#define DUK_STRIDX_INT_VARENV 104 /* '\xffVarenv' */
1199#define DUK_HEAP_STRING_INT_VARENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1200#define DUK_HTHREAD_STRING_INT_VARENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1201#define DUK_STRIDX_INT_SOURCE 105 /* '\xffSource' */
1202#define DUK_HEAP_STRING_INT_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1203#define DUK_HTHREAD_STRING_INT_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1204#define DUK_STRIDX_INT_PC2LINE 106 /* '\xffPc2line' */
1205#define DUK_HEAP_STRING_INT_PC2LINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1206#define DUK_HTHREAD_STRING_INT_PC2LINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1207#define DUK_STRIDX_INT_ARGS 107 /* '\xffArgs' */
1208#define DUK_HEAP_STRING_INT_ARGS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_ARGS)
1209#define DUK_HTHREAD_STRING_INT_ARGS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_ARGS)
1210#define DUK_STRIDX_INT_MAP 108 /* '\xffMap' */
1211#define DUK_HEAP_STRING_INT_MAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1212#define DUK_HTHREAD_STRING_INT_MAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1213#define DUK_STRIDX_INT_FINALIZER 109 /* '\xffFinalizer' */
1214#define DUK_HEAP_STRING_INT_FINALIZER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1215#define DUK_HTHREAD_STRING_INT_FINALIZER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1216#define DUK_STRIDX_INT_HANDLER 110 /* '\xffHandler' */
1217#define DUK_HEAP_STRING_INT_HANDLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_HANDLER)
1218#define DUK_HTHREAD_STRING_INT_HANDLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_HANDLER)
1219#define DUK_STRIDX_INT_CALLEE 111 /* '\xffCallee' */
1220#define DUK_HEAP_STRING_INT_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_CALLEE)
1221#define DUK_HTHREAD_STRING_INT_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_CALLEE)
1222#define DUK_STRIDX_INT_THREAD 112 /* '\xffThread' */
1223#define DUK_HEAP_STRING_INT_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THREAD)
1224#define DUK_HTHREAD_STRING_INT_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THREAD)
1225#define DUK_STRIDX_INT_REGBASE 113 /* '\xffRegbase' */
1226#define DUK_HEAP_STRING_INT_REGBASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_REGBASE)
1227#define DUK_HTHREAD_STRING_INT_REGBASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_REGBASE)
1228#define DUK_STRIDX_INT_TARGET 114 /* '\xffTarget' */
1229#define DUK_HEAP_STRING_INT_TARGET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1230#define DUK_HTHREAD_STRING_INT_TARGET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1231#define DUK_STRIDX_INT_THIS 115 /* '\xffThis' */
1232#define DUK_HEAP_STRING_INT_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THIS)
1233#define DUK_HTHREAD_STRING_INT_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THIS)
1234#define DUK_STRIDX_COMPILE 116 /* 'compile' */
1235#define DUK_HEAP_STRING_COMPILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1236#define DUK_HTHREAD_STRING_COMPILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1237#define DUK_STRIDX_INPUT 117 /* 'input' */
1238#define DUK_HEAP_STRING_INPUT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1239#define DUK_HTHREAD_STRING_INPUT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1240#define DUK_STRIDX_ERR_CREATE 118 /* 'errCreate' */
1241#define DUK_HEAP_STRING_ERR_CREATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1242#define DUK_HTHREAD_STRING_ERR_CREATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1243#define DUK_STRIDX_ERR_THROW 119 /* 'errThrow' */
1244#define DUK_HEAP_STRING_ERR_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1245#define DUK_HTHREAD_STRING_ERR_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1246#define DUK_STRIDX_MOD_SEARCH 120 /* 'modSearch' */
1247#define DUK_HEAP_STRING_MOD_SEARCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MOD_SEARCH)
1248#define DUK_HTHREAD_STRING_MOD_SEARCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MOD_SEARCH)
1249#define DUK_STRIDX_MOD_LOADED 121 /* 'modLoaded' */
1250#define DUK_HEAP_STRING_MOD_LOADED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MOD_LOADED)
1251#define DUK_HTHREAD_STRING_MOD_LOADED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MOD_LOADED)
1252#define DUK_STRIDX_ENV 122 /* 'env' */
1253#define DUK_HEAP_STRING_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1254#define DUK_HTHREAD_STRING_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1255#define DUK_STRIDX_HEX 123 /* 'hex' */
1256#define DUK_HEAP_STRING_HEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1257#define DUK_HTHREAD_STRING_HEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1258#define DUK_STRIDX_BASE64 124 /* 'base64' */
1259#define DUK_HEAP_STRING_BASE64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1260#define DUK_HTHREAD_STRING_BASE64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1261#define DUK_STRIDX_JX 125 /* 'jx' */
1262#define DUK_HEAP_STRING_JX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1263#define DUK_HTHREAD_STRING_JX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1264#define DUK_STRIDX_JC 126 /* 'jc' */
1265#define DUK_HEAP_STRING_JC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1266#define DUK_HTHREAD_STRING_JC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1267#define DUK_STRIDX_RESUME 127 /* 'resume' */
1268#define DUK_HEAP_STRING_RESUME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RESUME)
1269#define DUK_HTHREAD_STRING_RESUME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RESUME)
1270#define DUK_STRIDX_FMT 128 /* 'fmt' */
1271#define DUK_HEAP_STRING_FMT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FMT)
1272#define DUK_HTHREAD_STRING_FMT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FMT)
1273#define DUK_STRIDX_RAW 129 /* 'raw' */
1274#define DUK_HEAP_STRING_RAW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RAW)
1275#define DUK_HTHREAD_STRING_RAW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RAW)
1276#define DUK_STRIDX_LC_TRACE 130 /* 'trace' */
1277#define DUK_HEAP_STRING_LC_TRACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_TRACE)
1278#define DUK_HTHREAD_STRING_LC_TRACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_TRACE)
1279#define DUK_STRIDX_LC_DEBUG 131 /* 'debug' */
1280#define DUK_HEAP_STRING_LC_DEBUG(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_DEBUG)
1281#define DUK_HTHREAD_STRING_LC_DEBUG(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_DEBUG)
1282#define DUK_STRIDX_LC_INFO 132 /* 'info' */
1283#define DUK_HEAP_STRING_LC_INFO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_INFO)
1284#define DUK_HTHREAD_STRING_LC_INFO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_INFO)
1285#define DUK_STRIDX_LC_WARN 133 /* 'warn' */
1286#define DUK_HEAP_STRING_LC_WARN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_WARN)
1287#define DUK_HTHREAD_STRING_LC_WARN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_WARN)
1288#define DUK_STRIDX_LC_ERROR 134 /* 'error' */
1289#define DUK_HEAP_STRING_LC_ERROR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ERROR)
1290#define DUK_HTHREAD_STRING_LC_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ERROR)
1291#define DUK_STRIDX_LC_FATAL 135 /* 'fatal' */
1292#define DUK_HEAP_STRING_LC_FATAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FATAL)
1293#define DUK_HTHREAD_STRING_LC_FATAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FATAL)
1294#define DUK_STRIDX_LC_N 136 /* 'n' */
1295#define DUK_HEAP_STRING_LC_N(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_N)
1296#define DUK_HTHREAD_STRING_LC_N(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_N)
1297#define DUK_STRIDX_LC_L 137 /* 'l' */
1298#define DUK_HEAP_STRING_LC_L(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_L)
1299#define DUK_HTHREAD_STRING_LC_L(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_L)
1300#define DUK_STRIDX_CLOG 138 /* 'clog' */
1301#define DUK_HEAP_STRING_CLOG(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLOG)
1302#define DUK_HTHREAD_STRING_CLOG(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLOG)
1303#define DUK_STRIDX_TO_LOG_STRING 139 /* 'toLogString' */
1304#define DUK_HEAP_STRING_TO_LOG_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOG_STRING)
1305#define DUK_HTHREAD_STRING_TO_LOG_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOG_STRING)
1306#define DUK_STRIDX_JSON_EXT_UNDEFINED 140 /* '{"_undef":true}' */
1307#define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1308#define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1309#define DUK_STRIDX_JSON_EXT_NAN 141 /* '{"_nan":true}' */
1310#define DUK_HEAP_STRING_JSON_EXT_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1311#define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1312#define DUK_STRIDX_JSON_EXT_POSINF 142 /* '{"_inf":true}' */
1313#define DUK_HEAP_STRING_JSON_EXT_POSINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1314#define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1315#define DUK_STRIDX_JSON_EXT_NEGINF 143 /* '{"_ninf":true}' */
1316#define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1317#define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1318#define DUK_STRIDX_JSON_EXT_FUNCTION1 144 /* '{"_func":true}' */
1319#define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1320#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1321#define DUK_STRIDX_JSON_EXT_FUNCTION2 145 /* '{_func:true}' */
1322#define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1323#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1324#define DUK_STRIDX_BREAK 146 /* 'break' */
1325#define DUK_HEAP_STRING_BREAK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1326#define DUK_HTHREAD_STRING_BREAK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1327#define DUK_STRIDX_CASE 147 /* 'case' */
1328#define DUK_HEAP_STRING_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1329#define DUK_HTHREAD_STRING_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1330#define DUK_STRIDX_CATCH 148 /* 'catch' */
1331#define DUK_HEAP_STRING_CATCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1332#define DUK_HTHREAD_STRING_CATCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1333#define DUK_STRIDX_CONTINUE 149 /* 'continue' */
1334#define DUK_HEAP_STRING_CONTINUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1335#define DUK_HTHREAD_STRING_CONTINUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1336#define DUK_STRIDX_DEBUGGER 150 /* 'debugger' */
1337#define DUK_HEAP_STRING_DEBUGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1338#define DUK_HTHREAD_STRING_DEBUGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1339#define DUK_STRIDX_DEFAULT 151 /* 'default' */
1340#define DUK_HEAP_STRING_DEFAULT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1341#define DUK_HTHREAD_STRING_DEFAULT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1342#define DUK_STRIDX_DELETE 152 /* 'delete' */
1343#define DUK_HEAP_STRING_DELETE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1344#define DUK_HTHREAD_STRING_DELETE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1345#define DUK_STRIDX_DO 153 /* 'do' */
1346#define DUK_HEAP_STRING_DO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1347#define DUK_HTHREAD_STRING_DO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1348#define DUK_STRIDX_ELSE 154 /* 'else' */
1349#define DUK_HEAP_STRING_ELSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1350#define DUK_HTHREAD_STRING_ELSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1351#define DUK_STRIDX_FINALLY 155 /* 'finally' */
1352#define DUK_HEAP_STRING_FINALLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1353#define DUK_HTHREAD_STRING_FINALLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1354#define DUK_STRIDX_FOR 156 /* 'for' */
1355#define DUK_HEAP_STRING_FOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1356#define DUK_HTHREAD_STRING_FOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1357#define DUK_STRIDX_LC_FUNCTION 157 /* 'function' */
1358#define DUK_HEAP_STRING_LC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1359#define DUK_HTHREAD_STRING_LC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1360#define DUK_STRIDX_IF 158 /* 'if' */
1361#define DUK_HEAP_STRING_IF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1362#define DUK_HTHREAD_STRING_IF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1363#define DUK_STRIDX_IN 159 /* 'in' */
1364#define DUK_HEAP_STRING_IN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1365#define DUK_HTHREAD_STRING_IN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1366#define DUK_STRIDX_INSTANCEOF 160 /* 'instanceof' */
1367#define DUK_HEAP_STRING_INSTANCEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1368#define DUK_HTHREAD_STRING_INSTANCEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1369#define DUK_STRIDX_NEW 161 /* 'new' */
1370#define DUK_HEAP_STRING_NEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1371#define DUK_HTHREAD_STRING_NEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1372#define DUK_STRIDX_RETURN 162 /* 'return' */
1373#define DUK_HEAP_STRING_RETURN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1374#define DUK_HTHREAD_STRING_RETURN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1375#define DUK_STRIDX_SWITCH 163 /* 'switch' */
1376#define DUK_HEAP_STRING_SWITCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1377#define DUK_HTHREAD_STRING_SWITCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1378#define DUK_STRIDX_THIS 164 /* 'this' */
1379#define DUK_HEAP_STRING_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1380#define DUK_HTHREAD_STRING_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1381#define DUK_STRIDX_THROW 165 /* 'throw' */
1382#define DUK_HEAP_STRING_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1383#define DUK_HTHREAD_STRING_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1384#define DUK_STRIDX_TRY 166 /* 'try' */
1385#define DUK_HEAP_STRING_TRY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1386#define DUK_HTHREAD_STRING_TRY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1387#define DUK_STRIDX_TYPEOF 167 /* 'typeof' */
1388#define DUK_HEAP_STRING_TYPEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1389#define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1390#define DUK_STRIDX_VAR 168 /* 'var' */
1391#define DUK_HEAP_STRING_VAR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1392#define DUK_HTHREAD_STRING_VAR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1393#define DUK_STRIDX_CONST 169 /* 'const' */
1394#define DUK_HEAP_STRING_CONST(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1395#define DUK_HTHREAD_STRING_CONST(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1396#define DUK_STRIDX_VOID 170 /* 'void' */
1397#define DUK_HEAP_STRING_VOID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1398#define DUK_HTHREAD_STRING_VOID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1399#define DUK_STRIDX_WHILE 171 /* 'while' */
1400#define DUK_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1401#define DUK_HTHREAD_STRING_WHILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1402#define DUK_STRIDX_WITH 172 /* 'with' */
1403#define DUK_HEAP_STRING_WITH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1404#define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1405#define DUK_STRIDX_CLASS 173 /* 'class' */
1406#define DUK_HEAP_STRING_CLASS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1407#define DUK_HTHREAD_STRING_CLASS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1408#define DUK_STRIDX_ENUM 174 /* 'enum' */
1409#define DUK_HEAP_STRING_ENUM(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1410#define DUK_HTHREAD_STRING_ENUM(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1411#define DUK_STRIDX_EXPORT 175 /* 'export' */
1412#define DUK_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1413#define DUK_HTHREAD_STRING_EXPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1414#define DUK_STRIDX_EXTENDS 176 /* 'extends' */
1415#define DUK_HEAP_STRING_EXTENDS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1416#define DUK_HTHREAD_STRING_EXTENDS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1417#define DUK_STRIDX_IMPORT 177 /* 'import' */
1418#define DUK_HEAP_STRING_IMPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1419#define DUK_HTHREAD_STRING_IMPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1420#define DUK_STRIDX_SUPER 178 /* 'super' */
1421#define DUK_HEAP_STRING_SUPER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
1422#define DUK_HTHREAD_STRING_SUPER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
1423#define DUK_STRIDX_LC_NULL 179 /* 'null' */
1424#define DUK_HEAP_STRING_LC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
1425#define DUK_HTHREAD_STRING_LC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
1426#define DUK_STRIDX_TRUE 180 /* 'true' */
1427#define DUK_HEAP_STRING_TRUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
1428#define DUK_HTHREAD_STRING_TRUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
1429#define DUK_STRIDX_FALSE 181 /* 'false' */
1430#define DUK_HEAP_STRING_FALSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
1431#define DUK_HTHREAD_STRING_FALSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
1432#define DUK_STRIDX_IMPLEMENTS 182 /* 'implements' */
1433#define DUK_HEAP_STRING_IMPLEMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
1434#define DUK_HTHREAD_STRING_IMPLEMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
1435#define DUK_STRIDX_INTERFACE 183 /* 'interface' */
1436#define DUK_HEAP_STRING_INTERFACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
1437#define DUK_HTHREAD_STRING_INTERFACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
1438#define DUK_STRIDX_LET 184 /* 'let' */
1439#define DUK_HEAP_STRING_LET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
1440#define DUK_HTHREAD_STRING_LET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
1441#define DUK_STRIDX_PACKAGE 185 /* 'package' */
1442#define DUK_HEAP_STRING_PACKAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
1443#define DUK_HTHREAD_STRING_PACKAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
1444#define DUK_STRIDX_PRIVATE 186 /* 'private' */
1445#define DUK_HEAP_STRING_PRIVATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
1446#define DUK_HTHREAD_STRING_PRIVATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
1447#define DUK_STRIDX_PROTECTED 187 /* 'protected' */
1448#define DUK_HEAP_STRING_PROTECTED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
1449#define DUK_HTHREAD_STRING_PROTECTED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
1450#define DUK_STRIDX_PUBLIC 188 /* 'public' */
1451#define DUK_HEAP_STRING_PUBLIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
1452#define DUK_HTHREAD_STRING_PUBLIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
1453#define DUK_STRIDX_STATIC 189 /* 'static' */
1454#define DUK_HEAP_STRING_STATIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
1455#define DUK_HTHREAD_STRING_STATIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
1456#define DUK_STRIDX_YIELD 190 /* 'yield' */
1457#define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
1458#define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
1459
1460#define DUK_HEAP_NUM_STRINGS 191
1461#define DUK_STRIDX_START_RESERVED 146
1462#define DUK_STRIDX_START_STRICT_RESERVED 182
1463#define DUK_STRIDX_END_RESERVED 191 /* exclusive endpoint */
1464
1465/* To convert a heap stridx to a token number, subtract
1466 * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
1467 */
1468#if !defined(DUK_SINGLE_FILE)
1469DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1049];
1470#endif /* !DUK_SINGLE_FILE */
1471#define DUK_STRDATA_MAX_STRLEN 17
1472#define DUK_STRDATA_DATA_LENGTH 1049
1473#endif /* DUK_USE_ROM_STRINGS */
1474
1475#if defined(DUK_USE_ROM_OBJECTS)
1476#error ROM support not enabled, rerun make_dist.py with --rom-support
1477#else
1627#if !defined(DUK_SINGLE_FILE)
1629#endif /* !DUK_SINGLE_FILE */
1630#if defined(DUK_USE_BUILTIN_INITJS)
1631#if !defined(DUK_SINGLE_FILE)
1632DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[204];
1633#endif /* !DUK_SINGLE_FILE */
1634#define DUK_BUILTIN_INITJS_DATA_LENGTH 204
1635#endif /* DUK_USE_BUILTIN_INITJS */
1636#define DUK_BIDX_GLOBAL 0
1637#define DUK_BIDX_GLOBAL_ENV 1
1638#define DUK_BIDX_OBJECT_CONSTRUCTOR 2
1639#define DUK_BIDX_OBJECT_PROTOTYPE 3
1640#define DUK_BIDX_FUNCTION_CONSTRUCTOR 4
1641#define DUK_BIDX_FUNCTION_PROTOTYPE 5
1642#define DUK_BIDX_ARRAY_CONSTRUCTOR 6
1643#define DUK_BIDX_ARRAY_PROTOTYPE 7
1644#define DUK_BIDX_STRING_CONSTRUCTOR 8
1645#define DUK_BIDX_STRING_PROTOTYPE 9
1646#define DUK_BIDX_BOOLEAN_CONSTRUCTOR 10
1647#define DUK_BIDX_BOOLEAN_PROTOTYPE 11
1648#define DUK_BIDX_NUMBER_CONSTRUCTOR 12
1649#define DUK_BIDX_NUMBER_PROTOTYPE 13
1650#define DUK_BIDX_DATE_CONSTRUCTOR 14
1651#define DUK_BIDX_DATE_PROTOTYPE 15
1652#define DUK_BIDX_REGEXP_CONSTRUCTOR 16
1653#define DUK_BIDX_REGEXP_PROTOTYPE 17
1654#define DUK_BIDX_ERROR_CONSTRUCTOR 18
1655#define DUK_BIDX_ERROR_PROTOTYPE 19
1656#define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR 20
1657#define DUK_BIDX_EVAL_ERROR_PROTOTYPE 21
1658#define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR 22
1659#define DUK_BIDX_RANGE_ERROR_PROTOTYPE 23
1660#define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR 24
1661#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE 25
1662#define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR 26
1663#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE 27
1664#define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR 28
1665#define DUK_BIDX_TYPE_ERROR_PROTOTYPE 29
1666#define DUK_BIDX_URI_ERROR_CONSTRUCTOR 30
1667#define DUK_BIDX_URI_ERROR_PROTOTYPE 31
1668#define DUK_BIDX_MATH 32
1669#define DUK_BIDX_JSON 33
1670#define DUK_BIDX_TYPE_ERROR_THROWER 34
1671#define DUK_BIDX_PROXY_CONSTRUCTOR 35
1672#define DUK_BIDX_DUKTAPE 36
1673#define DUK_BIDX_THREAD_CONSTRUCTOR 37
1674#define DUK_BIDX_THREAD_PROTOTYPE 38
1675#define DUK_BIDX_BUFFER_CONSTRUCTOR 39
1676#define DUK_BIDX_BUFFER_PROTOTYPE 40
1677#define DUK_BIDX_POINTER_CONSTRUCTOR 41
1678#define DUK_BIDX_POINTER_PROTOTYPE 42
1679#define DUK_BIDX_LOGGER_CONSTRUCTOR 43
1680#define DUK_BIDX_LOGGER_PROTOTYPE 44
1681#define DUK_BIDX_DOUBLE_ERROR 45
1682#define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR 46
1683#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 47
1684#define DUK_BIDX_DATAVIEW_CONSTRUCTOR 48
1685#define DUK_BIDX_DATAVIEW_PROTOTYPE 49
1686#define DUK_BIDX_TYPEDARRAY_PROTOTYPE 50
1687#define DUK_BIDX_INT8ARRAY_CONSTRUCTOR 51
1688#define DUK_BIDX_INT8ARRAY_PROTOTYPE 52
1689#define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR 53
1690#define DUK_BIDX_UINT8ARRAY_PROTOTYPE 54
1691#define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR 55
1692#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 56
1693#define DUK_BIDX_INT16ARRAY_CONSTRUCTOR 57
1694#define DUK_BIDX_INT16ARRAY_PROTOTYPE 58
1695#define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR 59
1696#define DUK_BIDX_UINT16ARRAY_PROTOTYPE 60
1697#define DUK_BIDX_INT32ARRAY_CONSTRUCTOR 61
1698#define DUK_BIDX_INT32ARRAY_PROTOTYPE 62
1699#define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR 63
1700#define DUK_BIDX_UINT32ARRAY_PROTOTYPE 64
1701#define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR 65
1702#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 66
1703#define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR 67
1704#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 68
1705#define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR 69
1706#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 70
1707#define DUK_NUM_BUILTINS 71
1708#define DUK_NUM_BIDX_BUILTINS 71
1709#define DUK_NUM_ALL_BUILTINS 71
1710#if defined(DUK_USE_DOUBLE_LE)
1711#if !defined(DUK_SINGLE_FILE)
1712DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1713#endif /* !DUK_SINGLE_FILE */
1714#define DUK_BUILTINS_DATA_LENGTH 3833
1715#elif defined(DUK_USE_DOUBLE_BE)
1716#if !defined(DUK_SINGLE_FILE)
1717DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1718#endif /* !DUK_SINGLE_FILE */
1719#define DUK_BUILTINS_DATA_LENGTH 3833
1720#elif defined(DUK_USE_DOUBLE_ME)
1721#if !defined(DUK_SINGLE_FILE)
1722DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1723#endif /* !DUK_SINGLE_FILE */
1724#define DUK_BUILTINS_DATA_LENGTH 3833
1725#else
1726#error invalid endianness defines
1727#endif
1728#endif /* DUK_USE_ROM_OBJECTS */
1729#endif /* DUK_BUILTINS_H_INCLUDED */
1730#line 52 "duk_internal.h"
1731
1732#line 1 "duk_util.h"
1733/*
1734 * Utilities
1735 */
1736
1737#ifndef DUK_UTIL_H_INCLUDED
1738#define DUK_UTIL_H_INCLUDED
1739
1740#define DUK_UTIL_MIN_HASH_PRIME 17 /* must match genhashsizes.py */
1741
1742#define DUK_UTIL_GET_HASH_PROBE_STEP(hash) (duk_util_probe_steps[(hash) & 0x1f])
1743
1744/*
1745 * Endian conversion
1746 */
1747
1748#if defined(DUK_USE_INTEGER_LE)
1749#define DUK_HTON32(x) DUK_BSWAP32((x))
1750#define DUK_NTOH32(x) DUK_BSWAP32((x))
1751#define DUK_HTON16(x) DUK_BSWAP16((x))
1752#define DUK_NTOH16(x) DUK_BSWAP16((x))
1753#elif defined(DUK_USE_INTEGER_BE)
1754#define DUK_HTON32(x) (x)
1755#define DUK_NTOH32(x) (x)
1756#define DUK_HTON16(x) (x)
1757#define DUK_NTOH16(x) (x)
1758#else
1759#error internal error, endianness defines broken
1760#endif
1761
1762/*
1763 * Bitstream decoder
1764 */
1765
1766struct duk_bitdecoder_ctx {
1767 const duk_uint8_t *data;
1770 duk_uint32_t currval;
1772};
1773
1774/*
1775 * Bitstream encoder
1776 */
1777
1778struct duk_bitencoder_ctx {
1779 duk_uint8_t *data;
1782 duk_uint32_t currval;
1785};
1786
1787/*
1788 * Raw write/read macros for big endian, unaligned basic values.
1789 * Caller ensures there's enough space. The macros update the pointer
1790 * argument automatically on resizes. The idiom seems a bit odd, but
1791 * leads to compact code.
1792 */
1793
1794#define DUK_RAW_WRITE_U8(ptr,val) do { \
1795 *(ptr)++ = (duk_uint8_t) (val); \
1796 } while (0)
1797#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
1798#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
1799#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
1800#define DUK_RAW_WRITE_XUTF8(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_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
1806 duk__ptr += duk__len; \
1807 (ptr) = duk__ptr; \
1808 } while (0)
1809#define DUK_RAW_WRITE_CESU8(ptr,val) do { \
1810 /* 'ptr' is evaluated both as LHS and RHS. */ \
1811 duk_uint8_t *duk__ptr; \
1812 duk_small_int_t duk__len; \
1813 duk__ptr = (duk_uint8_t *) (ptr); \
1814 duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
1815 duk__ptr += duk__len; \
1816 (ptr) = duk__ptr; \
1817 } while (0)
1818
1819#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
1820#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
1821#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
1822#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
1823
1824/*
1825 * Buffer writer (dynamic buffer only)
1826 *
1827 * Helper for writing to a dynamic buffer with a concept of a "spare" area
1828 * to reduce resizes. You can ensure there is enough space beforehand and
1829 * then write for a while without further checks, relying on a stable data
1830 * pointer. Spare handling is automatic so call sites only indicate how
1831 * much data they need right now.
1832 *
1833 * There are several ways to write using bufwriter. The best approach
1834 * depends mainly on how much performance matters over code footprint.
1835 * The key issues are (1) ensuring there is space and (2) keeping the
1836 * pointers consistent. Fast code should ensure space for multiple writes
1837 * with one ensure call. Fastest inner loop code can temporarily borrow
1838 * the 'p' pointer but must write it back eventually.
1839 *
1840 * Be careful to ensure all macro arguments (other than static pointers like
1841 * 'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
1842 * necessary (if that's not possible, there should be a note near the macro).
1843 * Buffer write arguments often contain arithmetic etc so this is
1844 * particularly important here.
1845 */
1846
1847/* XXX: Migrate bufwriter and other read/write helpers to its own header? */
1848
1849struct duk_bufwriter_ctx {
1850 duk_uint8_t *p;
1851 duk_uint8_t *p_base;
1852 duk_uint8_t *p_limit;
1854};
1855
1856#define DUK_BW_SPARE_ADD 64
1857#define DUK_BW_SPARE_SHIFT 4 /* 2^4 -> 1/16 = 6.25% spare */
1858
1859/* Initialization and finalization (compaction), converting to other types. */
1860
1861#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
1862 duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
1863 } while (0)
1864#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
1865 duk_bw_init((thr), (bw_ctx), (buf)); \
1866 } while (0)
1867#define DUK_BW_COMPACT(thr,bw_ctx) do { \
1868 /* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
1869 duk_bw_compact((thr), (bw_ctx)); \
1870 } while (0)
1871#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
1872 duk_push_lstring((duk_context *) (thr), \
1873 (const char *) (bw_ctx)->p_base, \
1874 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
1875 } while (0)
1876/* Pointers may be NULL for a while when 'buf' size is zero and before any
1877 * ENSURE calls have been made. Once an ENSURE has been made, the pointers
1878 * are required to be non-NULL so that it's always valid to use memcpy() and
1879 * memmove(), even for zero size.
1880 */
1881#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
1882 DUK_ASSERT_EXPR((bw_ctx) != NULL && \
1883 (bw_ctx)->buf != NULL && \
1884 ((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
1885 ((bw_ctx)->p != NULL && \
1886 (bw_ctx)->p_base != NULL && \
1887 (bw_ctx)->p_limit != NULL && \
1888 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
1889 (bw_ctx)->p >= (bw_ctx)->p_base && \
1890 (bw_ctx)->p <= (bw_ctx)->p_limit)))
1891#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
1892 DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
1893 } while (0)
1894
1895/* Working with the pointer and current size. */
1896
1897#define DUK_BW_GET_PTR(thr,bw_ctx) \
1898 ((bw_ctx)->p)
1899#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
1900 (bw_ctx)->p = (ptr); \
1901 } while (0)
1902#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
1903 (bw_ctx)->p += (delta); \
1904 } while (0)
1905#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
1906 ((bw_ctx)->p_base)
1907#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
1908 ((bw_ctx)->p_limit)
1909#define DUK_BW_GET_SIZE(thr,bw_ctx) \
1910 ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
1911#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
1912 DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
1913 (bw_ctx)->p = (bw_ctx)->p_base + (sz); \
1914 } while (0)
1915#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
1916 /* Reset to zero size, keep current limit. */ \
1917 (bw_ctx)->p = (bw_ctx)->p_base; \
1918 } while (0)
1919#define DUK_BW_GET_BUFFER(thr,bw_ctx) \
1920 ((bw_ctx)->buf)
1921
1922/* Ensuring (reserving) space. */
1923
1924#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
1925 duk_size_t duk__sz, duk__space; \
1926 DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
1927 duk__sz = (sz); \
1928 duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
1929 if (duk__space < duk__sz) { \
1930 (void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
1931 } \
1932 } while (0)
1933/* NOTE: Multiple evaluation of 'ptr' in this macro. */
1934/* XXX: Rework to use an always-inline function? */
1935#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
1936 (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
1937 (ptr) : \
1938 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
1939#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
1940 DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
1941#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
1942 (DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
1943 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
1944#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
1945 DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
1946 } while (0)
1947
1948/* Miscellaneous. */
1949
1950#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
1951 (bw_ctx)->p = (ptr); \
1952 duk_bw_compact((thr), (bw_ctx)); \
1953 } while (0)
1954
1955/* Fast write calls which assume you control the spare beforehand.
1956 * Multibyte write variants exist and use a temporary write pointer
1957 * because byte writes alias with anything: with a stored pointer
1958 * explicit pointer load/stores get generated (e.g. gcc -Os).
1959 */
1960
1961#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
1962 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
1963 *(bw_ctx)->p++ = (duk_uint8_t) (val); \
1964 } while (0)
1965#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
1966 duk_uint8_t *duk__p; \
1967 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
1968 duk__p = (bw_ctx)->p; \
1969 *duk__p++ = (duk_uint8_t) (val1); \
1970 *duk__p++ = (duk_uint8_t) (val2); \
1971 (bw_ctx)->p = duk__p; \
1972 } while (0)
1973#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
1974 duk_uint8_t *duk__p; \
1975 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
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 (bw_ctx)->p = duk__p; \
1981 } while (0)
1982#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
1983 duk_uint8_t *duk__p; \
1984 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
1985 duk__p = (bw_ctx)->p; \
1986 *duk__p++ = (duk_uint8_t) (val1); \
1987 *duk__p++ = (duk_uint8_t) (val2); \
1988 *duk__p++ = (duk_uint8_t) (val3); \
1989 *duk__p++ = (duk_uint8_t) (val4); \
1990 (bw_ctx)->p = duk__p; \
1991 } while (0)
1992#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
1993 duk_uint8_t *duk__p; \
1994 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
1995 duk__p = (bw_ctx)->p; \
1996 *duk__p++ = (duk_uint8_t) (val1); \
1997 *duk__p++ = (duk_uint8_t) (val2); \
1998 *duk__p++ = (duk_uint8_t) (val3); \
1999 *duk__p++ = (duk_uint8_t) (val4); \
2000 *duk__p++ = (duk_uint8_t) (val5); \
2001 (bw_ctx)->p = duk__p; \
2002 } while (0)
2003#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2004 duk_uint8_t *duk__p; \
2005 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2006 duk__p = (bw_ctx)->p; \
2007 *duk__p++ = (duk_uint8_t) (val1); \
2008 *duk__p++ = (duk_uint8_t) (val2); \
2009 *duk__p++ = (duk_uint8_t) (val3); \
2010 *duk__p++ = (duk_uint8_t) (val4); \
2011 *duk__p++ = (duk_uint8_t) (val5); \
2012 *duk__p++ = (duk_uint8_t) (val6); \
2013 (bw_ctx)->p = duk__p; \
2014 } while (0)
2015#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2016 duk_ucodepoint_t duk__cp; \
2017 duk_small_int_t duk__enc_len; \
2018 duk__cp = (cp); \
2019 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2020 duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2021 (bw_ctx)->p += duk__enc_len; \
2022 } while (0)
2023#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2024 duk_ucodepoint_t duk__cp; \
2025 duk_small_int_t duk__enc_len; \
2026 duk__cp = (duk_ucodepoint_t) (cp); \
2027 DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2028 duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2029 (bw_ctx)->p += duk__enc_len; \
2030 } while (0)
2031/* XXX: add temporary duk__p pointer here too; sharing */
2032#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2033 const void *duk__valptr; \
2034 duk_size_t duk__valsz; \
2035 duk__valptr = (const void *) (valptr); \
2036 duk__valsz = (duk_size_t) (valsz); \
2037 DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2038 (bw_ctx)->p += duk__valsz; \
2039 } while (0)
2040#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2041 const duk_uint8_t *duk__val; \
2042 duk_size_t duk__val_len; \
2043 duk__val = (const duk_uint8_t *) (val); \
2044 duk__val_len = DUK_STRLEN((const char *) duk__val); \
2045 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2046 (bw_ctx)->p += duk__val_len; \
2047 } while (0)
2048#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2049 duk_size_t duk__val_len; \
2050 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2051 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2052 (bw_ctx)->p += duk__val_len; \
2053 } while (0)
2054#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2055 duk_size_t duk__val_len; \
2056 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2057 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2058 (bw_ctx)->p += duk__val_len; \
2059 } while (0)
2060#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2061 duk_size_t duk__val_len; \
2062 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2063 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2064 (bw_ctx)->p += duk__val_len; \
2065 } while (0)
2066#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2067 duk_size_t duk__val_len; \
2068 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2069 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2070 (bw_ctx)->p += duk__val_len; \
2071 } while (0)
2072
2073/* Append bytes from a slice already in the buffer. */
2074#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2075 duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2076
2077/* Insert bytes in the middle of the buffer from an external buffer. */
2078#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2079 duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2080
2081/* Insert bytes in the middle of the buffer from a slice already
2082 * in the buffer. Source offset is interpreted "before" the operation.
2083 */
2084#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2085 duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2086
2087/* Insert a reserved area somewhere in the buffer; caller fills it.
2088 * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2089 * area for convenience.
2090 */
2091#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2092 duk_bw_insert_raw_area((thr), (bw), (off), (len))
2093
2094/* Remove a slice from inside buffer. */
2095#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2096 duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2097
2098/* Safe write calls which will ensure space first. */
2099
2100#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2101 DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2102 DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2103 } while (0)
2104#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2105 DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2106 DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2107 } while (0)
2108#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2109 DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2110 DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2111 } while (0)
2112#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2113 DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2114 DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2115 } while (0)
2116#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2117 DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2118 DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2119 } while (0)
2120#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2121 DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2122 DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2123 } while (0)
2124#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2125 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2126 DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2127 } while (0)
2128#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2129 DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2130 DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2131 } while (0)
2132/* XXX: add temporary duk__p pointer here too; sharing */
2133#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2134 const void *duk__valptr; \
2135 duk_size_t duk__valsz; \
2136 duk__valptr = (const void *) (valptr); \
2137 duk__valsz = (duk_size_t) (valsz); \
2138 DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2139 DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2140 (bw_ctx)->p += duk__valsz; \
2141 } while (0)
2142#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2143 const duk_uint8_t *duk__val; \
2144 duk_size_t duk__val_len; \
2145 duk__val = (const duk_uint8_t *) (val); \
2146 duk__val_len = DUK_STRLEN((const char *) duk__val); \
2147 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2148 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2149 (bw_ctx)->p += duk__val_len; \
2150 } while (0)
2151#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2152 duk_size_t duk__val_len; \
2153 duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2154 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2155 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2156 (bw_ctx)->p += duk__val_len; \
2157 } while (0)
2158#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2159 duk_size_t duk__val_len; \
2160 duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2161 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2162 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2163 (bw_ctx)->p += duk__val_len; \
2164 } while (0)
2165#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2166 duk_size_t duk__val_len; \
2167 duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2168 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2169 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2170 (bw_ctx)->p += duk__val_len; \
2171 } while (0)
2172#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2173 duk_size_t duk__val_len; \
2174 duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2175 DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2176 DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2177 (bw_ctx)->p += duk__val_len; \
2178 } while (0)
2179
2180#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2181 duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2182#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2183 duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2184#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2185 duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2186#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2187 /* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2188 duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2189#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2190 /* No difference between raw/ensure because the buffer shrinks. */ \
2191 DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2192
2193/*
2194 * Externs and prototypes
2195 */
2196
2197#if !defined(DUK_SINGLE_FILE)
2198DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2199DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2200DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2201#if defined(DUK_USE_HEX_FASTPATH)
2202DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2203DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2204#endif
2205#if defined(DUK_USE_BASE64_FASTPATH)
2206DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];
2207DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];
2208#endif
2209#endif /* !DUK_SINGLE_FILE */
2210
2211/* Note: assumes that duk_util_probe_steps size is 32 */
2212#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2213#if !defined(DUK_SINGLE_FILE)
2215#endif /* !DUK_SINGLE_FILE */
2216#endif
2217
2218#if defined(DUK_USE_STRHASH_DENSE)
2219DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2220#endif
2221
2222#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2223DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size);
2224#endif
2225
2228DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
2229
2230DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2232
2235
2242DUK_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);
2243DUK_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);
2249/* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2250
2251DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
2252DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
2254DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
2255DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
2256DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
2257
2258#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
2259DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2260#endif
2261
2262#endif /* DUK_UTIL_H_INCLUDED */
2263#line 1 "duk_strings.h"
2264/*
2265 * Shared error messages: declarations and macros
2266 *
2267 * Error messages are accessed through macros with fine-grained, explicit
2268 * error message distinctions. Concrete error messages are selected by the
2269 * macros and multiple macros can map to the same concrete string to save
2270 * on code footprint. This allows flexible footprint/verbosity tuning with
2271 * minimal code impact. There are a few limitations to this approach:
2272 * (1) switching between plain messages and format strings doesn't work
2273 * conveniently, and (2) conditional strings are a bit awkward to handle.
2274 *
2275 * Because format strings behave differently in the call site (they need to
2276 * be followed by format arguments), they have a special prefix (DUK_STR_FMT_
2277 * and duk_str_fmt_).
2278 *
2279 * On some compilers using explicit shared strings is preferable; on others
2280 * it may be better to use straight literals because the compiler will combine
2281 * them anyway, and such strings won't end up unnecessarily in a symbol table.
2282 */
2283
2284#ifndef DUK_ERRMSG_H_INCLUDED
2285#define DUK_ERRMSG_H_INCLUDED
2286
2287#define DUK_STR_INTERNAL_ERROR duk_str_internal_error
2288#define DUK_STR_INVALID_COUNT duk_str_invalid_count
2289#define DUK_STR_INVALID_CALL_ARGS duk_str_invalid_call_args
2290#define DUK_STR_NOT_CONSTRUCTABLE duk_str_not_constructable
2291#define DUK_STR_NOT_CALLABLE duk_str_not_callable
2292#define DUK_STR_NOT_EXTENSIBLE duk_str_not_extensible
2293#define DUK_STR_NOT_WRITABLE duk_str_not_writable
2294#define DUK_STR_NOT_CONFIGURABLE duk_str_not_configurable
2295
2296#if !defined(DUK_SINGLE_FILE)
2305#endif /* !DUK_SINGLE_FILE */
2306
2307#define DUK_STR_INVALID_CONTEXT duk_str_invalid_context
2308#define DUK_STR_INVALID_INDEX duk_str_invalid_call_args
2309#define DUK_STR_PUSH_BEYOND_ALLOC_STACK duk_str_push_beyond_alloc_stack
2310#define DUK_STR_NOT_UNDEFINED duk_str_unexpected_type
2311#define DUK_STR_NOT_NULL duk_str_unexpected_type
2312#define DUK_STR_NOT_BOOLEAN duk_str_unexpected_type
2313#define DUK_STR_NOT_NUMBER duk_str_unexpected_type
2314#define DUK_STR_NOT_STRING duk_str_unexpected_type
2315#define DUK_STR_NOT_OBJECT duk_str_unexpected_type
2316#define DUK_STR_NOT_POINTER duk_str_unexpected_type
2317#define DUK_STR_NOT_BUFFER duk_str_not_buffer /* still in use with verbose messages */
2318#define DUK_STR_UNEXPECTED_TYPE duk_str_unexpected_type
2319#define DUK_STR_NOT_THREAD duk_str_unexpected_type
2320#define DUK_STR_NOT_COMPILEDFUNCTION duk_str_unexpected_type
2321#define DUK_STR_NOT_NATIVEFUNCTION duk_str_unexpected_type
2322#define DUK_STR_NOT_C_FUNCTION duk_str_unexpected_type
2323#define DUK_STR_NOT_FUNCTION duk_str_unexpected_type
2324#define DUK_STR_NOT_REGEXP duk_str_unexpected_type
2325#define DUK_STR_DEFAULTVALUE_COERCE_FAILED duk_str_defaultvalue_coerce_failed
2326#define DUK_STR_NUMBER_OUTSIDE_RANGE duk_str_number_outside_range
2327#define DUK_STR_NOT_OBJECT_COERCIBLE duk_str_not_object_coercible
2328#define DUK_STR_STRING_TOO_LONG duk_str_string_too_long
2329#define DUK_STR_BUFFER_TOO_LONG duk_str_buffer_too_long
2330#define DUK_STR_SPRINTF_TOO_LONG duk_str_sprintf_too_long
2331#define DUK_STR_ALLOC_FAILED duk_str_alloc_failed
2332#define DUK_STR_POP_TOO_MANY duk_str_pop_too_many
2333#define DUK_STR_WRONG_BUFFER_TYPE duk_str_wrong_buffer_type
2334#define DUK_STR_ENCODE_FAILED duk_str_encode_failed
2335#define DUK_STR_DECODE_FAILED duk_str_decode_failed
2336#define DUK_STR_NO_SOURCECODE duk_str_no_sourcecode
2337#define DUK_STR_CONCAT_RESULT_TOO_LONG duk_str_concat_result_too_long
2338#define DUK_STR_UNIMPLEMENTED duk_str_unimplemented
2339#define DUK_STR_UNSUPPORTED duk_str_unsupported
2340#define DUK_STR_ARRAY_LENGTH_OVER_2G duk_str_array_length_over_2g
2341
2342#if !defined(DUK_SINGLE_FILE)
2363#endif /* !DUK_SINGLE_FILE */
2364
2365#define DUK_STR_FMT_PTR duk_str_fmt_ptr
2366#define DUK_STR_FMT_INVALID_JSON duk_str_fmt_invalid_json
2367#define DUK_STR_JSONDEC_RECLIMIT duk_str_jsondec_reclimit
2368#define DUK_STR_JSONENC_RECLIMIT duk_str_jsonenc_reclimit
2369#define DUK_STR_CYCLIC_INPUT duk_str_cyclic_input
2370
2371#if !defined(DUK_SINGLE_FILE)
2377#endif /* !DUK_SINGLE_FILE */
2378
2379#define DUK_STR_PROXY_REVOKED duk_str_proxy_revoked
2380#define DUK_STR_INVALID_BASE duk_str_invalid_base
2381#define DUK_STR_STRICT_CALLER_READ duk_str_strict_caller_read
2382#define DUK_STR_PROXY_REJECTED duk_str_proxy_rejected
2383#define DUK_STR_INVALID_ARRAY_LENGTH duk_str_invalid_array_length
2384#define DUK_STR_ARRAY_LENGTH_WRITE_FAILED duk_str_array_length_write_failed
2385#define DUK_STR_ARRAY_LENGTH_NOT_WRITABLE duk_str_array_length_not_writable
2386#define DUK_STR_SETTER_UNDEFINED duk_str_setter_undefined
2387#define DUK_STR_REDEFINE_VIRT_PROP duk_str_redefine_virt_prop
2388#define DUK_STR_INVALID_DESCRIPTOR duk_str_invalid_descriptor
2389#define DUK_STR_PROPERTY_IS_VIRTUAL duk_str_property_is_virtual
2390
2391#if !defined(DUK_SINGLE_FILE)
2403#endif /* !DUK_SINGLE_FILE */
2404
2405#define DUK_STR_PARSE_ERROR duk_str_parse_error
2406#define DUK_STR_DUPLICATE_LABEL duk_str_duplicate_label
2407#define DUK_STR_INVALID_LABEL duk_str_invalid_label
2408#define DUK_STR_INVALID_ARRAY_LITERAL duk_str_invalid_array_literal
2409#define DUK_STR_INVALID_OBJECT_LITERAL duk_str_invalid_object_literal
2410#define DUK_STR_INVALID_VAR_DECLARATION duk_str_invalid_var_declaration
2411#define DUK_STR_CANNOT_DELETE_IDENTIFIER duk_str_cannot_delete_identifier
2412#define DUK_STR_INVALID_EXPRESSION duk_str_invalid_expression
2413#define DUK_STR_INVALID_LVALUE duk_str_invalid_lvalue
2414#define DUK_STR_EXPECTED_IDENTIFIER duk_str_expected_identifier
2415#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED duk_str_empty_expr_not_allowed
2416#define DUK_STR_INVALID_FOR duk_str_invalid_for
2417#define DUK_STR_INVALID_SWITCH duk_str_invalid_switch
2418#define DUK_STR_INVALID_BREAK_CONT_LABEL duk_str_invalid_break_cont_label
2419#define DUK_STR_INVALID_RETURN duk_str_invalid_return
2420#define DUK_STR_INVALID_TRY duk_str_invalid_try
2421#define DUK_STR_INVALID_THROW duk_str_invalid_throw
2422#define DUK_STR_WITH_IN_STRICT_MODE duk_str_with_in_strict_mode
2423#define DUK_STR_FUNC_STMT_NOT_ALLOWED duk_str_func_stmt_not_allowed
2424#define DUK_STR_UNTERMINATED_STMT duk_str_unterminated_stmt
2425#define DUK_STR_INVALID_ARG_NAME duk_str_invalid_arg_name
2426#define DUK_STR_INVALID_FUNC_NAME duk_str_invalid_func_name
2427#define DUK_STR_INVALID_GETSET_NAME duk_str_invalid_getset_name
2428#define DUK_STR_FUNC_NAME_REQUIRED duk_str_func_name_required
2429
2430#if !defined(DUK_SINGLE_FILE)
2455#endif /* !DUK_SINGLE_FILE */
2456
2457#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM duk_str_invalid_quantifier_no_atom
2458#define DUK_STR_INVALID_QUANTIFIER_VALUES duk_str_invalid_quantifier_values
2459#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES duk_str_quantifier_too_many_copies
2460#define DUK_STR_UNEXPECTED_CLOSING_PAREN duk_str_unexpected_closing_paren
2461#define DUK_STR_UNEXPECTED_END_OF_PATTERN duk_str_unexpected_end_of_pattern
2462#define DUK_STR_UNEXPECTED_REGEXP_TOKEN duk_str_unexpected_regexp_token
2463#define DUK_STR_INVALID_REGEXP_FLAGS duk_str_invalid_regexp_flags
2464#define DUK_STR_INVALID_BACKREFS duk_str_invalid_backrefs
2465
2466#if !defined(DUK_SINGLE_FILE)
2475#endif /* !DUK_SINGLE_FILE */
2476
2477#define DUK_STR_VALSTACK_LIMIT duk_str_valstack_limit
2478#define DUK_STR_CALLSTACK_LIMIT duk_str_callstack_limit
2479#define DUK_STR_CATCHSTACK_LIMIT duk_str_catchstack_limit
2480#define DUK_STR_PROTOTYPE_CHAIN_LIMIT duk_str_prototype_chain_limit
2481#define DUK_STR_BOUND_CHAIN_LIMIT duk_str_bound_chain_limit
2482#define DUK_STR_C_CALLSTACK_LIMIT duk_str_c_callstack_limit
2483#define DUK_STR_COMPILER_RECURSION_LIMIT duk_str_compiler_recursion_limit
2484#define DUK_STR_BYTECODE_LIMIT duk_str_bytecode_limit
2485#define DUK_STR_REG_LIMIT duk_str_reg_limit
2486#define DUK_STR_TEMP_LIMIT duk_str_temp_limit
2487#define DUK_STR_CONST_LIMIT duk_str_const_limit
2488#define DUK_STR_FUNC_LIMIT duk_str_func_limit
2489#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT duk_str_regexp_compiler_recursion_limit
2490#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT duk_str_regexp_executor_recursion_limit
2491#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT duk_str_regexp_executor_step_limit
2492
2493#if !defined(DUK_SINGLE_FILE)
2509#endif /* !DUK_SINGLE_FILE */
2510
2511#if !defined(DUK_SINGLE_FILE)
2513#endif /* !DUK_SINGLE_FILE */
2514
2515#endif /* DUK_ERRMSG_H_INCLUDED */
2516#line 1 "duk_js_bytecode.h"
2517/*
2518 * Ecmascript bytecode
2519 */
2520
2521#ifndef DUK_JS_BYTECODE_H_INCLUDED
2522#define DUK_JS_BYTECODE_H_INCLUDED
2523
2524/*
2525 * Logical instruction layout
2526 * ==========================
2527 *
2528 * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
2529 * !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!
2530 * +---------------------------------------------------+-----------+
2531 * ! C ! B ! A ! OP !
2532 * +---------------------------------------------------+-----------+
2533 *
2534 * OP (6 bits): opcode (DUK_OP_*), access should be fastest
2535 * A (8 bits): typically a target register number
2536 * B (9 bits): typically first source register/constant number
2537 * C (9 bits): typically second source register/constant number
2538 *
2539 * Some instructions combine BC or ABC together for larger parameter values.
2540 * Signed integers (e.g. jump offsets) are encoded as unsigned, with an opcode
2541 * specific bias. B and C may denote a register or a constant, see
2542 * DUK_BC_ISREG() and DUK_BC_ISCONST().
2543 *
2544 * Note: macro naming is a bit misleading, e.g. "ABC" in macro name but
2545 * the field layout is logically "CBA".
2546 */
2547
2548typedef duk_uint32_t duk_instr_t;
2549
2550#define DUK_DEC_OP(x) ((x) & 0x3fUL)
2551#define DUK_DEC_A(x) (((x) >> 6) & 0xffUL)
2552#define DUK_DEC_B(x) (((x) >> 14) & 0x1ffUL)
2553#define DUK_DEC_C(x) (((x) >> 23) & 0x1ffUL)
2554#define DUK_DEC_BC(x) (((x) >> 14) & 0x3ffffUL)
2555#define DUK_DEC_ABC(x) (((x) >> 6) & 0x3ffffffUL)
2556
2557#define DUK_ENC_OP(op) ((duk_instr_t) (op))
2558#define DUK_ENC_OP_ABC(op,abc) ((duk_instr_t) ( \
2559 (((duk_instr_t) (abc)) << 6) | \
2560 ((duk_instr_t) (op)) \
2561 ))
2562#define DUK_ENC_OP_A_BC(op,a,bc) ((duk_instr_t) ( \
2563 (((duk_instr_t) (bc)) << 14) | \
2564 (((duk_instr_t) (a)) << 6) | \
2565 ((duk_instr_t) (op)) \
2566 ))
2567#define DUK_ENC_OP_A_B_C(op,a,b,c) ((duk_instr_t) ( \
2568 (((duk_instr_t) (c)) << 23) | \
2569 (((duk_instr_t) (b)) << 14) | \
2570 (((duk_instr_t) (a)) << 6) | \
2571 ((duk_instr_t) (op)) \
2572 ))
2573#define DUK_ENC_OP_A_B(op,a,b) DUK_ENC_OP_A_B_C(op,a,b,0)
2574#define DUK_ENC_OP_A(op,a) DUK_ENC_OP_A_B_C(op,a,0,0)
2575
2576/* Constants should be signed so that signed arithmetic involving them
2577 * won't cause values to be coerced accidentally to unsigned.
2578 */
2579#define DUK_BC_OP_MIN 0
2580#define DUK_BC_OP_MAX 0x3fL
2581#define DUK_BC_A_MIN 0
2582#define DUK_BC_A_MAX 0xffL
2583#define DUK_BC_B_MIN 0
2584#define DUK_BC_B_MAX 0x1ffL
2585#define DUK_BC_C_MIN 0
2586#define DUK_BC_C_MAX 0x1ffL
2587#define DUK_BC_BC_MIN 0
2588#define DUK_BC_BC_MAX 0x3ffffL
2589#define DUK_BC_ABC_MIN 0
2590#define DUK_BC_ABC_MAX 0x3ffffffL
2591#define DUK_BC_EXTRAOP_MIN DUK_BC_A_MIN
2592#define DUK_BC_EXTRAOP_MAX DUK_BC_A_MAX
2593
2594#define DUK_OP_LDREG 0
2595#define DUK_OP_STREG 1
2596#define DUK_OP_LDCONST 2
2597#define DUK_OP_LDINT 3
2598#define DUK_OP_LDINTX 4
2599#define DUK_OP_MPUTOBJ 5
2600#define DUK_OP_MPUTOBJI 6
2601#define DUK_OP_MPUTARR 7
2602#define DUK_OP_MPUTARRI 8
2603#define DUK_OP_NEW 9
2604#define DUK_OP_NEWI 10
2605#define DUK_OP_REGEXP 11
2606#define DUK_OP_CSREG 12
2607#define DUK_OP_CSREGI 13
2608#define DUK_OP_GETVAR 14
2609#define DUK_OP_PUTVAR 15
2610#define DUK_OP_DECLVAR 16
2611#define DUK_OP_DELVAR 17
2612#define DUK_OP_CSVAR 18
2613#define DUK_OP_CSVARI 19
2614#define DUK_OP_CLOSURE 20
2615#define DUK_OP_GETPROP 21
2616#define DUK_OP_PUTPROP 22
2617#define DUK_OP_DELPROP 23
2618#define DUK_OP_CSPROP 24
2619#define DUK_OP_CSPROPI 25
2620#define DUK_OP_ADD 26
2621#define DUK_OP_SUB 27
2622#define DUK_OP_MUL 28
2623#define DUK_OP_DIV 29
2624#define DUK_OP_MOD 30
2625#define DUK_OP_BAND 31
2626#define DUK_OP_BOR 32
2627#define DUK_OP_BXOR 33
2628#define DUK_OP_BASL 34
2629#define DUK_OP_BLSR 35
2630#define DUK_OP_BASR 36
2631#define DUK_OP_EQ 37
2632#define DUK_OP_NEQ 38
2633#define DUK_OP_SEQ 39
2634#define DUK_OP_SNEQ 40
2635#define DUK_OP_GT 41
2636#define DUK_OP_GE 42
2637#define DUK_OP_LT 43
2638#define DUK_OP_LE 44
2639#define DUK_OP_IF 45
2640#define DUK_OP_JUMP 46
2641#define DUK_OP_RETURN 47
2642#define DUK_OP_CALL 48
2643#define DUK_OP_CALLI 49
2644#define DUK_OP_TRYCATCH 50
2645#define DUK_OP_EXTRA 51
2646#define DUK_OP_PREINCR 52 /* pre/post opcode values have constraints, */
2647#define DUK_OP_PREDECR 53 /* see duk_js_executor.c */
2648#define DUK_OP_POSTINCR 54
2649#define DUK_OP_POSTDECR 55
2650#define DUK_OP_PREINCV 56
2651#define DUK_OP_PREDECV 57
2652#define DUK_OP_POSTINCV 58
2653#define DUK_OP_POSTDECV 59
2654#define DUK_OP_PREINCP 60
2655#define DUK_OP_PREDECP 61
2656#define DUK_OP_POSTINCP 62
2657#define DUK_OP_POSTDECP 63
2658#define DUK_OP_NONE 64 /* dummy value used as marker */
2659
2660/* DUK_OP_EXTRA, sub-operation in A */
2661#define DUK_EXTRAOP_NOP 0
2662#define DUK_EXTRAOP_INVALID 1
2663#define DUK_EXTRAOP_LDTHIS 2
2664#define DUK_EXTRAOP_LDUNDEF 3
2665#define DUK_EXTRAOP_LDNULL 4
2666#define DUK_EXTRAOP_LDTRUE 5
2667#define DUK_EXTRAOP_LDFALSE 6
2668#define DUK_EXTRAOP_NEWOBJ 7
2669#define DUK_EXTRAOP_NEWARR 8
2670#define DUK_EXTRAOP_SETALEN 9
2671#define DUK_EXTRAOP_TYPEOF 10
2672#define DUK_EXTRAOP_TYPEOFID 11
2673#define DUK_EXTRAOP_INITENUM 12
2674#define DUK_EXTRAOP_NEXTENUM 13
2675#define DUK_EXTRAOP_INITSET 14
2676#define DUK_EXTRAOP_INITSETI 15
2677#define DUK_EXTRAOP_INITGET 16
2678#define DUK_EXTRAOP_INITGETI 17
2679#define DUK_EXTRAOP_ENDTRY 18
2680#define DUK_EXTRAOP_ENDCATCH 19
2681#define DUK_EXTRAOP_ENDFIN 20
2682#define DUK_EXTRAOP_THROW 21
2683#define DUK_EXTRAOP_INVLHS 22
2684#define DUK_EXTRAOP_UNM 23
2685#define DUK_EXTRAOP_UNP 24
2686#define DUK_EXTRAOP_DEBUGGER 25
2687#define DUK_EXTRAOP_BREAK 26
2688#define DUK_EXTRAOP_CONTINUE 27
2689#define DUK_EXTRAOP_BNOT 28
2690#define DUK_EXTRAOP_LNOT 29
2691#define DUK_EXTRAOP_INSTOF 30
2692#define DUK_EXTRAOP_IN 31
2693#define DUK_EXTRAOP_LABEL 32
2694#define DUK_EXTRAOP_ENDLABEL 33
2695
2696/* DUK_OP_CALL flags in A */
2697#define DUK_BC_CALL_FLAG_TAILCALL (1 << 0)
2698#define DUK_BC_CALL_FLAG_EVALCALL (1 << 1)
2699
2700/* DUK_OP_TRYCATCH flags in A */
2701#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1 << 0)
2702#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1 << 1)
2703#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1 << 2)
2704#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1 << 3)
2705
2706/* DUK_OP_RETURN flags in A */
2707#define DUK_BC_RETURN_FLAG_HAVE_RETVAL (1 << 0)
2708
2709/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags (DUK_PROPDESC_FLAG_XXX) */
2710#define DUK_BC_DECLVAR_FLAG_UNDEF_VALUE (1 << 4) /* use 'undefined' for value automatically */
2711#define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1 << 5) /* function declaration */
2712
2713/* misc constants and helper macros */
2714#define DUK_BC_REGLIMIT 256 /* if B/C is >= this value, refers to a const */
2715#define DUK_BC_ISREG(x) ((x) < DUK_BC_REGLIMIT)
2716#define DUK_BC_ISCONST(x) ((x) >= DUK_BC_REGLIMIT)
2717#define DUK_BC_LDINT_BIAS (1L << 17)
2718#define DUK_BC_LDINTX_SHIFT 18
2719#define DUK_BC_JUMP_BIAS (1L << 25)
2720
2721#endif /* DUK_JS_BYTECODE_H_INCLUDED */
2722#line 1 "duk_lexer.h"
2723/*
2724 * Lexer defines.
2725 */
2726
2727#ifndef DUK_LEXER_H_INCLUDED
2728#define DUK_LEXER_H_INCLUDED
2729
2730typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
2731
2732/*
2733 * A token is interpreted as any possible production of InputElementDiv
2734 * and InputElementRegExp, see E5 Section 7 in its entirety. Note that
2735 * the E5 "Token" production does not cover all actual tokens of the
2736 * language (which is explicitly stated in the specification, Section 7.5).
2737 * Null and boolean literals are defined as part of both ReservedWord
2738 * (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions. Here,
2739 * null and boolean values have literal tokens, and are not reserved
2740 * words.
2741 *
2742 * Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
2743 * The number tokens always have a non-negative value. The unary minus
2744 * operator in "-1.0" is optimized during compilation to yield a single
2745 * negative constant.
2746 *
2747 * Token numbering is free except that reserved words are required to be
2748 * in a continuous range and in a particular order. See genstrings.py.
2749 */
2750
2751#define DUK_LEXER_INITCTX(ctx) duk_lexer_initctx((ctx))
2752
2753#define DUK_LEXER_SETPOINT(ctx,pt) duk_lexer_setpoint((ctx), (pt))
2754
2755#define DUK_LEXER_GETPOINT(ctx,pt) do { (pt)->offset = (ctx)->window[0].offset; \
2756 (pt)->line = (ctx)->window[0].line; } while (0)
2757
2758/* currently 6 characters of lookup are actually needed (duk_lexer.c) */
2759#define DUK_LEXER_WINDOW_SIZE 6
2760#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
2761#define DUK_LEXER_BUFFER_SIZE 64
2762#endif
2763
2764#define DUK_TOK_MINVAL 0
2765
2766/* returned after EOF (infinite amount) */
2767#define DUK_TOK_EOF 0
2768
2769/* identifier names (E5 Section 7.6) */
2770#define DUK_TOK_IDENTIFIER 1
2771
2772/* reserved words: keywords */
2773#define DUK_TOK_START_RESERVED 2
2774#define DUK_TOK_BREAK 2
2775#define DUK_TOK_CASE 3
2776#define DUK_TOK_CATCH 4
2777#define DUK_TOK_CONTINUE 5
2778#define DUK_TOK_DEBUGGER 6
2779#define DUK_TOK_DEFAULT 7
2780#define DUK_TOK_DELETE 8
2781#define DUK_TOK_DO 9
2782#define DUK_TOK_ELSE 10
2783#define DUK_TOK_FINALLY 11
2784#define DUK_TOK_FOR 12
2785#define DUK_TOK_FUNCTION 13
2786#define DUK_TOK_IF 14
2787#define DUK_TOK_IN 15
2788#define DUK_TOK_INSTANCEOF 16
2789#define DUK_TOK_NEW 17
2790#define DUK_TOK_RETURN 18
2791#define DUK_TOK_SWITCH 19
2792#define DUK_TOK_THIS 20
2793#define DUK_TOK_THROW 21
2794#define DUK_TOK_TRY 22
2795#define DUK_TOK_TYPEOF 23
2796#define DUK_TOK_VAR 24
2797#define DUK_TOK_CONST 25
2798#define DUK_TOK_VOID 26
2799#define DUK_TOK_WHILE 27
2800#define DUK_TOK_WITH 28
2801
2802/* reserved words: future reserved words */
2803#define DUK_TOK_CLASS 29
2804#define DUK_TOK_ENUM 30
2805#define DUK_TOK_EXPORT 31
2806#define DUK_TOK_EXTENDS 32
2807#define DUK_TOK_IMPORT 33
2808#define DUK_TOK_SUPER 34
2809
2810/* "null", "true", and "false" are always reserved words.
2811 * Note that "get" and "set" are not!
2812 */
2813#define DUK_TOK_NULL 35
2814#define DUK_TOK_TRUE 36
2815#define DUK_TOK_FALSE 37
2816
2817/* reserved words: additional future reserved words in strict mode */
2818#define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */
2819#define DUK_TOK_IMPLEMENTS 38
2820#define DUK_TOK_INTERFACE 39
2821#define DUK_TOK_LET 40
2822#define DUK_TOK_PACKAGE 41
2823#define DUK_TOK_PRIVATE 42
2824#define DUK_TOK_PROTECTED 43
2825#define DUK_TOK_PUBLIC 44
2826#define DUK_TOK_STATIC 45
2827#define DUK_TOK_YIELD 46
2828
2829#define DUK_TOK_END_RESERVED 47 /* exclusive */
2830
2831/* "get" and "set" are tokens but NOT ReservedWords. They are currently
2832 * parsed and identifiers and these defines are actually now unused.
2833 */
2834#define DUK_TOK_GET 47
2835#define DUK_TOK_SET 48
2836
2837/* punctuators (unlike the spec, also includes "/" and "/=") */
2838#define DUK_TOK_LCURLY 49
2839#define DUK_TOK_RCURLY 50
2840#define DUK_TOK_LBRACKET 51
2841#define DUK_TOK_RBRACKET 52
2842#define DUK_TOK_LPAREN 53
2843#define DUK_TOK_RPAREN 54
2844#define DUK_TOK_PERIOD 55
2845#define DUK_TOK_SEMICOLON 56
2846#define DUK_TOK_COMMA 57
2847#define DUK_TOK_LT 58
2848#define DUK_TOK_GT 59
2849#define DUK_TOK_LE 60
2850#define DUK_TOK_GE 61
2851#define DUK_TOK_EQ 62
2852#define DUK_TOK_NEQ 63
2853#define DUK_TOK_SEQ 64
2854#define DUK_TOK_SNEQ 65
2855#define DUK_TOK_ADD 66
2856#define DUK_TOK_SUB 67
2857#define DUK_TOK_MUL 68
2858#define DUK_TOK_DIV 69
2859#define DUK_TOK_MOD 70
2860#define DUK_TOK_INCREMENT 71
2861#define DUK_TOK_DECREMENT 72
2862#define DUK_TOK_ALSHIFT 73 /* named "arithmetic" because result is signed */
2863#define DUK_TOK_ARSHIFT 74
2864#define DUK_TOK_RSHIFT 75
2865#define DUK_TOK_BAND 76
2866#define DUK_TOK_BOR 77
2867#define DUK_TOK_BXOR 78
2868#define DUK_TOK_LNOT 79
2869#define DUK_TOK_BNOT 80
2870#define DUK_TOK_LAND 81
2871#define DUK_TOK_LOR 82
2872#define DUK_TOK_QUESTION 83
2873#define DUK_TOK_COLON 84
2874#define DUK_TOK_EQUALSIGN 85
2875#define DUK_TOK_ADD_EQ 86
2876#define DUK_TOK_SUB_EQ 87
2877#define DUK_TOK_MUL_EQ 88
2878#define DUK_TOK_DIV_EQ 89
2879#define DUK_TOK_MOD_EQ 90
2880#define DUK_TOK_ALSHIFT_EQ 91
2881#define DUK_TOK_ARSHIFT_EQ 92
2882#define DUK_TOK_RSHIFT_EQ 93
2883#define DUK_TOK_BAND_EQ 94
2884#define DUK_TOK_BOR_EQ 95
2885#define DUK_TOK_BXOR_EQ 96
2886
2887/* literals (E5 Section 7.8), except null, true, false, which are treated
2888 * like reserved words (above).
2889 */
2890#define DUK_TOK_NUMBER 97
2891#define DUK_TOK_STRING 98
2892#define DUK_TOK_REGEXP 99
2893
2894#define DUK_TOK_MAXVAL 99 /* inclusive */
2895
2896/* Convert heap string index to a token (reserved words) */
2897#define DUK_STRIDX_TO_TOK(x) ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
2898
2899/* Sanity check */
2900#if (DUK_TOK_MAXVAL > 255)
2901#error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
2902#endif
2903
2904/* Sanity checks for string and token defines */
2905#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
2906#error mismatch in token defines
2907#endif
2908#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
2909#error mismatch in token defines
2910#endif
2911#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
2912#error mismatch in token defines
2913#endif
2914#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
2915#error mismatch in token defines
2916#endif
2917#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
2918#error mismatch in token defines
2919#endif
2920#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
2921#error mismatch in token defines
2922#endif
2923#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
2924#error mismatch in token defines
2925#endif
2926#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
2927#error mismatch in token defines
2928#endif
2929#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
2930#error mismatch in token defines
2931#endif
2932#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
2933#error mismatch in token defines
2934#endif
2935#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
2936#error mismatch in token defines
2937#endif
2938#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
2939#error mismatch in token defines
2940#endif
2941#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
2942#error mismatch in token defines
2943#endif
2944#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
2945#error mismatch in token defines
2946#endif
2947#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
2948#error mismatch in token defines
2949#endif
2950#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
2951#error mismatch in token defines
2952#endif
2953#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
2954#error mismatch in token defines
2955#endif
2956#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
2957#error mismatch in token defines
2958#endif
2959#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
2960#error mismatch in token defines
2961#endif
2962#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
2963#error mismatch in token defines
2964#endif
2965#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
2966#error mismatch in token defines
2967#endif
2968#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
2969#error mismatch in token defines
2970#endif
2971#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
2972#error mismatch in token defines
2973#endif
2974#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
2975#error mismatch in token defines
2976#endif
2977#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
2978#error mismatch in token defines
2979#endif
2980#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
2981#error mismatch in token defines
2982#endif
2983#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
2984#error mismatch in token defines
2985#endif
2986#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
2987#error mismatch in token defines
2988#endif
2989#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
2990#error mismatch in token defines
2991#endif
2992#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
2993#error mismatch in token defines
2994#endif
2995#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
2996#error mismatch in token defines
2997#endif
2998#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
2999#error mismatch in token defines
3000#endif
3001#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
3002#error mismatch in token defines
3003#endif
3004#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
3005#error mismatch in token defines
3006#endif
3007#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
3008#error mismatch in token defines
3009#endif
3010#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
3011#error mismatch in token defines
3012#endif
3013#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3014#error mismatch in token defines
3015#endif
3016#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
3017#error mismatch in token defines
3018#endif
3019#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
3020#error mismatch in token defines
3021#endif
3022#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
3023#error mismatch in token defines
3024#endif
3025#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
3026#error mismatch in token defines
3027#endif
3028#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
3029#error mismatch in token defines
3030#endif
3031#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
3032#error mismatch in token defines
3033#endif
3034#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
3035#error mismatch in token defines
3036#endif
3037#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
3038#error mismatch in token defines
3039#endif
3040
3041/* Regexp tokens */
3042#define DUK_RETOK_EOF 0
3043#define DUK_RETOK_DISJUNCTION 1
3044#define DUK_RETOK_QUANTIFIER 2
3045#define DUK_RETOK_ASSERT_START 3
3046#define DUK_RETOK_ASSERT_END 4
3047#define DUK_RETOK_ASSERT_WORD_BOUNDARY 5
3048#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY 6
3049#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD 7
3050#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD 8
3051#define DUK_RETOK_ATOM_PERIOD 9
3052#define DUK_RETOK_ATOM_CHAR 10
3053#define DUK_RETOK_ATOM_DIGIT 11
3054#define DUK_RETOK_ATOM_NOT_DIGIT 12
3055#define DUK_RETOK_ATOM_WHITE 13
3056#define DUK_RETOK_ATOM_NOT_WHITE 14
3057#define DUK_RETOK_ATOM_WORD_CHAR 15
3058#define DUK_RETOK_ATOM_NOT_WORD_CHAR 16
3059#define DUK_RETOK_ATOM_BACKREFERENCE 17
3060#define DUK_RETOK_ATOM_START_CAPTURE_GROUP 18
3061#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP 19
3062#define DUK_RETOK_ATOM_START_CHARCLASS 20
3063#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21
3064#define DUK_RETOK_ATOM_END_GROUP 22
3065
3066/* Constants for duk_lexer_ctx.buf. */
3067#define DUK_LEXER_TEMP_BUF_LIMIT 256
3068
3069/* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
3070 * Some fields (like num, str1, str2) are only valid for specific token types and may have
3071 * stale values otherwise.
3072 */
3073struct duk_token {
3074 duk_small_int_t t; /* token type (with reserved word identification) */
3075 duk_small_int_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */
3076 duk_double_t num; /* numeric value of token */
3077 duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
3078 duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
3079 duk_size_t start_offset; /* start byte offset of token in lexer input */
3080 duk_int_t start_line; /* start line of token (first char) */
3081 duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */
3082 duk_bool_t lineterm; /* token was preceded by a lineterm */
3083 duk_bool_t allow_auto_semi; /* token allows automatic semicolon insertion (eof or preceded by newline) */
3084};
3085
3086#define DUK_RE_QUANTIFIER_INFINITE ((duk_uint32_t) 0xffffffffUL)
3087
3088/* A regexp token value. */
3089struct duk_re_token {
3090 duk_small_int_t t; /* token type */
3092 duk_uint_fast32_t num; /* numeric value (character, count) */
3095};
3096
3097/* A structure for 'snapshotting' a point for rewinding */
3098struct duk_lexer_point {
3101};
3102
3103/* Lexer codepoint with additional info like offset/line number */
3104struct duk_lexer_codepoint {
3108};
3109
3110/* Lexer context. Same context is used for Ecmascript and Regexp parsing. */
3111struct duk_lexer_ctx {
3112#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3113 duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
3115#else
3116 duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
3117#endif
3118
3119 duk_hthread *thr; /* thread; minimizes argument passing */
3120
3121 const duk_uint8_t *input; /* input string (may be a user pointer) */
3122 duk_size_t input_length; /* input byte length */
3123 duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */
3124 duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */
3125
3126 duk_idx_t slot1_idx; /* valstack slot for 1st token value */
3127 duk_idx_t slot2_idx; /* valstack slot for 2nd token value */
3128 duk_idx_t buf_idx; /* valstack slot for temp buffer */
3129 duk_hbuffer_dynamic *buf; /* temp accumulation buffer */
3130 duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */
3131
3132 duk_int_t token_count; /* number of tokens parsed */
3133 duk_int_t token_limit; /* maximum token count before error (sanity backstop) */
3134};
3135
3136/*
3137 * Prototypes
3138 */
3139
3141
3143
3146 duk_token *out_token,
3147 duk_bool_t strict_mode,
3148 duk_bool_t regexp_mode);
3149#ifdef DUK_USE_REGEXP_SUPPORT
3151DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
3152#endif /* DUK_USE_REGEXP_SUPPORT */
3153
3154#endif /* DUK_LEXER_H_INCLUDED */
3155#line 1 "duk_js_compiler.h"
3156/*
3157 * Ecmascript compiler.
3158 */
3159
3160#ifndef DUK_JS_COMPILER_H_INCLUDED
3161#define DUK_JS_COMPILER_H_INCLUDED
3162
3163/* ecmascript compiler limits */
3164#define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */
3165
3166/* maximum loopcount for peephole optimization */
3167#define DUK_COMPILER_PEEPHOLE_MAXITER 3
3168
3169/* maximum bytecode length in instructions */
3170#define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */
3171
3172/*
3173 * Compiler intermediate values
3174 *
3175 * Intermediate values describe either plain values (e.g. strings or
3176 * numbers) or binary operations which have not yet been coerced into
3177 * either a left-hand-side or right-hand-side role (e.g. object property).
3178 */
3179
3180#define DUK_IVAL_NONE 0 /* no value */
3181#define DUK_IVAL_PLAIN 1 /* register, constant, or value */
3182#define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
3183#define DUK_IVAL_ARITH_EXTRAOP 3 /* binary arithmetic using extraops; DUK_EXTRAOP_INSTOF etc */
3184#define DUK_IVAL_PROP 4 /* property access */
3185#define DUK_IVAL_VAR 5 /* variable access */
3186
3187#define DUK_ISPEC_NONE 0 /* no value */
3188#define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */
3189#define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */
3190
3191/* bit mask which indicates that a regconst is a constant instead of a register */
3192#define DUK_JS_CONST_MARKER 0x80000000UL
3193
3194/* type to represent a reg/const reference during compilation */
3195typedef duk_uint32_t duk_regconst_t;
3196
3197/* type to represent a straight register reference, with <0 indicating none */
3198typedef duk_int32_t duk_reg_t;
3199
3200typedef struct {
3201 duk_small_uint_t t; /* DUK_ISPEC_XXX */
3202 duk_regconst_t regconst;
3203 duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */
3204} duk_ispec;
3205
3206typedef struct {
3207 /*
3208 * PLAIN: x1
3209 * ARITH: x1 <op> x2
3210 * PROP: x1.x2
3211 * VAR: x1 (name)
3212 */
3213
3214 /* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
3215 duk_small_uint_t t; /* DUK_IVAL_XXX */
3216 duk_small_uint_t op; /* bytecode opcode (or extraop) for binary ops */
3217 duk_ispec x1;
3218 duk_ispec x2;
3219} duk_ivalue;
3220
3221/*
3222 * Bytecode instruction representation during compilation
3223 *
3224 * Contains the actual instruction and (optionally) debug info.
3225 */
3226
3227struct duk_compiler_instr {
3229#if defined(DUK_USE_PC2LINE)
3230 duk_uint32_t line;
3231#endif
3232};
3233
3234/*
3235 * Compiler state
3236 */
3237
3238#define DUK_LABEL_FLAG_ALLOW_BREAK (1 << 0)
3239#define DUK_LABEL_FLAG_ALLOW_CONTINUE (1 << 1)
3240
3241#define DUK_DECL_TYPE_VAR 0
3242#define DUK_DECL_TYPE_FUNC 1
3243
3244/* XXX: optimize to 16 bytes */
3245typedef struct {
3246 duk_small_uint_t flags;
3247 duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */
3248 duk_hstring *h_label; /* borrowed label name */
3249 duk_int_t catch_depth; /* catch depth at point of definition */
3250 duk_int_t pc_label; /* pc of label statement:
3251 * pc+1: break jump site
3252 * pc+2: continue jump site
3253 */
3254
3255 /* Fast jumps (which avoid longjmp) jump directly to the jump sites
3256 * which are always known even while the iteration/switch statement
3257 * is still being parsed. A final peephole pass "straightens out"
3258 * the jumps.
3259 */
3261
3262/* Compiling state of one function, eventually converted to duk_hcompiledfunction */
3263struct duk_compiler_func {
3264 /* These pointers are at the start of the struct so that they pack
3265 * nicely. Mixing pointers and integer values is bad on some
3266 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
3267 */
3268
3269 duk_bufwriter_ctx bw_code; /* bufwriter for code */
3270
3271 duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */
3272 /* h_code: held in bw_code */
3273 duk_hobject *h_consts; /* array */
3274 duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
3275 * offset/line points to closing brace to allow skipping on pass 2
3276 */
3277 duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ]
3278 * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
3279 * record function and variable declarations in pass 1
3280 */
3281 duk_hobject *h_labelnames; /* array of active label names */
3282 duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */
3283 duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */
3284 duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
3285
3286 /* value stack indices for tracking objects */
3287 /* code_idx: not needed */
3295
3296 /* temp reg handling */
3297 duk_reg_t temp_first; /* first register that is a temporary (below: variables) */
3298 duk_reg_t temp_next; /* next temporary register to allocate */
3299 duk_reg_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */
3300
3301 /* shuffle registers if large number of regs/consts */
3305
3306 /* stats for current expression being parsed */
3309 duk_int_t paren_level; /* parenthesis count, 0 = top level */
3310 duk_bool_t expr_lhs; /* expression is left-hand-side compatible */
3311 duk_bool_t allow_in; /* current paren level allows 'in' token */
3312
3313 /* misc */
3314 duk_int_t stmt_next; /* statement id allocation (running counter) */
3315 duk_int_t label_next; /* label id allocation (running counter) */
3316 duk_int_t catch_depth; /* catch stack depth */
3317 duk_int_t with_depth; /* with stack depth (affects identifier lookups) */
3318 duk_int_t fnum_next; /* inner function numbering */
3319 duk_int_t num_formals; /* number of formal arguments */
3320 duk_reg_t reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
3321#if defined(DUK_USE_DEBUGGER_SUPPORT)
3322 duk_int_t min_line; /* XXX: typing (duk_hcompiledfunction has duk_uint32_t) */
3323 duk_int_t max_line;
3324#endif
3325
3326 /* status booleans */
3327 duk_bool_t is_function; /* is an actual function (not global/eval code) */
3328 duk_bool_t is_eval; /* is eval code */
3329 duk_bool_t is_global; /* is global code */
3330 duk_bool_t is_setget; /* is a setter/getter */
3331 duk_bool_t is_decl; /* is a function declaration (as opposed to function expression) */
3332 duk_bool_t is_strict; /* function is strict */
3333 duk_bool_t is_notail; /* function must not be tail called */
3334 duk_bool_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */
3335 duk_bool_t in_scanning; /* parsing in "scanning" phase (first pass) */
3336 duk_bool_t may_direct_eval; /* function may call direct eval */
3337 duk_bool_t id_access_arguments; /* function refers to 'arguments' identifier */
3338 duk_bool_t id_access_slow; /* function makes one or more slow path accesses */
3339 duk_bool_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */
3340 duk_bool_t needs_shuffle; /* function needs shuffle registers */
3341 duk_bool_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
3342};
3343
3344struct duk_compiler_ctx {
3346
3347 /* filename being compiled (ends up in functions' '_filename' property) */
3348 duk_hstring *h_filename; /* borrowed reference */
3349
3350 /* lexing (tokenization) state (contains two valstack slot indices) */
3352
3353 /* current and previous token for parsing */
3356 duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */
3357 duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */
3358 duk_idx_t tok21_idx; /* prev_token slot1 */
3359 duk_idx_t tok22_idx; /* prev_token slot2 */
3360
3361 /* recursion limit */
3364
3365 /* code emission temporary */
3367
3368 /* current function being compiled (embedded instead of pointer for more compact access) */
3370};
3371
3372/*
3373 * Prototypes
3374 */
3375
3376#define DUK_JS_COMPILE_FLAG_EVAL (1 << 0) /* source is eval code (not global) */
3377#define DUK_JS_COMPILE_FLAG_STRICT (1 << 1) /* strict outer context */
3378#define DUK_JS_COMPILE_FLAG_FUNCEXPR (1 << 2) /* source is a function expression (used for Function constructor) */
3379
3380DUK_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);
3381
3382#endif /* DUK_JS_COMPILER_H_INCLUDED */
3383#line 1 "duk_regexp.h"
3384/*
3385 * Regular expression structs, constants, and bytecode defines.
3386 */
3387
3388#ifndef DUK_REGEXP_H_INCLUDED
3389#define DUK_REGEXP_H_INCLUDED
3390
3391/* maximum bytecode copies for {n,m} quantifiers */
3392#define DUK_RE_MAX_ATOM_COPIES 1000
3393
3394/* regexp compilation limits */
3395#define DUK_RE_COMPILE_TOKEN_LIMIT 100000000L /* 1e8 */
3396
3397/* regexp execution limits */
3398#define DUK_RE_EXECUTE_STEPS_LIMIT 1000000000L /* 1e9 */
3399
3400/* regexp opcodes */
3401#define DUK_REOP_MATCH 1
3402#define DUK_REOP_CHAR 2
3403#define DUK_REOP_PERIOD 3
3404#define DUK_REOP_RANGES 4
3405#define DUK_REOP_INVRANGES 5
3406#define DUK_REOP_JUMP 6
3407#define DUK_REOP_SPLIT1 7
3408#define DUK_REOP_SPLIT2 8
3409#define DUK_REOP_SQMINIMAL 9
3410#define DUK_REOP_SQGREEDY 10
3411#define DUK_REOP_SAVE 11
3412#define DUK_REOP_WIPERANGE 12
3413#define DUK_REOP_LOOKPOS 13
3414#define DUK_REOP_LOOKNEG 14
3415#define DUK_REOP_BACKREFERENCE 15
3416#define DUK_REOP_ASSERT_START 16
3417#define DUK_REOP_ASSERT_END 17
3418#define DUK_REOP_ASSERT_WORD_BOUNDARY 18
3419#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY 19
3420
3421/* flags */
3422#define DUK_RE_FLAG_GLOBAL (1 << 0)
3423#define DUK_RE_FLAG_IGNORE_CASE (1 << 1)
3424#define DUK_RE_FLAG_MULTILINE (1 << 2)
3425
3426struct duk_re_matcher_ctx {
3428
3429 duk_uint32_t re_flags;
3430 const duk_uint8_t *input;
3431 const duk_uint8_t *input_end;
3432 const duk_uint8_t *bytecode;
3433 const duk_uint8_t *bytecode_end;
3434 const duk_uint8_t **saved; /* allocated from valstack (fixed buffer) */
3435 duk_uint32_t nsaved;
3436 duk_uint32_t recursion_depth;
3437 duk_uint32_t recursion_limit;
3438 duk_uint32_t steps_count;
3439 duk_uint32_t steps_limit;
3440};
3441
3442struct duk_re_compiler_ctx {
3444
3445 duk_uint32_t re_flags;
3449 duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */
3450 duk_uint32_t highest_backref;
3451 duk_uint32_t recursion_depth;
3452 duk_uint32_t recursion_limit;
3453 duk_uint32_t nranges; /* internal temporary value, used for char classes */
3454};
3455
3456/*
3457 * Prototypes
3458 */
3459
3463DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hacky helper for String.prototype.split() */
3464
3465#endif /* DUK_REGEXP_H_INCLUDED */
3466#line 1 "duk_heaphdr.h"
3467/*
3468 * Heap header definition and assorted macros, including ref counting.
3469 * Access all fields through the accessor macros.
3470 */
3471
3472#ifndef DUK_HEAPHDR_H_INCLUDED
3473#define DUK_HEAPHDR_H_INCLUDED
3474
3475/*
3476 * Common heap header
3477 *
3478 * All heap objects share the same flags and refcount fields. Objects other
3479 * than strings also need to have a single or double linked list pointers
3480 * for insertion into the "heap allocated" list. Strings are held in the
3481 * heap-wide string table so they don't need link pointers.
3482 *
3483 * Technically, 'h_refcount' must be wide enough to guarantee that it cannot
3484 * wrap (otherwise objects might be freed incorrectly after wrapping). This
3485 * means essentially that the refcount field must be as wide as data pointers.
3486 * On 64-bit platforms this means that the refcount needs to be 64 bits even
3487 * if an 'int' is 32 bits. This is a bit unfortunate, and compromising on
3488 * this might be reasonable in the future.
3489 *
3490 * Heap header size on 32-bit platforms: 8 bytes without reference counting,
3491 * 16 bytes with reference counting.
3492 */
3493
3494struct duk_heaphdr {
3495 duk_uint32_t h_flags;
3496
3497#if defined(DUK_USE_REFERENCE_COUNTING)
3498#if defined(DUK_USE_REFCOUNT16)
3499 duk_uint16_t h_refcount16;
3500#else
3502#endif
3503#endif
3504
3505#if defined(DUK_USE_HEAPPTR16)
3506 duk_uint16_t h_next16;
3507#else
3509#endif
3510
3511#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3512 /* refcounting requires direct heap frees, which in turn requires a dual linked heap */
3513#if defined(DUK_USE_HEAPPTR16)
3514 duk_uint16_t h_prev16;
3515#else
3517#endif
3518#endif
3519
3520 /* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
3521 * struct won't align nicely to 4 bytes. This 16-bit extra field
3522 * is added to make the alignment clean; the field can be used by
3523 * heap objects when 16-bit packing is used. This field is now
3524 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
3525 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
3526 * this only matter to low memory environments anyway.
3527 */
3528#if defined(DUK_USE_HEAPPTR16)
3529 duk_uint16_t h_extra16;
3530#endif
3531};
3532
3533struct duk_heaphdr_string {
3534 /* 16 bits would be enough for shared heaphdr flags and duk_hstring
3535 * flags. The initial parts of duk_heaphdr_string and duk_heaphdr
3536 * must match so changing the flags field size here would be quite
3537 * awkward. However, to minimize struct size, we can pack at least
3538 * 16 bits of duk_hstring data into the flags field.
3539 */
3540 duk_uint32_t h_flags;
3541
3542#if defined(DUK_USE_REFERENCE_COUNTING)
3543#if defined(DUK_USE_REFCOUNT16)
3544 duk_uint16_t h_refcount16;
3545 duk_uint16_t h_strextra16; /* round out to 8 bytes */
3546#else
3548#endif
3549#endif
3550};
3551
3552#define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL
3553#define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
3554
3555 /* 2 bits for heap type */
3556#define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */
3557#define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */
3558
3559#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
3560#define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n))
3561#define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
3562#define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
3563
3564#define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */
3565#define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */
3566#define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */
3567#define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */
3568#define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */
3569
3570#define DUK_HTYPE_MIN 1
3571#define DUK_HTYPE_STRING 1
3572#define DUK_HTYPE_OBJECT 2
3573#define DUK_HTYPE_BUFFER 3
3574#define DUK_HTYPE_MAX 3
3575
3576#if defined(DUK_USE_HEAPPTR16)
3577#define DUK_HEAPHDR_GET_NEXT(heap,h) \
3578 ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
3579#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
3580 (h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
3581 } while (0)
3582#else
3583#define DUK_HEAPHDR_GET_NEXT(heap,h) ((h)->h_next)
3584#define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
3585 (h)->h_next = (val); \
3586 } while (0)
3587#endif
3588
3589#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3590#if defined(DUK_USE_HEAPPTR16)
3591#define DUK_HEAPHDR_GET_PREV(heap,h) \
3592 ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
3593#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
3594 (h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
3595 } while (0)
3596#else
3597#define DUK_HEAPHDR_GET_PREV(heap,h) ((h)->h_prev)
3598#define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
3599 (h)->h_prev = (val); \
3600 } while (0)
3601#endif
3602#endif
3603
3604#if defined(DUK_USE_REFERENCE_COUNTING)
3605#if defined(DUK_USE_REFCOUNT16)
3606#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount16)
3607#define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \
3608 (h)->h_refcount16 = (val); \
3609 } while (0)
3610#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount16) /* result: updated refcount */
3611#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount16) /* result: updated refcount */
3612#else
3613#define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount)
3614#define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \
3615 (h)->h_refcount = (val); \
3616 } while (0)
3617#define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */
3618#define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */
3619#endif
3620#else
3621/* refcount macros not defined without refcounting, caller must #ifdef now */
3622#endif /* DUK_USE_REFERENCE_COUNTING */
3623
3624/*
3625 * Note: type is treated as a field separate from flags, so some masking is
3626 * involved in the macros below.
3627 */
3628
3629#define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags)
3630
3631#define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
3632#define DUK_HEAPHDR_SET_FLAGS(h,val) do { \
3633 (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
3634 } while (0)
3635
3636#define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
3637#define DUK_HEAPHDR_SET_TYPE(h,val) do { \
3638 (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
3639 } while (0)
3640
3641#define DUK_HEAPHDR_HTYPE_VALID(h) ( \
3642 DUK_HEAPHDR_GET_TYPE((h)) >= DUK_HTYPE_MIN && \
3643 DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
3644 )
3645
3646#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval) do { \
3647 (h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
3648 ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
3649 } while (0)
3650
3651#define DUK_HEAPHDR_SET_FLAG_BITS(h,bits) do { \
3652 DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3653 (h)->h_flags |= (bits); \
3654 } while (0)
3655
3656#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits) do { \
3657 DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3658 (h)->h_flags &= ~((bits)); \
3659 } while (0)
3660
3661#define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits) (((h)->h_flags & (bits)) != 0)
3662
3663#define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3664#define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3665#define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3666
3667#define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3668#define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3669#define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3670
3671#define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3672#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3673#define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3674
3675#define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3676#define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3677#define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3678
3679#define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3680#define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3681#define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3682
3683/* get or set a range of flags; m=first bit number, n=number of bits */
3684#define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
3685
3686#define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v) do { \
3687 (h)->h_flags = \
3688 ((h)->h_flags & (~(((1 << (n)) - 1) << (m)))) \
3689 | ((v) << (m)); \
3690 } while (0)
3691
3692/* init pointer fields to null */
3693#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3694#define DUK_HEAPHDR_INIT_NULLS(h) do { \
3695 DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3696 DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
3697 } while (0)
3698#else
3699#define DUK_HEAPHDR_INIT_NULLS(h) do { \
3700 DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3701 } while (0)
3702#endif
3703
3704#define DUK_HEAPHDR_STRING_INIT_NULLS(h) /* currently nop */
3705
3706/*
3707 * Assert helpers
3708 */
3709
3710/* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
3711 * h->prev->next should point back to h.
3712 */
3713#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
3714#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
3715 if ((h) != NULL) { \
3716 duk_heaphdr *h__prev, *h__next; \
3717 h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
3718 h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
3719 DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
3720 DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
3721 } \
3722 } while (0)
3723#else
3724#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
3725#endif
3726
3727/*
3728 * Reference counting helper macros. The macros take a thread argument
3729 * and must thus always be executed in a specific thread context. The
3730 * thread argument is needed for features like finalization. Currently
3731 * it is not required for INCREF, but it is included just in case.
3732 *
3733 * Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
3734 * defined without DUK_USE_REFERENCE_COUNTING, so caller must #ifdef
3735 * around them.
3736 */
3737
3738#if defined(DUK_USE_REFERENCE_COUNTING)
3739
3740#if defined(DUK_USE_ROM_OBJECTS)
3741/* With ROM objects "needs refcount update" is true when the value is
3742 * heap allocated and is not a ROM object.
3743 */
3744/* XXX: double evaluation for 'tv' argument. */
3745#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
3746 (DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
3747#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h)))
3748#else /* DUK_USE_ROM_OBJECTS */
3749/* Without ROM objects "needs refcount update" == is heap allocated. */
3750#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv))
3751#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1
3752#endif /* DUK_USE_ROM_OBJECTS */
3753
3754/* Fast variants, inline refcount operations except for refzero handling.
3755 * Can be used explicitly when speed is always more important than size.
3756 * For a good compiler and a single file build, these are basically the
3757 * same as a forced inline.
3758 */
3759#define DUK_TVAL_INCREF_FAST(thr,tv) do { \
3760 duk_tval *duk__tv = (tv); \
3761 DUK_ASSERT(duk__tv != NULL); \
3762 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
3763 duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
3764 DUK_ASSERT(duk__h != NULL); \
3765 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3766 DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
3767 } \
3768 } while (0)
3769#define DUK_TVAL_DECREF_FAST(thr,tv) do { \
3770 duk_tval *duk__tv = (tv); \
3771 DUK_ASSERT(duk__tv != NULL); \
3772 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
3773 duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
3774 DUK_ASSERT(duk__h != NULL); \
3775 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3776 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
3777 if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
3778 duk_heaphdr_refzero((thr), duk__h); \
3779 } \
3780 } \
3781 } while (0)
3782#define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
3783 duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
3784 DUK_ASSERT(duk__h != NULL); \
3785 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3786 if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
3787 DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
3788 } \
3789 } while (0)
3790#define DUK_HEAPHDR_DECREF_FAST(thr,h) do { \
3791 duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
3792 DUK_ASSERT(duk__h != NULL); \
3793 DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3794 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
3795 if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
3796 if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
3797 duk_heaphdr_refzero((thr), duk__h); \
3798 } \
3799 } \
3800 } while (0)
3801
3802/* Slow variants, call to a helper to reduce code size.
3803 * Can be used explicitly when size is always more important than speed.
3804 */
3805#define DUK_TVAL_INCREF_SLOW(thr,tv) do { \
3806 duk_tval_incref((tv)); \
3807 } while (0)
3808#define DUK_TVAL_DECREF_SLOW(thr,tv) do { \
3809 duk_tval_decref((thr), (tv)); \
3810 } while (0)
3811#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { \
3812 duk_heaphdr_incref((duk_heaphdr *) (h)); \
3813 } while (0)
3814#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { \
3815 duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
3816 } while (0)
3817
3818/* Default variants. Selection depends on speed/size preference.
3819 * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
3820 * is about +1kB for _FAST variants.
3821 */
3822#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
3823#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_FAST((thr),(tv))
3824#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_FAST((thr),(tv))
3825#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_FAST((thr),(h))
3826#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST((thr),(h))
3827#else
3828#define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_SLOW((thr),(tv))
3829#define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_SLOW((thr),(tv))
3830#define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_SLOW((thr),(h))
3831#define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_SLOW((thr),(h))
3832#endif
3833
3834/* Casting convenience. */
3835#define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3836#define DUK_HSTRING_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3837#define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3838#define DUK_HOBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3839#define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3840#define DUK_HBUFFER_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3841#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3842#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3843#define DUK_HNATIVEFUNCTION_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3844#define DUK_HNATIVEFUNCTION_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3845#define DUK_HBUFFEROBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3846#define DUK_HBUFFEROBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3847#define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3848#define DUK_HTHREAD_DECREF(thr,h) DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3849
3850/* Convenience for some situations; the above macros don't allow NULLs
3851 * for performance reasons.
3852 */
3853#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
3854 if ((h) != NULL) { \
3855 DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
3856 } \
3857 } while (0)
3858#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
3859 if ((h) != NULL) { \
3860 DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
3861 } \
3862 } while (0)
3863
3864/*
3865 * Macros to set a duk_tval and update refcount of the target (decref the
3866 * old value and incref the new value if necessary). This is both performance
3867 * and footprint critical; any changes made should be measured for size/speed.
3868 */
3869
3870#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
3871 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3872 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3873 DUK_TVAL_SET_UNDEFINED(tv__dst); \
3874 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3875 } while (0)
3876
3877#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
3878 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3879 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3880 DUK_TVAL_SET_UNUSED(tv__dst); \
3881 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3882 } while (0)
3883
3884#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
3885 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3886 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3887 DUK_TVAL_SET_NULL(tv__dst); \
3888 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3889 } while (0)
3890
3891#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3892 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3893 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3894 DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
3895 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3896 } while (0)
3897
3898#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3899 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3900 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3901 DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
3902 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3903 } while (0)
3904#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3905 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3906 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3907 DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
3908 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3909 } while (0)
3910#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3911 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3912 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3913 DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
3914 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3915 } while (0)
3916#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
3917 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3918 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3919 DUK_TVAL_SET_NAN(tv__dst); \
3920 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3921 } while (0)
3922#if defined(DUK_USE_FASTINT)
3923#define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3924 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3925 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3926 DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
3927 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3928 } while (0)
3929#define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3930 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3931 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3932 DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
3933 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3934 } while (0)
3935#define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3936 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3937 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3938 DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
3939 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3940 } while (0)
3941#else
3942#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
3943 DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
3944#endif /* DUK_USE_FASTINT */
3945
3946#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) 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_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
3950 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3951 } while (0)
3952
3953#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3954 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3955 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3956 DUK_TVAL_SET_STRING(tv__dst, (newval)); \
3957 DUK_HSTRING_INCREF((thr), (newval)); \
3958 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3959 } while (0)
3960
3961#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3962 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3963 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3964 DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
3965 DUK_HOBJECT_INCREF((thr), (newval)); \
3966 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3967 } while (0)
3968
3969#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3970 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3971 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3972 DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
3973 DUK_HBUFFER_INCREF((thr), (newval)); \
3974 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3975 } while (0)
3976
3977#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3978 duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3979 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3980 DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
3981 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3982 } while (0)
3983
3984/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
3985 * etc, so it's very important for performance. Measure when changing.
3986 *
3987 * NOTE: the source and destination duk_tval pointers may be the same, and
3988 * the macros MUST deal with that correctly.
3989 */
3990
3991/* Original idiom used, minimal code size. */
3992#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
3993 duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
3994 tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
3995 DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3996 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
3997 DUK_TVAL_INCREF((thr), tv__src); \
3998 DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
3999 } while (0)
4000
4001/* Faster alternative: avoid making a temporary copy of tvptr_dst and use
4002 * fast incref/decref macros.
4003 */
4004#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
4005 duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
4006 tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
4007 DUK_TVAL_INCREF_FAST((thr), tv__src); \
4008 if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
4009 h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
4010 DUK_ASSERT(h__obj != NULL); \
4011 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4012 DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
4013 } else { \
4014 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4015 } \
4016 } while (0)
4017
4018/* XXX: no optimized variants yet */
4019#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4020#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4021#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
4022#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4023#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4024#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4025#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4026#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
4027#if defined(DUK_USE_FASTINT)
4028#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_FASTINT_UPDREF_ALT0
4029#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
4030#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
4031#else
4032#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */
4033#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4034#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4035#endif /* DUK_USE_FASTINT */
4036#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4037#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
4038#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4039#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4040#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
4041
4042#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4043/* Optimized for speed. */
4044#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1
4045#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1
4046#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4047#else
4048/* Optimized for size. */
4049#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
4050#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
4051#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4052#endif
4053
4054#else /* DUK_USE_REFERENCE_COUNTING */
4055
4056#define DUK_TVAL_INCREF_FAST(thr,v) do {} while (0) /* nop */
4057#define DUK_TVAL_DECREF_FAST(thr,v) do {} while (0) /* nop */
4058#define DUK_TVAL_INCREF_SLOW(thr,v) do {} while (0) /* nop */
4059#define DUK_TVAL_DECREF_SLOW(thr,v) do {} while (0) /* nop */
4060#define DUK_TVAL_INCREF(thr,v) do {} while (0) /* nop */
4061#define DUK_TVAL_DECREF(thr,v) do {} while (0) /* nop */
4062#define DUK_HEAPHDR_INCREF_FAST(thr,h) do {} while (0) /* nop */
4063#define DUK_HEAPHDR_DECREF_FAST(thr,h) do {} while (0) /* nop */
4064#define DUK_HEAPHDR_INCREF_SLOW(thr,h) do {} while (0) /* nop */
4065#define DUK_HEAPHDR_DECREF_SLOW(thr,h) do {} while (0) /* nop */
4066#define DUK_HEAPHDR_INCREF(thr,h) do {} while (0) /* nop */
4067#define DUK_HEAPHDR_DECREF(thr,h) do {} while (0) /* nop */
4068#define DUK_HSTRING_INCREF(thr,h) do {} while (0) /* nop */
4069#define DUK_HSTRING_DECREF(thr,h) do {} while (0) /* nop */
4070#define DUK_HOBJECT_INCREF(thr,h) do {} while (0) /* nop */
4071#define DUK_HOBJECT_DECREF(thr,h) do {} while (0) /* nop */
4072#define DUK_HBUFFER_INCREF(thr,h) do {} while (0) /* nop */
4073#define DUK_HBUFFER_DECREF(thr,h) do {} while (0) /* nop */
4074#define DUK_HCOMPILEDFUNCTION_INCREF(thr,h) do {} while (0) /* nop */
4075#define DUK_HCOMPILEDFUNCTION_DECREF(thr,h) do {} while (0) /* nop */
4076#define DUK_HNATIVEFUNCTION_INCREF(thr,h) do {} while (0) /* nop */
4077#define DUK_HNATIVEFUNCTION_DECREF(thr,h) do {} while (0) /* nop */
4078#define DUK_HBUFFEROBJECT_INCREF(thr,h) do {} while (0) /* nop */
4079#define DUK_HBUFFEROBJECT_DECREF(thr,h) do {} while (0) /* nop */
4080#define DUK_HTHREAD_INCREF(thr,h) do {} while (0) /* nop */
4081#define DUK_HTHREAD_DECREF(thr,h) do {} while (0) /* nop */
4082#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4083#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4084
4085#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4086 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4087 DUK_TVAL_SET_UNDEFINED(tv__dst); \
4088 DUK_UNREF((thr)); \
4089 } while (0)
4090
4091#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4092 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4093 DUK_TVAL_SET_UNUSED(tv__dst); \
4094 DUK_UNREF((thr)); \
4095 } while (0)
4096
4097#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4098 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4099 DUK_TVAL_SET_NULL(tv__dst); \
4100 DUK_UNREF((thr)); \
4101 } while (0)
4102
4103#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4104 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4105 DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4106 DUK_UNREF((thr)); \
4107 } while (0)
4108
4109#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4110 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4111 DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
4112 DUK_UNREF((thr)); \
4113 } while (0)
4114#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4115 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4116 DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
4117 DUK_UNREF((thr)); \
4118 } while (0)
4119#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4120 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4121 DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
4122 DUK_UNREF((thr)); \
4123 } while (0)
4124#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
4125 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4126 DUK_TVAL_SET_NAN(tv__dst); \
4127 DUK_UNREF((thr)); \
4128 } while (0)
4129#if defined(DUK_USE_FASTINT)
4130#define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4131 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4132 DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
4133 DUK_UNREF((thr)); \
4134 } while (0)
4135#define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4136 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4137 DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
4138 DUK_UNREF((thr)); \
4139 } while (0)
4140#define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4141 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4142 DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
4143 DUK_UNREF((thr)); \
4144 } while (0)
4145#else
4146#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
4147 DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
4148#endif /* DUK_USE_FASTINT */
4149
4150#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
4151 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4152 DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
4153 DUK_UNREF((thr)); \
4154 } while (0)
4155
4156#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4157 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4158 DUK_TVAL_SET_STRING(tv__dst, (newval)); \
4159 DUK_UNREF((thr)); \
4160 } while (0)
4161
4162#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4163 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4164 DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
4165 DUK_UNREF((thr)); \
4166 } while (0)
4167
4168#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4169 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4170 DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
4171 DUK_UNREF((thr)); \
4172 } while (0)
4173
4174#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4175 duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4176 DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
4177 DUK_UNREF((thr)); \
4178 } while (0)
4179
4180#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
4181 duk_tval *tv__dst, *tv__src; \
4182 tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
4183 DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4184 DUK_UNREF((thr)); \
4185 } while (0)
4186
4187#define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4188#define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4189#define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
4190#define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4191#define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4192#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4193#define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4194#define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
4195#if defined(DUK_USE_FASTINT)
4196#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_FASTINT_UPDREF_ALT0
4197#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
4198#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
4199#else
4200#define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */
4201#define DUK_TVAL_SET_FASTINT_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4202#define DUK_TVAL_SET_FASTINT_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4203#endif /* DUK_USE_FASTINT */
4204#define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4205#define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
4206#define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4207#define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4208#define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
4209
4210#define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
4211#define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
4212#define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4213
4214#endif /* DUK_USE_REFERENCE_COUNTING */
4215
4216#endif /* DUK_HEAPHDR_H_INCLUDED */
4217#line 1 "duk_api_internal.h"
4218/*
4219 * Internal API calls which have (stack and other) semantics similar
4220 * to the public API.
4221 */
4222
4223#ifndef DUK_API_INTERNAL_H_INCLUDED
4224#define DUK_API_INTERNAL_H_INCLUDED
4225
4226/* duk_push_sprintf constants */
4227#define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L
4228#define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L)
4229
4230/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
4231 * blamed as source of error for error fileName / lineNumber.
4232 */
4233#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24)
4234
4235/* Valstack resize flags */
4236#define DUK_VSRESIZE_FLAG_SHRINK (1 << 0)
4237#define DUK_VSRESIZE_FLAG_COMPACT (1 << 1)
4238#define DUK_VSRESIZE_FLAG_THROW (1 << 2)
4239
4240/* Current convention is to use duk_size_t for value stack sizes and global indices,
4241 * and duk_idx_t for local frame indices.
4242 */
4245 duk_size_t min_new_size,
4246 duk_small_uint_t flags);
4247
4248#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
4249DUK_INTERNAL_DECL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index);
4250#endif
4251
4255
4256/* Push the current 'this' binding; throw TypeError if binding is not object
4257 * coercible (CheckObjectCoercible).
4258 */
4260
4261/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
4263
4264/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
4266
4267/* Get a borrowed duk_tval pointer to the current 'this' binding. Caller must
4268 * make sure there's an active callstack entry. Note that the returned pointer
4269 * is unstable with regards to side effects.
4270 */
4272
4273/* XXX: add fastint support? */
4274#define duk_push_u64(ctx,val) \
4275 duk_push_number((ctx), (duk_double_t) (val))
4276#define duk_push_i64(ctx,val) \
4277 duk_push_number((ctx), (duk_double_t) (val))
4278
4279/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
4280#define duk_push_u32(ctx,val) \
4281 duk_push_uint((ctx), (duk_uint_t) (val))
4282#define duk_push_i32(ctx,val) \
4283 duk_push_int((ctx), (duk_int_t) (val))
4284
4285/* sometimes stack and array indices need to go on the stack */
4286#define duk_push_idx(ctx,val) \
4287 duk_push_int((ctx), (duk_int_t) (val))
4288#define duk_push_uarridx(ctx,val) \
4289 duk_push_uint((ctx), (duk_uint_t) (val))
4290#define duk_push_size_t(ctx,val) \
4291 duk_push_uint((ctx), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
4292
4299
4301
4302#if 0 /* This would be pointless: unexpected type and lightfunc would both return NULL */
4303DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
4304#endif
4306
4307#if 0 /*unused*/
4308DUK_INTERNAL_DECL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index);
4309#endif
4310
4312#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
4313DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index);
4314#endif
4316#if !defined(DUK_USE_PARANOID_ERRORS)
4318#endif
4319
4320DUK_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 */
4323#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
4325#endif
4326
4333
4335
4338
4343#define duk_push_hthread(ctx,h) \
4344 duk_push_hobject((ctx), (duk_hobject *) (h))
4345#define duk_push_hcompiledfunction(ctx,h) \
4346 duk_push_hobject((ctx), (duk_hobject *) (h))
4347#define duk_push_hnativefunction(ctx,h) \
4348 duk_push_hobject((ctx), (duk_hobject *) (h))
4350DUK_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);
4356
4357DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz);
4361
4362#if !defined(DUK_USE_PARANOID_ERRORS)
4365#endif
4366
4367DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [] -> [val] */
4368DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx); /* [val] -> [] */
4371
4372DUK_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); /* [] -> [] */
4373
4374DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags); /* [key val] -> [] */
4375DUK_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] -> [] */
4376DUK_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] -> [] */
4377DUK_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); /* [] -> [] */
4378DUK_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); /* [] -> [] */
4379
4380/* These are macros for now, but could be separate functions to reduce code
4381 * footprint (check call site count before refactoring).
4382 */
4383#define duk_xdef_prop_wec(ctx,obj_index) \
4384 duk_xdef_prop((ctx), (obj_index), DUK_PROPDESC_FLAGS_WEC)
4385#define duk_xdef_prop_index_wec(ctx,obj_index,arr_index) \
4386 duk_xdef_prop_index((ctx), (obj_index), (arr_index), DUK_PROPDESC_FLAGS_WEC)
4387#define duk_xdef_prop_stridx_wec(ctx,obj_index,stridx) \
4388 duk_xdef_prop_stridx((ctx), (obj_index), (stridx), DUK_PROPDESC_FLAGS_WEC)
4389
4390/* Set object 'length'. */
4392
4393/* Raw internal valstack access macros: access is unsafe so call site
4394 * must have a guarantee that the index is valid. When that is the case,
4395 * using these macro results in faster and smaller code than duk_get_tval().
4396 * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
4397 */
4398#define DUK_ASSERT_VALID_NEGIDX(ctx,idx) \
4399 (DUK_ASSERT_EXPR((idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4400#define DUK_ASSERT_VALID_POSIDX(ctx,idx) \
4401 (DUK_ASSERT_EXPR((idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4402#define DUK_GET_TVAL_NEGIDX(ctx,idx) \
4403 (DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_top + (idx))
4404#define DUK_GET_TVAL_POSIDX(ctx,idx) \
4405 (DUK_ASSERT_VALID_POSIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_bottom + (idx))
4406#define DUK_GET_HOBJECT_NEGIDX(ctx,idx) \
4407 (DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_top + (idx)))
4408#define DUK_GET_HOBJECT_POSIDX(ctx,idx) \
4409 (DUK_ASSERT_VALID_POSIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_bottom + (idx)))
4410
4411#endif /* DUK_API_INTERNAL_H_INCLUDED */
4412#line 1 "duk_hstring.h"
4413/*
4414 * Heap string representation.
4415 *
4416 * Strings are byte sequences ordinarily stored in extended UTF-8 format,
4417 * allowing values larger than the official UTF-8 range (used internally)
4418 * and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
4419 * Strings may also be invalid UTF-8 altogether which is the case e.g. with
4420 * strings used as internal property names and raw buffers converted to
4421 * strings. In such cases the 'clen' field contains an inaccurate value.
4422 *
4423 * Ecmascript requires support for 32-bit long strings. However, since each
4424 * 16-bit codepoint can take 3 bytes in CESU-8, this representation can only
4425 * support about 1.4G codepoint long strings in extreme cases. This is not
4426 * really a practical issue.
4427 */
4428
4429#ifndef DUK_HSTRING_H_INCLUDED
4430#define DUK_HSTRING_H_INCLUDED
4431
4432/* Impose a maximum string length for now. Restricted artificially to
4433 * ensure adding a heap header length won't overflow size_t. The limit
4434 * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
4435 *
4436 * E5.1 makes provisions to support strings longer than 4G characters.
4437 * This limit should be eliminated on 64-bit platforms (and increased
4438 * closer to maximum support on 32-bit platforms).
4439 */
4440
4441#if defined(DUK_USE_STRLEN16)
4442#define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL)
4443#else
4444#define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL)
4445#endif
4446
4447/* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings),
4448 * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
4449 * regexp bytecode is), and "contains non-BMP characters". These are not
4450 * needed right now.
4451 */
4452
4453#define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */
4454#define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */
4455#define DUK_HSTRING_FLAG_INTERNAL DUK_HEAPHDR_USER_FLAG(2) /* string is internal */
4456#define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(3) /* string is a reserved word (non-strict) */
4457#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(4) /* string is a reserved word (strict) */
4458#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(5) /* string is 'eval' or 'arguments' */
4459#define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(6) /* string data is external (duk_hstring_external) */
4460
4461#define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4462#define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4463#define DUK_HSTRING_HAS_INTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4464#define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4465#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4466#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4467#define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4468
4469#define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4470#define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4471#define DUK_HSTRING_SET_INTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4472#define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4473#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4474#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4475#define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4476
4477#define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4478#define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4479#define DUK_HSTRING_CLEAR_INTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4480#define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4481#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4482#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4483#define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4484
4485#if 0 /* Slightly smaller code without explicit flag, but explicit flag
4486 * is very useful when 'clen' is dropped.
4487 */
4488#define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
4489#endif
4490#define DUK_HSTRING_IS_ASCII(x) DUK_HSTRING_HAS_ASCII((x))
4491#define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
4492
4493#if defined(DUK_USE_STRHASH16)
4494#define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16)
4495#define DUK_HSTRING_SET_HASH(x,v) do { \
4496 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
4497 } while (0)
4498#else
4499#define DUK_HSTRING_GET_HASH(x) ((x)->hash)
4500#define DUK_HSTRING_SET_HASH(x,v) do { \
4501 (x)->hash = (v); \
4502 } while (0)
4503#endif
4504
4505#if defined(DUK_USE_STRLEN16)
4506#define DUK_HSTRING_GET_BYTELEN(x) ((x)->hdr.h_strextra16)
4507#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
4508 (x)->hdr.h_strextra16 = (v); \
4509 } while (0)
4510#if defined(DUK_USE_HSTRING_CLEN)
4511#define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen16)
4512#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4513 (x)->clen16 = (v); \
4514 } while (0)
4515#else
4516#define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
4517#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4518 DUK_ASSERT(0); /* should never be called */ \
4519 } while (0)
4520#endif
4521#else
4522#define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen)
4523#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
4524 (x)->blen = (v); \
4525 } while (0)
4526#define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen)
4527#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4528 (x)->clen = (v); \
4529 } while (0)
4530#endif
4531
4532#if defined(DUK_USE_HSTRING_EXTDATA)
4533#define DUK_HSTRING_GET_EXTDATA(x) \
4534 ((x)->extdata)
4535#define DUK_HSTRING_GET_DATA(x) \
4536 (DUK_HSTRING_HAS_EXTDATA((x)) ? \
4537 DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
4538#else
4539#define DUK_HSTRING_GET_DATA(x) \
4540 ((const duk_uint8_t *) ((x) + 1))
4541#endif
4542
4543#define DUK_HSTRING_GET_DATA_END(x) \
4544 (DUK_HSTRING_GET_DATA((x)) + (x)->blen)
4545
4546/* marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest valid) */
4547#define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
4548
4549/* get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
4550 * avoids helper call if string has no array index value.
4551 */
4552#define DUK_HSTRING_GET_ARRIDX_FAST(h) \
4553 (DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_string_helper((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
4554
4555/* slower but more compact variant */
4556#define DUK_HSTRING_GET_ARRIDX_SLOW(h) \
4557 (duk_js_to_arrayindex_string_helper((h)))
4558
4559/*
4560 * Misc
4561 */
4562
4563struct duk_hstring {
4564 /* Smaller heaphdr than for other objects, because strings are held
4565 * in string intern table which requires no link pointers. Much of
4566 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
4567 * field in there.
4568 */
4570
4571 /* Note: we could try to stuff a partial hash (e.g. 16 bits) into the
4572 * shared heap header. Good hashing needs more hash bits though.
4573 */
4574
4575 /* string hash */
4576#if defined(DUK_USE_STRHASH16)
4577 /* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
4578#else
4579 duk_uint32_t hash;
4580#endif
4581
4582 /* length in bytes (not counting NUL term) */
4583#if defined(DUK_USE_STRLEN16)
4584 /* placed in duk_heaphdr_string */
4585#else
4586 duk_uint32_t blen;
4587#endif
4588
4589 /* length in codepoints (must be E5 compatible) */
4590#if defined(DUK_USE_STRLEN16)
4591#if defined(DUK_USE_HSTRING_CLEN)
4592 duk_uint16_t clen16;
4593#else
4594 /* computed live */
4595#endif
4596#else
4597 duk_uint32_t clen;
4598#endif
4599
4600 /*
4601 * String value of 'blen+1' bytes follows (+1 for NUL termination
4602 * convenience for C API). No alignment needs to be guaranteed
4603 * for strings, but fields above should guarantee alignment-by-4
4604 * (but not alignment-by-8).
4605 */
4606};
4607
4608/* The external string struct is defined even when the feature is inactive. */
4609struct duk_hstring_external {
4611
4612 /*
4613 * For an external string, the NUL-terminated string data is stored
4614 * externally. The user must guarantee that data behind this pointer
4615 * doesn't change while it's used.
4616 */
4617
4618 const duk_uint8_t *extdata;
4619};
4620
4621/*
4622 * Prototypes
4623 */
4624
4626
4627#if !defined(DUK_USE_HSTRING_CLEN)
4629#endif
4630
4631#endif /* DUK_HSTRING_H_INCLUDED */
4632#line 1 "duk_hobject.h"
4633/*
4634 * Heap object representation.
4635 *
4636 * Heap objects are used for Ecmascript objects, arrays, and functions,
4637 * but also for internal control like declarative and object environment
4638 * records. Compiled functions, native functions, and threads are also
4639 * objects but with an extended C struct.
4640 *
4641 * Objects provide the required Ecmascript semantics and exotic behaviors
4642 * especially for property access.
4643 *
4644 * Properties are stored in three conceptual parts:
4645 *
4646 * 1. A linear 'entry part' contains ordered key-value-attributes triples
4647 * and is the main method of string properties.
4648 *
4649 * 2. An optional linear 'array part' is used for array objects to store a
4650 * (dense) range of [0,N[ array indexed entries with default attributes
4651 * (writable, enumerable, configurable). If the array part would become
4652 * sparse or non-default attributes are required, the array part is
4653 * abandoned and moved to the 'entry part'.
4654 *
4655 * 3. An optional 'hash part' is used to optimize lookups of the entry
4656 * part; it is used only for objects with sufficiently many properties
4657 * and can be abandoned without loss of information.
4658 *
4659 * These three conceptual parts are stored in a single memory allocated area.
4660 * This minimizes memory allocation overhead but also means that all three
4661 * parts are resized together, and makes property access a bit complicated.
4662 */
4663
4664#ifndef DUK_HOBJECT_H_INCLUDED
4665#define DUK_HOBJECT_H_INCLUDED
4666
4667/* Object flag. There are currently 26 flag bits available. Make sure
4668 * this stays in sync with debugger object inspection code.
4669 */
4670#define DUK_HOBJECT_FLAG_EXTENSIBLE DUK_HEAPHDR_USER_FLAG(0) /* object is extensible */
4671#define DUK_HOBJECT_FLAG_CONSTRUCTABLE DUK_HEAPHDR_USER_FLAG(1) /* object is constructable */
4672#define DUK_HOBJECT_FLAG_BOUND DUK_HEAPHDR_USER_FLAG(2) /* object established using Function.prototype.bind() */
4673#define DUK_HOBJECT_FLAG_COMPILEDFUNCTION DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompiledfunction) */
4674#define DUK_HOBJECT_FLAG_NATIVEFUNCTION DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnativefunction) */
4675#define DUK_HOBJECT_FLAG_BUFFEROBJECT DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufferobject) (always exotic) */
4676#define DUK_HOBJECT_FLAG_THREAD DUK_HEAPHDR_USER_FLAG(7) /* object is a thread (duk_hthread) */
4677#define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */
4678#define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */
4679#define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tail called */
4680#define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompiledfunction) */
4681#define DUK_HOBJECT_FLAG_NAMEBINDING DUK_HEAPHDR_USER_FLAG(12) /* function: create binding for func name (function templates only, used for named function expressions) */
4682#define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */
4683#define DUK_HOBJECT_FLAG_ENVRECCLOSED DUK_HEAPHDR_USER_FLAG(14) /* envrec: (declarative) record is closed */
4684#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */
4685#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */
4686#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
4687#define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC DUK_HEAPHDR_USER_FLAG(18) /* Duktape/C (nativefunction) object, exotic 'length' */
4688#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(19) /* 'Proxy' object */
4689
4690#define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(20)
4691#define DUK_HOBJECT_FLAG_CLASS_BITS 5
4692
4693#define DUK_HOBJECT_GET_CLASS_NUMBER(h) \
4694 DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
4695#define DUK_HOBJECT_SET_CLASS_NUMBER(h,v) \
4696 DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
4697
4698#define DUK_HOBJECT_GET_CLASS_MASK(h) \
4699 (1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
4700
4701/* Macro for creating flag initializer from a class number.
4702 * Unsigned type cast is needed to avoid warnings about coercing
4703 * a signed integer to an unsigned one; the largest class values
4704 * have the highest bit (bit 31) set which causes this.
4705 */
4706#define DUK_HOBJECT_CLASS_AS_FLAGS(v) (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
4707
4708/* E5 Section 8.6.2 + custom classes */
4709#define DUK_HOBJECT_CLASS_UNUSED 0
4710#define DUK_HOBJECT_CLASS_ARGUMENTS 1
4711#define DUK_HOBJECT_CLASS_ARRAY 2
4712#define DUK_HOBJECT_CLASS_BOOLEAN 3
4713#define DUK_HOBJECT_CLASS_DATE 4
4714#define DUK_HOBJECT_CLASS_ERROR 5
4715#define DUK_HOBJECT_CLASS_FUNCTION 6
4716#define DUK_HOBJECT_CLASS_JSON 7
4717#define DUK_HOBJECT_CLASS_MATH 8
4718#define DUK_HOBJECT_CLASS_NUMBER 9
4719#define DUK_HOBJECT_CLASS_OBJECT 10
4720#define DUK_HOBJECT_CLASS_REGEXP 11
4721#define DUK_HOBJECT_CLASS_STRING 12
4722#define DUK_HOBJECT_CLASS_GLOBAL 13
4723#define DUK_HOBJECT_CLASS_OBJENV 14 /* custom */
4724#define DUK_HOBJECT_CLASS_DECENV 15 /* custom */
4725#define DUK_HOBJECT_CLASS_BUFFER 16 /* custom; implies DUK_HOBJECT_IS_BUFFEROBJECT */
4726#define DUK_HOBJECT_CLASS_POINTER 17 /* custom */
4727#define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */
4728#define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFFEROBJECT */
4729#define DUK_HOBJECT_CLASS_DATAVIEW 20
4730#define DUK_HOBJECT_CLASS_INT8ARRAY 21
4731#define DUK_HOBJECT_CLASS_UINT8ARRAY 22
4732#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23
4733#define DUK_HOBJECT_CLASS_INT16ARRAY 24
4734#define DUK_HOBJECT_CLASS_UINT16ARRAY 25
4735#define DUK_HOBJECT_CLASS_INT32ARRAY 26
4736#define DUK_HOBJECT_CLASS_UINT32ARRAY 27
4737#define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28
4738#define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29
4739#define DUK_HOBJECT_CLASS_MAX 29
4740
4741/* class masks */
4742#define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
4743#define DUK_HOBJECT_CMASK_UNUSED (1UL << DUK_HOBJECT_CLASS_UNUSED)
4744#define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
4745#define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY)
4746#define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
4747#define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE)
4748#define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR)
4749#define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION)
4750#define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON)
4751#define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH)
4752#define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER)
4753#define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT)
4754#define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP)
4755#define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING)
4756#define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL)
4757#define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV)
4758#define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV)
4759#define DUK_HOBJECT_CMASK_BUFFER (1UL << DUK_HOBJECT_CLASS_BUFFER)
4760#define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER)
4761#define DUK_HOBJECT_CMASK_THREAD (1UL << DUK_HOBJECT_CLASS_THREAD)
4762#define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
4763#define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
4764#define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
4765#define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
4766#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
4767#define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
4768#define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
4769#define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
4770#define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
4771#define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
4772#define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
4773
4774#define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS \
4775 (DUK_HOBJECT_CMASK_BUFFER | \
4776 DUK_HOBJECT_CMASK_ARRAYBUFFER | \
4777 DUK_HOBJECT_CMASK_DATAVIEW | \
4778 DUK_HOBJECT_CMASK_INT8ARRAY | \
4779 DUK_HOBJECT_CMASK_UINT8ARRAY | \
4780 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
4781 DUK_HOBJECT_CMASK_INT16ARRAY | \
4782 DUK_HOBJECT_CMASK_UINT16ARRAY | \
4783 DUK_HOBJECT_CMASK_INT32ARRAY | \
4784 DUK_HOBJECT_CMASK_UINT32ARRAY | \
4785 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
4786 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
4787
4788#define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
4789#define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
4790#define DUK_HOBJECT_IS_ENV(h) (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
4791#define DUK_HOBJECT_IS_ARRAY(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY)
4792#define DUK_HOBJECT_IS_COMPILEDFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4793#define DUK_HOBJECT_IS_NATIVEFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4794#define DUK_HOBJECT_IS_BUFFEROBJECT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4795#define DUK_HOBJECT_IS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4796
4797#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4798 DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4799 DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4800
4801#define DUK_HOBJECT_IS_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4802 DUK_HOBJECT_FLAG_BOUND | \
4803 DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4804 DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4805
4806#define DUK_HOBJECT_IS_CALLABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4807 DUK_HOBJECT_FLAG_BOUND | \
4808 DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4809 DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4810
4811/* object has any exotic behavior(s) */
4812#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
4813 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
4814 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
4815 DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \
4816 DUK_HOBJECT_FLAG_BUFFEROBJECT | \
4817 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4818
4819#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
4820
4821#define DUK_HOBJECT_HAS_EXTENSIBLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4822#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4823#define DUK_HOBJECT_HAS_BOUND(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4824#define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4825#define DUK_HOBJECT_HAS_NATIVEFUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4826#define DUK_HOBJECT_HAS_BUFFEROBJECT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4827#define DUK_HOBJECT_HAS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4828#define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4829#define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4830#define DUK_HOBJECT_HAS_NOTAIL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4831#define DUK_HOBJECT_HAS_NEWENV(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4832#define DUK_HOBJECT_HAS_NAMEBINDING(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4833#define DUK_HOBJECT_HAS_CREATEARGS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4834#define DUK_HOBJECT_HAS_ENVRECCLOSED(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4835#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4836#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4837#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4838#define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4839#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4840
4841#define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4842#define DUK_HOBJECT_SET_CONSTRUCTABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4843#define DUK_HOBJECT_SET_BOUND(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4844#define DUK_HOBJECT_SET_COMPILEDFUNCTION(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4845#define DUK_HOBJECT_SET_NATIVEFUNCTION(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4846#define DUK_HOBJECT_SET_BUFFEROBJECT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4847#define DUK_HOBJECT_SET_THREAD(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4848#define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4849#define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4850#define DUK_HOBJECT_SET_NOTAIL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4851#define DUK_HOBJECT_SET_NEWENV(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4852#define DUK_HOBJECT_SET_NAMEBINDING(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4853#define DUK_HOBJECT_SET_CREATEARGS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4854#define DUK_HOBJECT_SET_ENVRECCLOSED(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4855#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4856#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4857#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4858#define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4859#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4860
4861#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4862#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4863#define DUK_HOBJECT_CLEAR_BOUND(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4864#define DUK_HOBJECT_CLEAR_COMPILEDFUNCTION(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4865#define DUK_HOBJECT_CLEAR_NATIVEFUNCTION(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4866#define DUK_HOBJECT_CLEAR_BUFFEROBJECT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4867#define DUK_HOBJECT_CLEAR_THREAD(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4868#define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4869#define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4870#define DUK_HOBJECT_CLEAR_NOTAIL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4871#define DUK_HOBJECT_CLEAR_NEWENV(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4872#define DUK_HOBJECT_CLEAR_NAMEBINDING(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4873#define DUK_HOBJECT_CLEAR_CREATEARGS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4874#define DUK_HOBJECT_CLEAR_ENVRECCLOSED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4875#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4876#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4877#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4878#define DUK_HOBJECT_CLEAR_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4879#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4880
4881/* flags used for property attributes in duk_propdesc and packed flags */
4882#define DUK_PROPDESC_FLAG_WRITABLE (1 << 0) /* E5 Section 8.6.1 */
4883#define DUK_PROPDESC_FLAG_ENUMERABLE (1 << 1) /* E5 Section 8.6.1 */
4884#define DUK_PROPDESC_FLAG_CONFIGURABLE (1 << 2) /* E5 Section 8.6.1 */
4885#define DUK_PROPDESC_FLAG_ACCESSOR (1 << 3) /* accessor */
4886#define DUK_PROPDESC_FLAG_VIRTUAL (1 << 4) /* property is virtual: used in duk_propdesc, never stored
4887 * (used by e.g. buffer virtual properties)
4888 */
4889#define DUK_PROPDESC_FLAGS_MASK (DUK_PROPDESC_FLAG_WRITABLE | \
4890 DUK_PROPDESC_FLAG_ENUMERABLE | \
4891 DUK_PROPDESC_FLAG_CONFIGURABLE | \
4892 DUK_PROPDESC_FLAG_ACCESSOR)
4893
4894/* additional flags which are passed in the same flags argument as property
4895 * flags but are not stored in object properties.
4896 */
4897#define DUK_PROPDESC_FLAG_NO_OVERWRITE (1 << 4) /* internal define property: skip write silently if exists */
4899/* convenience */
4900#define DUK_PROPDESC_FLAGS_NONE 0
4901#define DUK_PROPDESC_FLAGS_W (DUK_PROPDESC_FLAG_WRITABLE)
4902#define DUK_PROPDESC_FLAGS_E (DUK_PROPDESC_FLAG_ENUMERABLE)
4903#define DUK_PROPDESC_FLAGS_C (DUK_PROPDESC_FLAG_CONFIGURABLE)
4904#define DUK_PROPDESC_FLAGS_WE (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
4905#define DUK_PROPDESC_FLAGS_WC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
4906#define DUK_PROPDESC_FLAGS_EC (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
4907#define DUK_PROPDESC_FLAGS_WEC (DUK_PROPDESC_FLAG_WRITABLE | \
4908 DUK_PROPDESC_FLAG_ENUMERABLE | \
4909 DUK_PROPDESC_FLAG_CONFIGURABLE)
4911/* flags for duk_hobject_get_own_propdesc() and variants */
4912#define DUK_GETDESC_FLAG_PUSH_VALUE (1 << 0) /* push value to stack */
4913#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP (1 << 1) /* don't throw for prototype loop */
4914
4915/*
4916 * Macro for object validity check
4917 *
4918 * Assert for currently guaranteed relations between flags, for instance.
4920
4921#define DUK_ASSERT_HOBJECT_VALID(h) do { \
4922 DUK_ASSERT((h) != NULL); \
4923 DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
4924 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
4925 DUK_ASSERT(!DUK_HOBJECT_IS_BUFFEROBJECT((h)) || \
4926 (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_BUFFER || \
4927 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
4928 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
4929 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
4930 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
4931 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
4932 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
4933 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
4934 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
4935 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
4936 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
4937 DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
4938 } while (0)
4939
4940/*
4941 * Macros to access the 'props' allocation.
4942 */
4943
4944#if defined(DUK_USE_HEAPPTR16)
4945#define DUK_HOBJECT_GET_PROPS(heap,h) \
4946 ((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
4947#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
4948 ((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
4949 } while (0)
4950#else
4951#define DUK_HOBJECT_GET_PROPS(heap,h) \
4952 ((h)->props)
4953#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
4954 (h)->props = (duk_uint8_t *) (x); \
4955 } while (0)
4956#endif
4957
4958#if defined(DUK_USE_HOBJECT_LAYOUT_1)
4959/* LAYOUT 1 */
4960#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
4961 ((duk_hstring **) (void *) ( \
4962 DUK_HOBJECT_GET_PROPS((heap), (h)) \
4963 ))
4964#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
4965 ((duk_propvalue *) (void *) ( \
4966 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4967 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
4968 ))
4969#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
4970 ((duk_uint8_t *) (void *) ( \
4971 DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
4972 ))
4973#define DUK_HOBJECT_A_GET_BASE(heap,h) \
4974 ((duk_tval *) (void *) ( \
4975 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4976 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
4977 ))
4978#define DUK_HOBJECT_H_GET_BASE(heap,h) \
4979 ((duk_uint32_t *) (void *) ( \
4980 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4981 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
4982 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
4983 ))
4984#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
4985 ( \
4986 (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
4987 (n_arr) * sizeof(duk_tval) + \
4988 (n_hash) * sizeof(duk_uint32_t) \
4989 )
4990#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 { \
4991 (set_e_k) = (duk_hstring **) (void *) (p_base); \
4992 (set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
4993 (set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
4994 (set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
4995 (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
4996 } while (0)
4997#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
4998/* LAYOUT 2 */
4999#if (DUK_USE_ALIGN_BY == 4)
5000#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
5001#elif (DUK_USE_ALIGN_BY == 8)
5002#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
5003#elif (DUK_USE_ALIGN_BY == 1)
5004#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
5005#else
5006#error invalid DUK_USE_ALIGN_BY
5007#endif
5008#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
5009 ((duk_hstring **) (void *) ( \
5010 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5011 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
5012 ))
5013#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5014 ((duk_propvalue *) (void *) ( \
5015 DUK_HOBJECT_GET_PROPS((heap), (h)) \
5016 ))
5017#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5018 ((duk_uint8_t *) (void *) ( \
5019 DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
5020 ))
5021#define DUK_HOBJECT_A_GET_BASE(heap,h) \
5022 ((duk_tval *) (void *) ( \
5023 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5024 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5025 DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
5026 ))
5027#define DUK_HOBJECT_H_GET_BASE(heap,h) \
5028 ((duk_uint32_t *) (void *) ( \
5029 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5030 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5031 DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
5032 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5033 ))
5034#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5035 ( \
5036 (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5037 DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
5038 (n_arr) * sizeof(duk_tval) + \
5039 (n_hash) * sizeof(duk_uint32_t) \
5040 )
5041#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 { \
5042 (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5043 (set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
5044 (set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
5045 (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
5046 sizeof(duk_uint8_t) * (n_ent) + \
5047 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
5048 (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
5049 } while (0)
5050#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
5051/* LAYOUT 3 */
5052#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
5053 ((duk_hstring **) (void *) ( \
5054 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5055 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
5056 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5057 ))
5058#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5059 ((duk_propvalue *) (void *) ( \
5060 DUK_HOBJECT_GET_PROPS((heap), (h)) \
5061 ))
5062#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5063 ((duk_uint8_t *) (void *) ( \
5064 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5065 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5066 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
5067 DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
5068 ))
5069#define DUK_HOBJECT_A_GET_BASE(heap,h) \
5070 ((duk_tval *) (void *) ( \
5071 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5072 DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
5073 ))
5074#define DUK_HOBJECT_H_GET_BASE(heap,h) \
5075 ((duk_uint32_t *) (void *) ( \
5076 DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5077 DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5078 DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5079 ))
5080#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5081 ( \
5082 (n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
5083 (n_arr) * sizeof(duk_tval) + \
5084 (n_hash) * sizeof(duk_uint32_t) \
5085 )
5086#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 { \
5087 (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5088 (set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
5089 (set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
5090 (set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
5091 (set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
5092 } while (0)
5093#else
5094#error invalid hobject layout defines
5095#endif /* hobject property layout */
5096
5097#define DUK_HOBJECT_P_ALLOC_SIZE(h) \
5098 DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
5100#define DUK_HOBJECT_E_GET_KEY(heap,h,i) (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5101#define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5102#define DUK_HOBJECT_E_GET_VALUE(heap,h,i) (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5103#define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5104#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5105#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5106#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5107#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5108#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5109#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5110#define DUK_HOBJECT_E_GET_FLAGS(heap,h,i) (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5111#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5112#define DUK_HOBJECT_A_GET_VALUE(heap,h,i) (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5113#define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5114#define DUK_HOBJECT_H_GET_INDEX(heap,h,i) (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5115#define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i) (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5116
5117#define DUK_HOBJECT_E_SET_KEY(heap,h,i,k) do { \
5118 DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
5119 } while (0)
5120#define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v) do { \
5121 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
5122 } while (0)
5123#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v) do { \
5124 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
5125 } while (0)
5126#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v) do { \
5127 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
5128 } while (0)
5129#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v) do { \
5130 DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
5131 } while (0)
5132#define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f) do { \
5133 DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
5134 } while (0)
5135#define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v) do { \
5136 DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
5137 } while (0)
5138#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
5139 DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v)) /* alias for above */
5140#define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v) do { \
5141 DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
5142 } while (0)
5143
5144#define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask) do { \
5145 DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
5146 } while (0)
5147
5148#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask) do { \
5149 DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
5150 } while (0)
5152#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5153#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5154#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5155#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5157#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5158#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5159#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5160#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5162#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5163#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5164#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5165#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5167#define DUK_PROPDESC_IS_WRITABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5168#define DUK_PROPDESC_IS_ENUMERABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5169#define DUK_PROPDESC_IS_CONFIGURABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5170#define DUK_PROPDESC_IS_ACCESSOR(p) (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5172#define DUK_HOBJECT_HASHIDX_UNUSED 0xffffffffUL
5173#define DUK_HOBJECT_HASHIDX_DELETED 0xfffffffeUL
5174
5175/*
5176 * Macros for accessing size fields
5177 */
5178
5179#if defined(DUK_USE_OBJSIZES16)
5180#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
5181#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
5182#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
5183#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
5184#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
5185#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
5186#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
5187#if defined(DUK_USE_HOBJECT_HASH_PART)
5188#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
5189#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
5190#else
5191#define DUK_HOBJECT_GET_HSIZE(h) 0
5192#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5193#endif
5194#else
5195#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
5196#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
5197#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
5198#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
5199#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
5200#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
5201#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
5202#if defined(DUK_USE_HOBJECT_HASH_PART)
5203#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
5204#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
5205#else
5206#define DUK_HOBJECT_GET_HSIZE(h) 0
5207#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5208#endif
5209#endif
5210
5211/*
5212 * Misc
5213 */
5214
5215/* Maximum prototype traversal depth. Sanity limit which handles e.g.
5216 * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
5217 */
5218#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L
5220/* Maximum traversal depth for "bound function" chains. */
5221#define DUK_HOBJECT_BOUND_CHAIN_SANITY 10000L
5222
5223/*
5224 * Ecmascript [[Class]]
5225 */
5227/* range check not necessary because all 4-bit values are mapped */
5228#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n) duk_class_number_to_stridx[(n)]
5229
5230#define DUK_HOBJECT_GET_CLASS_STRING(heap,h) \
5231 DUK_HEAP_GET_STRING( \
5232 (heap), \
5233 DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
5234 )
5235
5236/*
5237 * Macros for property handling
5238 */
5239
5240#if defined(DUK_USE_HEAPPTR16)
5241#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5242 ((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
5243#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5244 (h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
5245 } while (0)
5246#else
5247#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5248 ((h)->prototype)
5249#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5250 (h)->prototype = (x); \
5251 } while (0)
5252#endif
5254/* note: this updates refcounts */
5255#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p) duk_hobject_set_prototype_updref((thr), (h), (p))
5256
5257/*
5258 * Resizing and hash behavior
5259 */
5260
5261/* Sanity limit on max number of properties (allocated, not necessarily used).
5262 * This is somewhat arbitrary, but if we're close to 2**32 properties some
5263 * algorithms will fail (e.g. hash size selection, next prime selection).
5264 * Also, we use negative array/entry table indices to indicate 'not found',
5265 * so anything above 0x80000000 will cause trouble now.
5266 */
5267#if defined(DUK_USE_OBJSIZES16)
5268#define DUK_HOBJECT_MAX_PROPERTIES 0x0000ffffUL
5269#else
5270#define DUK_HOBJECT_MAX_PROPERTIES 0x7fffffffUL /* 2**31-1 ~= 2G properties */
5271#endif
5273/* higher value conserves memory; also note that linear scan is cache friendly */
5274#define DUK_HOBJECT_E_USE_HASH_LIMIT 32
5276/* hash size relative to entries size: for value X, approx. hash_prime(e_size + e_size / X) */
5277#define DUK_HOBJECT_H_SIZE_DIVISOR 4 /* hash size approx. 1.25 times entries size */
5279/* if new_size < L * old_size, resize without abandon check; L = 3-bit fixed point, e.g. 9 -> 9/8 = 112.5% */
5280#define DUK_HOBJECT_A_FAST_RESIZE_LIMIT 9 /* 112.5%, i.e. new size less than 12.5% higher -> fast resize */
5281
5282/* if density < L, abandon array part, L = 3-bit fixed point, e.g. 2 -> 2/8 = 25% */
5283/* limit is quite low: one array entry is 8 bytes, one normal entry is 4+1+8+4 = 17 bytes (with hash entry) */
5284#define DUK_HOBJECT_A_ABANDON_LIMIT 2 /* 25%, i.e. less than 25% used -> abandon */
5285
5286/* internal align target for props allocation, must be 2*n for some n */
5287#if (DUK_USE_ALIGN_BY == 4)
5288#define DUK_HOBJECT_ALIGN_TARGET 4
5289#elif (DUK_USE_ALIGN_BY == 8)
5290#define DUK_HOBJECT_ALIGN_TARGET 8
5291#elif (DUK_USE_ALIGN_BY == 1)
5292#define DUK_HOBJECT_ALIGN_TARGET 1
5293#else
5294#error invalid DUK_USE_ALIGN_BY
5295#endif
5297/* controls for minimum entry part growth */
5298#define DUK_HOBJECT_E_MIN_GROW_ADD 16
5299#define DUK_HOBJECT_E_MIN_GROW_DIVISOR 8 /* 2^3 -> 1/8 = 12.5% min growth */
5301/* controls for minimum array part growth */
5302#define DUK_HOBJECT_A_MIN_GROW_ADD 16
5303#define DUK_HOBJECT_A_MIN_GROW_DIVISOR 8 /* 2^3 -> 1/8 = 12.5% min growth */
5305/* probe sequence */
5306#define DUK_HOBJECT_HASH_INITIAL(hash,h_size) ((hash) % (h_size))
5307#define DUK_HOBJECT_HASH_PROBE_STEP(hash) DUK_UTIL_GET_HASH_PROBE_STEP((hash))
5308
5309/*
5310 * PC-to-line constants
5312
5313#define DUK_PC2LINE_SKIP 64
5315/* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
5316#define DUK_PC2LINE_MAX_DIFF_LENGTH (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
5317
5318/*
5319 * Struct defs
5320 */
5321
5322struct duk_propaccessor {
5325};
5326
5327union duk_propvalue {
5328 /* The get/set pointers could be 16-bit pointer compressed but it
5329 * would make no difference on 32-bit platforms because duk_tval is
5330 * 8 bytes or more anyway.
5331 */
5332 duk_tval v;
5334};
5335
5336struct duk_propdesc {
5337 /* read-only values 'lifted' for ease of use */
5341
5342 /* for updating (all are set to < 0 for virtual properties) */
5343 duk_int_t e_idx; /* prop index in 'entry part', < 0 if not there */
5344 duk_int_t h_idx; /* prop index in 'hash part', < 0 if not there */
5345 duk_int_t a_idx; /* prop index in 'array part', < 0 if not there */
5346};
5347
5348struct duk_hobject {
5350
5351 /*
5352 * 'props' contains {key,value,flags} entries, optional array entries, and
5353 * an optional hash lookup table for non-array entries in a single 'sliced'
5354 * allocation. There are several layout options, which differ slightly in
5355 * generated code size/speed and alignment/padding; duk_features.h selects
5356 * the layout used.
5357 *
5358 * Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
5359 *
5360 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5361 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5362 * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
5363 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5364 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5365 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5366 *
5367 * Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
5368 *
5369 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5370 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5371 * e_size * sizeof(duk_uint8_t) + pad bytes of entry flags (e_next gc reachable)
5372 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5373 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5374 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5375 *
5376 * Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
5377 *
5378 * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5379 * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5380 * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5381 * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5382 * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5383 * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
5384 *
5385 * In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
5386 * requiring 4 or 8 byte alignment. This ensures proper alignment
5387 * for the entries, at the cost of memory footprint. However, it's
5388 * probably preferable to use another layout on such platforms instead.
5389 *
5390 * In layout 2, the key and value parts are swapped to avoid padding
5391 * the key array on platforms requiring alignment by 8. The flags part
5392 * is padded to get alignment for array entries. The 'e_next' count does
5393 * not need to be rounded as in layout 1.
5394 *
5395 * In layout 3, entry values and array values are always aligned properly,
5396 * and assuming pointers are at most 8 bytes, so are the entry keys. Hash
5397 * indices will be properly aligned (assuming pointers are at least 4 bytes).
5398 * Finally, flags don't need additional alignment. This layout provides
5399 * compact allocations without padding (even on platforms with alignment
5400 * requirements) at the cost of a bit slower lookups.
5401 *
5402 * Objects with few keys don't have a hash index; keys are looked up linearly,
5403 * which is cache efficient because the keys are consecutive. Larger objects
5404 * have a hash index part which contains integer indexes to the entries part.
5405 *
5406 * A single allocation reduces memory allocation overhead but requires more
5407 * work when any part needs to be resized. A sliced allocation for entries
5408 * makes linear key matching faster on most platforms (more locality) and
5409 * skimps on flags size (which would be followed by 3 bytes of padding in
5410 * most architectures if entries were placed in a struct).
5411 *
5412 * 'props' also contains internal properties distinguished with a non-BMP
5413 * prefix. Often used properties should be placed early in 'props' whenever
5414 * possible to make accessing them as fast a possible.
5415 */
5416
5417#if defined(DUK_USE_HEAPPTR16)
5418 /* Located in duk_heaphdr h_extra16. Subclasses of duk_hobject (like
5419 * duk_hcompiledfunction) are not free to use h_extra16 for this reason.
5420 */
5421#else
5422 duk_uint8_t *props;
5423#endif
5424
5425 /* prototype: the only internal property lifted outside 'e' as it is so central */
5426#if defined(DUK_USE_HEAPPTR16)
5427 duk_uint16_t prototype16;
5428#else
5430#endif
5431
5432#if defined(DUK_USE_OBJSIZES16)
5433 duk_uint16_t e_size16;
5434 duk_uint16_t e_next16;
5435 duk_uint16_t a_size16;
5436#if defined(DUK_USE_HOBJECT_HASH_PART)
5437 duk_uint16_t h_size16;
5438#endif
5439#else
5440 duk_uint32_t e_size; /* entry part size */
5441 duk_uint32_t e_next; /* index for next new key ([0,e_next[ are gc reachable) */
5442 duk_uint32_t a_size; /* array part size (entirely gc reachable) */
5443#if defined(DUK_USE_HOBJECT_HASH_PART)
5444 duk_uint32_t h_size; /* hash part size or 0 if unused */
5445#endif
5446#endif
5447};
5448
5449/*
5450 * Exposed data
5451 */
5452
5453#if !defined(DUK_SINGLE_FILE)
5455#endif /* !DUK_SINGLE_FILE */
5456
5457/*
5458 * Prototypes
5459 */
5460
5461/* alloc and init */
5463#if 0 /* unused */
5464DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags);
5465#endif
5470
5471/* low-level property functions */
5477
5478/* XXX: when optimizing for guaranteed property slots, use a guaranteed
5479 * slot for internal value; this call can then access it directly.
5480 */
5481#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
5482 duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
5483
5484/* core property functions */
5490/* internal property functions */
5491#define DUK_DELPROP_FLAG_THROW (1 << 0)
5492#define DUK_DELPROP_FLAG_FORCE (1 << 1)
5498DUK_INTERNAL_DECL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length); /* XXX: duk_uarridx_t? */
5500DUK_INTERNAL_DECL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj); /* XXX: duk_uarridx_t? */
5501
5502/* helpers for defineProperty() and defineProperties() */
5505 duk_idx_t idx_in,
5506 duk_uint_t *out_defprop_flags,
5507 duk_idx_t *out_idx_value,
5508 duk_hobject **out_getter,
5509 duk_hobject **out_setter);
5512 duk_uint_t defprop_flags,
5513 duk_hobject *obj,
5514 duk_hstring *key,
5515 duk_idx_t idx_value,
5516 duk_hobject *get,
5517 duk_hobject *set);
5518
5519/* Object built-in methods */
5524
5525/* internal properties */
5528
5529/* hobject management functions */
5531
5532/* ES6 proxy */
5533#if defined(DUK_USE_ES6_PROXY)
5536#endif
5537
5538/* enumeration */
5542
5543/* macros */
5545
5546/* finalization */
5548
5549/* pc2line */
5550#if defined(DUK_USE_PC2LINE)
5553#endif
5554
5555/* misc */
5557
5558#endif /* DUK_HOBJECT_H_INCLUDED */
5559#line 1 "duk_hcompiledfunction.h"
5560/*
5561 * Heap compiled function (Ecmascript function) representation.
5562 *
5563 * There is a single data buffer containing the Ecmascript function's
5564 * bytecode, constants, and inner functions.
5565 */
5567#ifndef DUK_HCOMPILEDFUNCTION_H_INCLUDED
5568#define DUK_HCOMPILEDFUNCTION_H_INCLUDED
5569
5570/*
5571 * Field accessor macros
5572 */
5573
5574/* XXX: casts could be improved, especially for GET/SET DATA */
5575
5576#if defined(DUK_USE_HEAPPTR16)
5577#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
5578 ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
5579#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
5580 (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5581 } while (0)
5582#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h) \
5583 ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
5584#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v) do { \
5585 (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5586 } while (0)
5587#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h) \
5588 ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
5589#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v) do { \
5590 (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5591 } while (0)
5592#else
5593#define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
5594 ((duk_hbuffer_fixed *) (void *) (h)->data)
5595#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
5596 (h)->data = (duk_hbuffer *) (v); \
5597 } while (0)
5598#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h) \
5599 ((h)->funcs)
5600#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v) do { \
5601 (h)->funcs = (v); \
5602 } while (0)
5603#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h) \
5604 ((h)->bytecode)
5605#define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v) do { \
5606 (h)->bytecode = (v); \
5607 } while (0)
5608#endif
5609
5610/*
5611 * Accessor macros for function specific data areas
5612 */
5614/* Note: assumes 'data' is always a fixed buffer */
5615#define DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE(heap,h) \
5616 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h)))
5617
5618#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap,h) \
5619 ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((heap), (h)))
5620
5621#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap,h) \
5622 DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h))
5623
5624#define DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap,h) \
5625 DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h))
5626
5627#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap,h) \
5628 ((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h)))
5629
5630#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap,h) \
5631 ((duk_hobject **) (void *) DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h)))
5633/* XXX: double evaluation of DUK_HCOMPILEDFUNCTION_GET_DATA() */
5634#define DUK_HCOMPILEDFUNCTION_GET_CODE_END(heap,h) \
5635 ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) + \
5636 DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA((heap), h))))
5637
5638#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap,h) \
5639 ( \
5640 (duk_size_t) \
5641 ( \
5642 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END((heap), (h))) - \
5643 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE((heap), (h))) \
5644 ) \
5646
5647#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(heap,h) \
5648 ( \
5649 (duk_size_t) \
5650 ( \
5651 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END((heap), (h))) - \
5652 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE((heap), (h))) \
5653 ) \
5655
5656#define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap,h) \
5657 ( \
5658 (duk_size_t) \
5659 ( \
5660 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END((heap),(h))) - \
5661 ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE((heap),(h))) \
5662 ) \
5664
5665#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap,h) \
5666 ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
5667
5668#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap,h) \
5669 ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
5670
5671#define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(heap,h) \
5672 ((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
5673
5674
5675/*
5676 * Main struct
5677 */
5678
5679struct duk_hcompiledfunction {
5680 /* shared object part */
5682
5683 /*
5684 * Pointers to function data area for faster access. Function
5685 * data is a buffer shared between all closures of the same
5686 * "template" function. The data buffer is always fixed (non-
5687 * dynamic, hence stable), with a layout as follows:
5688 *
5689 * constants (duk_tval)
5690 * inner functions (duk_hobject *)
5691 * bytecode (duk_instr_t)
5692 *
5693 * Note: bytecode end address can be computed from 'data' buffer
5694 * size. It is not strictly necessary functionally, assuming
5695 * bytecode never jumps outside its allocated area. However,
5696 * it's a safety/robustness feature for avoiding the chance of
5697 * executing random data as bytecode due to a compiler error.
5698 *
5699 * Note: values in the data buffer must be incref'd (they will
5700 * be decref'd on release) for every compiledfunction referring
5701 * to the 'data' element.
5702 */
5703
5704 /* Data area, fixed allocation, stable data ptrs. */
5705#if defined(DUK_USE_HEAPPTR16)
5706 duk_uint16_t data16;
5707#else
5709#endif
5710
5711 /* No need for constants pointer (= same as data).
5712 *
5713 * When using 16-bit packing alignment to 4 is nice. 'funcs' will be
5714 * 4-byte aligned because 'constants' are duk_tvals. For now the
5715 * inner function pointers are not compressed, so that 'bytecode' will
5716 * also be 4-byte aligned.
5717 */
5718#if defined(DUK_USE_HEAPPTR16)
5719 duk_uint16_t funcs16;
5720 duk_uint16_t bytecode16;
5721#else
5724#endif
5725
5726 /*
5727 * 'nregs' registers are allocated on function entry, at most 'nargs'
5728 * are initialized to arguments, and the rest to undefined. Arguments
5729 * above 'nregs' are not mapped to registers. All registers in the
5730 * active stack range must be initialized because they are GC reachable.
5731 * 'nargs' is needed so that if the function is given more than 'nargs'
5732 * arguments, the additional arguments do not 'clobber' registers
5733 * beyond 'nregs' which must be consistently initialized to undefined.
5734 *
5735 * Usually there is no need to know which registers are mapped to
5736 * local variables. Registers may be allocated to variable in any
5737 * way (even including gaps). However, a register-variable mapping
5738 * must be the same for the duration of the function execution and
5739 * the register cannot be used for anything else.
5740 *
5741 * When looking up variables by name, the '_Varmap' map is used.
5742 * When an activation closes, registers mapped to arguments are
5743 * copied into the environment record based on the same map. The
5744 * reverse map (from register to variable) is not currently needed
5745 * at run time, except for debugging, so it is not maintained.
5746 */
5747
5748 duk_uint16_t nregs; /* regs to allocate */
5749 duk_uint16_t nargs; /* number of arguments allocated to regs */
5750
5751 /*
5752 * Additional control information is placed into the object itself
5753 * as internal properties to avoid unnecessary fields for the
5754 * majority of functions. The compiler tries to omit internal
5755 * control fields when possible.
5756 *
5757 * Function templates:
5758 *
5759 * {
5760 * name: "func", // declaration, named function expressions
5761 * fileName: <debug info for creating nice errors>
5762 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
5763 * _Formals: [ "arg1", "arg2" ],
5764 * _Source: "function func(arg1, arg2) { ... }",
5765 * _Pc2line: <debug info for pc-to-line mapping>,
5766 * }
5767 *
5768 * Function instances:
5769 *
5770 * {
5771 * length: 2,
5772 * prototype: { constructor: <func> },
5773 * caller: <thrower>,
5774 * arguments: <thrower>,
5775 * name: "func", // declaration, named function expressions
5776 * fileName: <debug info for creating nice errors>
5777 * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
5778 * _Formals: [ "arg1", "arg2" ],
5779 * _Source: "function func(arg1, arg2) { ... }",
5780 * _Pc2line: <debug info for pc-to-line mapping>,
5781 * _Varenv: <variable environment of closure>,
5782 * _Lexenv: <lexical environment of closure (if differs from _Varenv)>
5783 * }
5784 *
5785 * More detailed description of these properties can be found
5786 * in the documentation.
5787 */
5788
5789#if defined(DUK_USE_DEBUGGER_SUPPORT)
5790 /* Line number range for function. Needed during debugging to
5791 * determine active breakpoints.
5792 */
5793 duk_uint32_t start_line;
5794 duk_uint32_t end_line;
5795#endif
5796};
5797
5798#endif /* DUK_HCOMPILEDFUNCTION_H_INCLUDED */
5799#line 1 "duk_hnativefunction.h"
5800/*
5801 * Heap native function representation.
5802 */
5804#ifndef DUK_HNATIVEFUNCTION_H_INCLUDED
5805#define DUK_HNATIVEFUNCTION_H_INCLUDED
5807#define DUK_HNATIVEFUNCTION_NARGS_VARARGS ((duk_int16_t) -1)
5808#define DUK_HNATIVEFUNCTION_NARGS_MAX ((duk_int16_t) 0x7fff)
5809
5810struct duk_hnativefunction {
5811 /* shared object part */
5813
5815 duk_int16_t nargs;
5816 duk_int16_t magic;
5817
5818 /* The 'magic' field allows an opaque 16-bit field to be accessed by the
5819 * Duktape/C function. This allows, for instance, the same native function
5820 * to be used for a set of very similar functions, with the 'magic' field
5821 * providing the necessary non-argument flags / values to guide the behavior
5822 * of the native function. The value is signed on purpose: it is easier to
5823 * convert a signed value to unsigned (simply AND with 0xffff) than vice
5824 * versa.
5825 *
5826 * Note: cannot place nargs/magic into the heaphdr flags, because
5827 * duk_hobject takes almost all flags already (and needs the spare).
5828 */
5829};
5830
5831#endif /* DUK_HNATIVEFUNCTION_H_INCLUDED */
5832#line 1 "duk_hbufferobject.h"
5833/*
5834 * Heap Buffer object representation. Used for all Buffer variants.
5835 */
5837#ifndef DUK_HBUFFEROBJECT_H_INCLUDED
5838#define DUK_HBUFFEROBJECT_H_INCLUDED
5840/* All element accessors are host endian now (driven by TypedArray spec). */
5841#define DUK_HBUFFEROBJECT_ELEM_UINT8 0
5842#define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED 1
5843#define DUK_HBUFFEROBJECT_ELEM_INT8 2
5844#define DUK_HBUFFEROBJECT_ELEM_UINT16 3
5845#define DUK_HBUFFEROBJECT_ELEM_INT16 4
5846#define DUK_HBUFFEROBJECT_ELEM_UINT32 5
5847#define DUK_HBUFFEROBJECT_ELEM_INT32 6
5848#define DUK_HBUFFEROBJECT_ELEM_FLOAT32 7
5849#define DUK_HBUFFEROBJECT_ELEM_FLOAT64 8
5850#define DUK_HBUFFEROBJECT_ELEM_MAX 8
5851
5852#define DUK_ASSERT_HBUFFEROBJECT_VALID(h) do { \
5853 DUK_ASSERT((h) != NULL); \
5854 DUK_ASSERT((h)->shift <= 3); \
5855 DUK_ASSERT((h)->elem_type <= DUK_HBUFFEROBJECT_ELEM_MAX); \
5856 DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8) || \
5857 ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) || \
5858 ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT8) || \
5859 ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT16) || \
5860 ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT16) || \
5861 ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT32) || \
5862 ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT32) || \
5863 ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT32) || \
5864 ((h)->shift == 3 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT64)); \
5865 DUK_ASSERT((h)->is_view == 0 || (h)->is_view == 1); \
5866 DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) (h))); \
5867 if ((h)->buf == NULL) { \
5868 DUK_ASSERT((h)->offset == 0); \
5869 DUK_ASSERT((h)->length == 0); \
5870 } else { \
5871 /* No assertions for offset or length; in particular, \
5872 * it's OK for length to be longer than underlying \
5873 * buffer. Just ensure they don't wrap when added. \
5874 */ \
5875 DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
5876 } \
5877 } while (0)
5878
5879/* Get the current data pointer (caller must ensure buf != NULL) as a
5880 * duk_uint8_t ptr.
5881 */
5882#define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap,h) \
5883 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5884 (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
5885
5886/* True if slice is full, i.e. offset is zero and length covers the entire
5887 * buffer. This status may change independently of the duk_hbufferobject if
5888 * the underlying buffer is dynamic and changes without the hbufferobject
5889 * being changed.
5890 */
5891#define DUK_HBUFFEROBJECT_FULL_SLICE(h) \
5892 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5893 ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
5894
5895/* Validate that the whole slice [0,length[ is contained in the underlying
5896 * buffer. Caller must ensure 'buf' != NULL.
5897 */
5898#define DUK_HBUFFEROBJECT_VALID_SLICE(h) \
5899 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5900 ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
5901
5902/* Validate byte read/write for virtual 'offset', i.e. check that the
5903 * offset, taking into account h->offset, is within the underlying
5904 * buffer size. This is a safety check which is needed to ensure
5905 * that even a misconfigured duk_hbufferobject never causes memory
5906 * unsafe behavior (e.g. if an underlying dynamic buffer changes
5907 * after being setup). Caller must ensure 'buf' != NULL.
5909#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_INCL(h,off) \
5910 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5911 ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
5912
5913#define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h,off) \
5914 (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5915 ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
5916
5917/* Clamp an input byte length (already assumed to be within the nominal
5918 * duk_hbufferobject 'length') to the current dynamic buffer limits to
5919 * yield a byte length limit that's safe for memory accesses. This value
5920 * can be invalidated by any side effect because it may trigger a user
5921 * callback that resizes the underlying buffer.
5922 */
5923#define DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h,len) \
5924 (DUK_ASSERT_EXPR((h) != NULL), \
5925 duk_hbufferobject_clamp_bytelength((h), (len)))
5926
5927struct duk_hbufferobject {
5928 /* Shared object part. */
5930
5931 /* Underlying buffer (refcounted), may be NULL. */
5933
5934 /* Slice and accessor information.
5935 *
5936 * Because the underlying buffer may be dynamic, these may be
5937 * invalidated by the buffer being modified so that both offset
5938 * and length should be validated before every access. Behavior
5939 * when the underlying buffer has changed doesn't need to be clean:
5940 * virtual 'length' doesn't need to be affected, reads can return
5941 * zero/NaN, and writes can be ignored.
5942 *
5943 * Note that a data pointer cannot be precomputed because 'buf' may
5944 * be dynamic and its pointer unstable.
5945 */
5946
5947 duk_uint_t offset; /* byte offset to buf */
5948 duk_uint_t length; /* byte index limit for element access, exclusive */
5949 duk_uint8_t shift; /* element size shift:
5950 * 0 = u8/i8
5951 * 1 = u16/i16
5952 * 2 = u32/i32/float
5953 * 3 = double
5954 */
5955 duk_uint8_t elem_type; /* element type */
5956 duk_uint8_t is_view;
5957};
5958
5959#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5961#endif
5964
5965#endif /* DUK_HBUFFEROBJECT_H_INCLUDED */
5966#line 1 "duk_hthread.h"
5967/*
5968 * Heap thread object representation.
5969 *
5970 * duk_hthread is also the 'context' (duk_context) for exposed APIs
5971 * which mostly operate on the topmost frame of the value stack.
5972 */
5973
5974#ifndef DUK_HTHREAD_H_INCLUDED
5975#define DUK_HTHREAD_H_INCLUDED
5978 * Stack constants
5981#define DUK_VALSTACK_GROW_STEP 128 /* roughly 1 kiB */
5982#define DUK_VALSTACK_SHRINK_THRESHOLD 256 /* roughly 2 kiB */
5983#define DUK_VALSTACK_SHRINK_SPARE 64 /* roughly 0.5 kiB */
5984#define DUK_VALSTACK_INITIAL_SIZE 128 /* roughly 1.0 kiB -> but rounds up to DUK_VALSTACK_GROW_STEP in practice */
5985#define DUK_VALSTACK_INTERNAL_EXTRA 64 /* internal extra elements assumed on function entry,
5986 * always added to user-defined 'extra' for e.g. the
5987 * duk_check_stack() call.
5988 */
5989#define DUK_VALSTACK_API_ENTRY_MINIMUM DUK_API_ENTRY_STACK
5990 /* number of elements guaranteed to be user accessible
5991 * (in addition to call arguments) on Duktape/C function entry.
5992 */
5994/* Note: DUK_VALSTACK_INITIAL_SIZE must be >= DUK_VALSTACK_API_ENTRY_MINIMUM
5995 * + DUK_VALSTACK_INTERNAL_EXTRA so that the initial stack conforms to spare
5996 * requirements.
5998
5999#define DUK_VALSTACK_DEFAULT_MAX 1000000L
6001#define DUK_CALLSTACK_GROW_STEP 8 /* roughly 256 bytes */
6002#define DUK_CALLSTACK_SHRINK_THRESHOLD 16 /* roughly 512 bytes */
6003#define DUK_CALLSTACK_SHRINK_SPARE 8 /* roughly 256 bytes */
6004#define DUK_CALLSTACK_INITIAL_SIZE 8
6005#define DUK_CALLSTACK_DEFAULT_MAX 10000L
6006
6007#define DUK_CATCHSTACK_GROW_STEP 4 /* roughly 64 bytes */
6008#define DUK_CATCHSTACK_SHRINK_THRESHOLD 8 /* roughly 128 bytes */
6009#define DUK_CATCHSTACK_SHRINK_SPARE 4 /* roughly 64 bytes */
6010#define DUK_CATCHSTACK_INITIAL_SIZE 4
6011#define DUK_CATCHSTACK_DEFAULT_MAX 10000L
6014 * Activation defines
6015 */
6017#define DUK_ACT_FLAG_STRICT (1 << 0) /* function executes in strict mode */
6018#define DUK_ACT_FLAG_TAILCALLED (1 << 1) /* activation has tail called one or more times */
6019#define DUK_ACT_FLAG_CONSTRUCT (1 << 2) /* function executes as a constructor (called via "new") */
6020#define DUK_ACT_FLAG_PREVENT_YIELD (1 << 3) /* activation prevents yield (native call or "new") */
6021#define DUK_ACT_FLAG_DIRECT_EVAL (1 << 4) /* activation is a direct eval call */
6022#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE (1 << 5) /* activation has active breakpoint(s) */
6023
6024#define DUK_ACT_GET_FUNC(act) ((act)->func)
6025
6026/*
6027 * Flags for __FILE__ / __LINE__ registered into tracedata
6028 */
6030#define DUK_TB_FLAG_NOBLAME_FILELINE (1 << 0) /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
6033 * Catcher defines
6034 */
6036/* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
6037#define DUK_CAT_TYPE_MASK 0x0000000fUL
6038#define DUK_CAT_TYPE_BITS 4
6039#define DUK_CAT_LABEL_MASK 0xffffff00UL
6040#define DUK_CAT_LABEL_BITS 24
6041#define DUK_CAT_LABEL_SHIFT 8
6043#define DUK_CAT_FLAG_CATCH_ENABLED (1 << 4) /* catch part will catch */
6044#define DUK_CAT_FLAG_FINALLY_ENABLED (1 << 5) /* finally part will catch */
6045#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED (1 << 6) /* request to create catch binding */
6046#define DUK_CAT_FLAG_LEXENV_ACTIVE (1 << 7) /* catch or with binding is currently active */
6048#define DUK_CAT_TYPE_UNKNOWN 0
6049#define DUK_CAT_TYPE_TCF 1
6050#define DUK_CAT_TYPE_LABEL 2
6051
6052#define DUK_CAT_GET_TYPE(c) ((c)->flags & DUK_CAT_TYPE_MASK)
6053#define DUK_CAT_GET_LABEL(c) (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
6054
6055#define DUK_CAT_HAS_CATCH_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
6056#define DUK_CAT_HAS_FINALLY_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
6057#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
6058#define DUK_CAT_HAS_LEXENV_ACTIVE(c) ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
6059
6060#define DUK_CAT_SET_CATCH_ENABLED(c) do { \
6061 (c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
6062 } while (0)
6063#define DUK_CAT_SET_FINALLY_ENABLED(c) do { \
6064 (c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
6065 } while (0)
6066#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c) do { \
6067 (c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6068 } while (0)
6069#define DUK_CAT_SET_LEXENV_ACTIVE(c) do { \
6070 (c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
6071 } while (0)
6072
6073#define DUK_CAT_CLEAR_CATCH_ENABLED(c) do { \
6074 (c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
6075 } while (0)
6076#define DUK_CAT_CLEAR_FINALLY_ENABLED(c) do { \
6077 (c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
6078 } while (0)
6079#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c) do { \
6080 (c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6081 } while (0)
6082#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c) do { \
6083 (c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
6084 } while (0)
6085
6086/*
6087 * Thread defines
6088 */
6089
6090#if defined(DUK_USE_ROM_STRINGS)
6091#define DUK_HTHREAD_GET_STRING(thr,idx) \
6092 ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
6093#else /* DUK_USE_ROM_STRINGS */
6094#if defined(DUK_USE_HEAPPTR16)
6095#define DUK_HTHREAD_GET_STRING(thr,idx) \
6096 ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
6097#else
6098#define DUK_HTHREAD_GET_STRING(thr,idx) \
6099 ((thr)->strs[(idx)])
6100#endif
6101#endif /* DUK_USE_ROM_STRINGS */
6103#define DUK_HTHREAD_GET_CURRENT_ACTIVATION(thr) (&(thr)->callstack[(thr)->callstack_top - 1])
6104
6105/* values for the state field */
6106#define DUK_HTHREAD_STATE_INACTIVE 1 /* thread not currently running */
6107#define DUK_HTHREAD_STATE_RUNNING 2 /* thread currently running (only one at a time) */
6108#define DUK_HTHREAD_STATE_RESUMED 3 /* thread resumed another thread (active but not running) */
6109#define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */
6110#define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */
6111
6112/* Executor interrupt default interval when nothing else requires a
6113 * smaller value. The default interval must be small enough to allow
6114 * for reasonable execution timeout checking but large enough to keep
6115 * impact on execution performance low.
6116 */
6117#if defined(DUK_USE_INTERRUPT_COUNTER)
6118#define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L)
6119#endif
6120
6121/*
6122 * Assert context is valid: non-NULL pointer, fields look sane.
6123 *
6124 * This is used by public API call entrypoints to catch invalid 'ctx' pointers
6125 * as early as possible; invalid 'ctx' pointers cause very odd and difficult to
6126 * diagnose behavior so it's worth checking even when the check is not 100%.
6127 */
6129#if defined(DUK_USE_PREFER_SIZE)
6130#define DUK_ASSERT_CTX_VSSIZE(ctx) /*nop*/
6131#else
6132#define DUK_ASSERT_CTX_VSSIZE(ctx) \
6133 DUK_ASSERT((duk_size_t) (((duk_hthread *) (ctx))->valstack_end - ((duk_hthread *) (ctx))->valstack) == \
6134 ((duk_hthread *) (ctx))->valstack_size)
6135#endif
6136#define DUK_ASSERT_CTX_VALID(ctx) do { \
6137 DUK_ASSERT((ctx) != NULL); \
6138 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (ctx)) == DUK_HTYPE_OBJECT); \
6139 DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (ctx))); \
6140 DUK_ASSERT(((duk_hthread *) (ctx))->unused1 == 0); \
6141 DUK_ASSERT(((duk_hthread *) (ctx))->unused2 == 0); \
6142 DUK_ASSERT(((duk_hthread *) (ctx))->valstack != NULL); \
6143 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack); \
6144 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack); \
6145 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack_bottom); \
6146 DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack_top); \
6147 DUK_ASSERT_CTX_VSSIZE((ctx)); \
6148 } while (0)
6149
6150/*
6151 * Struct defines
6152 */
6153
6154/* XXX: for a memory-code tradeoff, remove 'func' and make it's access either a function
6155 * or a macro. This would make the activation 32 bytes long on 32-bit platforms again.
6156 */
6157
6158/* Note: it's nice if size is 2^N (at least for 32-bit platforms). */
6159struct duk_activation {
6160 duk_tval tv_func; /* borrowed: full duk_tval for function being executed; for lightfuncs */
6161 duk_hobject *func; /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
6162 duk_hobject *var_env; /* current variable environment (may be NULL if delayed) */
6163 duk_hobject *lex_env; /* current lexical environment (may be NULL if delayed) */
6164#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
6165 /* Previous value of 'func' caller, restored when unwound. Only in use
6166 * when 'func' is non-strict.
6167 */
6168 duk_hobject *prev_caller;
6169#endif
6170
6171 duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
6172#if defined(DUK_USE_DEBUGGER_SUPPORT)
6173 duk_uint32_t prev_line; /* needed for stepping */
6174#endif
6176
6177 /* idx_bottom and idx_retval are only used for book-keeping of
6178 * Ecmascript-initiated calls, to allow returning to an Ecmascript
6179 * function properly. They are duk_size_t to match the convention
6180 * that value stack sizes are duk_size_t and local frame indices
6181 * are duk_idx_t.
6182 */
6183
6184 /* Bottom of valstack for this activation, used to reset
6185 * valstack_bottom on return; index is absolute. Note:
6186 * idx_top not needed because top is set to 'nregs' always
6187 * when returning to an Ecmascript activation.
6188 */
6190
6191 /* Return value when returning to this activation (points to caller
6192 * reg, not callee reg); index is absolute (only set if activation is
6193 * not topmost).
6194 *
6195 * Note: idx_bottom is always set, while idx_retval is only applicable
6196 * for activations below the topmost one. Currently idx_retval for
6197 * the topmost activation is considered garbage (and it not initialized
6198 * on entry or cleared on return; may contain previous or garbage
6199 * values).
6200 */
6202
6203 /* Current 'this' binding is the value just below idx_bottom.
6204 * Previously, 'this' binding was handled with an index to the
6205 * (calling) valstack. This works for everything except tail
6206 * calls, which must not "cumulate" valstack temps.
6207 */
6208};
6209
6210/* Note: it's nice if size is 2^N (not 4x4 = 16 bytes on 32 bit) */
6211struct duk_catcher {
6212 duk_hstring *h_varname; /* borrowed reference to catch variable name (or NULL if none) */
6213 /* (reference is valid as long activation exists) */
6214 duk_instr_t *pc_base; /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
6215 duk_size_t callstack_index; /* callstack index of related activation */
6216 duk_size_t idx_base; /* idx_base and idx_base+1 get completion value and type */
6217 duk_uint32_t flags; /* type and control flags, label number */
6218};
6219
6220struct duk_hthread {
6221 /* Shared object part */
6223
6224 /* Pointer to bytecode executor's 'curr_pc' variable. Used to copy
6225 * the current PC back into the topmost activation when activation
6226 * state is about to change (or "syncing" is otherwise needed). This
6227 * is rather awkward but important for performance, see execution.rst.
6228 */
6230
6231 /* Backpointers. */
6232 duk_heap *heap;
6233
6234 /* Current strictness flag: affects API calls. */
6235 duk_uint8_t strict;
6236
6237 /* Thread state. */
6238 duk_uint8_t state;
6239 duk_uint8_t unused1;
6240 duk_uint8_t unused2;
6241
6242 /* Sanity limits for stack sizes. */
6246
6247 /* XXX: Valstack, callstack, and catchstack are currently assumed
6248 * to have non-NULL pointers. Relaxing this would not lead to big
6249 * benefits (except perhaps for terminated threads).
6250 */
6251
6252 /* Value stack: these are expressed as pointers for faster stack manipulation.
6253 * [valstack,valstack_top[ is GC-reachable, [valstack_top,valstack_end[ is
6254 * not GC-reachable but kept initialized as 'undefined'.
6255 */
6256 duk_tval *valstack; /* start of valstack allocation */
6257 duk_tval *valstack_end; /* end of valstack allocation (exclusive) */
6258 duk_tval *valstack_bottom; /* bottom of current frame */
6259 duk_tval *valstack_top; /* top of current frame (exclusive) */
6260#if !defined(DUK_USE_PREFER_SIZE)
6261 duk_size_t valstack_size; /* cached: valstack_end - valstack (in entries, not bytes) */
6262#endif
6263
6264 /* Call stack. [0,callstack_top[ is GC reachable. */
6266 duk_size_t callstack_size; /* allocation size */
6267 duk_size_t callstack_top; /* next to use, highest used is top - 1 */
6268 duk_size_t callstack_preventcount; /* number of activation records in callstack preventing a yield */
6269
6270 /* Catch stack. [0,catchstack_top[ is GC reachable. */
6272 duk_size_t catchstack_size; /* allocation size */
6273 duk_size_t catchstack_top; /* next to use, highest used is top - 1 */
6274
6275 /* Yield/resume book-keeping. */
6276 duk_hthread *resumer; /* who resumed us (if any) */
6277
6278 /* Current compiler state (if any), used for augmenting SyntaxErrors. */
6280
6281#if defined(DUK_USE_INTERRUPT_COUNTER)
6282 /* Interrupt counter for triggering a slow path check for execution
6283 * timeout, debugger interaction such as breakpoints, etc. The value
6284 * is valid for the current running thread, and both the init and
6285 * counter values are copied whenever a thread switch occurs. It's
6286 * important for the counter to be conveniently accessible for the
6287 * bytecode executor inner loop for performance reasons.
6288 */
6289 duk_int_t interrupt_counter; /* countdown state */
6290 duk_int_t interrupt_init; /* start value for current countdown */
6291#endif
6292
6293 /* Builtin-objects; may or may not be shared with other threads,
6294 * threads existing in different "compartments" will have different
6295 * built-ins. Must be stored on a per-thread basis because there
6296 * is no intermediate structure for a thread group / compartment.
6297 * This takes quite a lot of space, currently 43x4 = 172 bytes on
6298 * 32-bit platforms.
6299 *
6300 * In some cases the builtins array could be ROM based, but it's
6301 * sometimes edited (e.g. for sandboxing) so it's better to keep
6302 * this array in RAM.
6303 */
6305
6306 /* Convenience copies from heap/vm for faster access. */
6307#if defined(DUK_USE_ROM_STRINGS)
6308 /* No field needed when strings are in ROM. */
6309#else
6310#if defined(DUK_USE_HEAPPTR16)
6311 duk_uint16_t *strs16;
6312#else
6313 duk_hstring **strs;
6314#endif
6315#endif
6316};
6317
6318/*
6319 * Prototypes
6320 */
6321
6326
6333
6335DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6336DUK_INTERNAL_DECL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6337DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6338
6339#if defined(DUK_USE_DEBUGGER_SUPPORT)
6340DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
6341#endif
6345
6346#endif /* DUK_HTHREAD_H_INCLUDED */
6347#line 1 "duk_hbuffer.h"
6348/*
6349 * Heap buffer representation.
6350 *
6351 * Heap allocated user data buffer which is either:
6353 * 1. A fixed size buffer (data follows header statically)
6354 * 2. A dynamic size buffer (data pointer follows header)
6355 *
6356 * The data pointer for a variable size buffer of zero size may be NULL.
6357 */
6358
6359#ifndef DUK_HBUFFER_H_INCLUDED
6360#define DUK_HBUFFER_H_INCLUDED
6361
6363 * Flags
6364 *
6365 * Fixed buffer: 0
6366 * Dynamic buffer: DUK_HBUFFER_FLAG_DYNAMIC
6367 * External buffer: DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
6370#define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */
6371#define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */
6373#define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6374#define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6375
6376#define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6377#define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6378
6379#define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6380#define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6381
6382/*
6383 * Misc defines
6384 */
6385
6386/* Impose a maximum buffer length for now. Restricted artificially to
6387 * ensure resize computations or adding a heap header length won't
6388 * overflow size_t and that a signed duk_int_t can hold a buffer
6389 * length. The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
6391
6392#if defined(DUK_USE_BUFLEN16)
6393#define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL)
6394#else
6395/* Intentionally not 0x7fffffffUL; at least JSON code expects that
6396 * 2*len + 2 fits in 32 bits.
6397 */
6398#define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL)
6399#endif
6400
6401/*
6402 * Field access
6403 */
6404
6405/* Get/set the current user visible size, without accounting for a dynamic
6406 * buffer's "spare" (= usable size).
6407 */
6408#if defined(DUK_USE_BUFLEN16)
6409/* size stored in duk_heaphdr unused flag bits */
6410#define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16)
6411#define DUK_HBUFFER_SET_SIZE(x,v) do { \
6412 duk_size_t duk__v; \
6413 duk__v = (v); \
6414 DUK_ASSERT(duk__v <= 0xffffUL); \
6415 (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
6416 } while (0)
6417#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
6418 (x)->hdr.h_flags += ((dv) << 16); \
6419 } while (0)
6420#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
6421 (x)->hdr.h_flags -= ((dv) << 16); \
6422 } while (0)
6423#else
6424#define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size)
6425#define DUK_HBUFFER_SET_SIZE(x,v) do { \
6426 ((duk_hbuffer *) (x))->size = (v); \
6427 } while (0)
6428#define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
6429 (x)->size += (dv); \
6430 } while (0)
6431#define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
6432 (x)->size -= (dv); \
6433 } while (0)
6434#endif
6435
6436#define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6437#define DUK_HBUFFER_FIXED_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
6438
6439#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6440#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
6441#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
6442#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
6443
6444#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6445#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
6446
6447#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
6448
6449#if defined(DUK_USE_HEAPPTR16)
6450#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
6451 ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
6452#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
6453 ((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6454 } while (0)
6455#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
6456 ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \
6457 } while (0)
6458#else
6459#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) ((x)->curr_alloc)
6460#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
6461 (x)->curr_alloc = (void *) (v); \
6462 } while (0)
6463#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
6464 (x)->curr_alloc = (void *) NULL; \
6465 } while (0)
6466#endif
6467
6468/* No pointer compression because pointer is potentially outside of
6469 * Duktape heap.
6470 */
6471#if defined(DUK_USE_HEAPPTR16)
6472#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
6473 ((void *) (x)->curr_alloc)
6474#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
6475 (x)->curr_alloc = (void *) (v); \
6476 } while (0)
6477#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
6478 (x)->curr_alloc = (void *) NULL; \
6479 } while (0)
6480#else
6481#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
6482 ((void *) (x)->curr_alloc)
6483#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
6484 (x)->curr_alloc = (void *) (v); \
6485 } while (0)
6486#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
6487 (x)->curr_alloc = (void *) NULL; \
6488 } while (0)
6489#endif
6490
6491/* Get a pointer to the current buffer contents (matching current allocation
6492 * size). May be NULL for zero size dynamic/external buffer.
6493 */
6494#if defined(DUK_USE_HEAPPTR16)
6495#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
6496 DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
6497 ( \
6498 DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
6499 DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
6500 DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
6501 ) : \
6502 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
6503 )
6504#else
6505/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
6506 * have the same layout so checking for fixed vs. dynamic (or external) is enough.
6507 */
6508#define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
6509 DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
6510 DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
6511 DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
6512 )
6513#endif
6514
6515/*
6516 * Structs
6517 */
6518
6519/* Shared prefix for all buffer types. */
6520struct duk_hbuffer {
6522
6523 /* It's not strictly necessary to track the current size, but
6524 * it is useful for writing robust native code.
6525 */
6526
6527 /* Current size (not counting a dynamic buffer's "spare"). */
6528#if defined(DUK_USE_BUFLEN16)
6529 /* Stored in duk_heaphdr unused flags. */
6530#else
6532#endif
6533
6534 /*
6535 * Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
6536 * flag.
6537 *
6538 * If the flag is clear (the buffer is a fixed size one), the buffer
6539 * data follows the header directly, consisting of 'size' bytes.
6540 *
6541 * If the flag is set, the actual buffer is allocated separately, and
6542 * a few control fields follow the header. Specifically:
6543 *
6544 * - a "void *" pointing to the current allocation
6545 * - a duk_size_t indicating the full allocated size (always >= 'size')
6546 *
6547 * If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
6548 * by user code, so that Duktape won't be able to resize it and won't
6549 * free it. This allows buffers to point to e.g. an externally
6550 * allocated structure such as a frame buffer.
6551 *
6552 * Unlike strings, no terminator byte (NUL) is guaranteed after the
6553 * data. This would be convenient, but would pad aligned user buffers
6554 * unnecessarily upwards in size. For instance, if user code requested
6555 * a 64-byte dynamic buffer, 65 bytes would actually be allocated which
6556 * would then potentially round upwards to perhaps 68 or 72 bytes.
6557 */
6558};
6559
6560/* Fixed buffer; data follows struct, with proper alignment guaranteed by
6561 * struct size.
6562 */
6563#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
6564#pragma pack(push, 8)
6565#endif
6566struct duk_hbuffer_fixed {
6567 /* A union is used here as a portable struct size / alignment trick:
6568 * by adding a 32-bit or a 64-bit (unused) union member, the size of
6569 * the struct is effectively forced to be a multiple of 4 or 8 bytes
6570 * (respectively) without increasing the size of the struct unless
6571 * necessary.
6572 */
6573 union {
6574 struct {
6576#if defined(DUK_USE_BUFLEN16)
6577 /* Stored in duk_heaphdr unused flags. */
6578#else
6580#endif
6581 } s;
6582#if (DUK_USE_ALIGN_BY == 4)
6583 duk_uint32_t dummy_for_align4;
6584#elif (DUK_USE_ALIGN_BY == 8)
6586#elif (DUK_USE_ALIGN_BY == 1)
6587 /* no extra padding */
6588#else
6589#error invalid DUK_USE_ALIGN_BY
6590#endif
6591 } u;
6592
6593 /*
6594 * Data follows the struct header. The struct size is padded by the
6595 * compiler based on the struct members. This guarantees that the
6596 * buffer data will be aligned-by-4 but not necessarily aligned-by-8.
6597 *
6598 * On platforms where alignment does not matter, the struct padding
6599 * could be removed (if there is any). On platforms where alignment
6600 * by 8 is required, the struct size must be forced to be a multiple
6601 * of 8 by some means. Without it, some user code may break, and also
6602 * Duktape itself breaks (e.g. the compiler stores duk_tvals in a
6603 * dynamic buffer).
6604 */
6605}
6606#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
6607__attribute__ ((aligned (8)))
6608#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
6609__attribute__ ((aligned (8)))
6610#endif
6611;
6612#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
6613#pragma pack(pop)
6614#endif
6615
6616/* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
6617 * heap allocation primitives. Also used for external buffers when low memory
6618 * options are not used.
6619 */
6620struct duk_hbuffer_dynamic {
6622
6623#if defined(DUK_USE_BUFLEN16)
6624 /* Stored in duk_heaphdr unused flags. */
6625#else
6627#endif
6628
6629#if defined(DUK_USE_HEAPPTR16)
6630 /* Stored in duk_heaphdr h_extra16. */
6631#else
6632 void *curr_alloc; /* may be NULL if alloc_size == 0 */
6633#endif
6634
6635 /*
6636 * Allocation size for 'curr_alloc' is alloc_size. There is no
6637 * automatic NUL terminator for buffers (see above for rationale).
6638 *
6639 * 'curr_alloc' is explicitly allocated with heap allocation
6640 * primitives and will thus always have alignment suitable for
6641 * e.g. duk_tval and an IEEE double.
6642 */
6643};
6644
6645/* External buffer with 'curr_alloc' managed by user code and pointing to an
6646 * arbitrary address. When heap pointer compression is not used, this struct
6647 * has the same layout as duk_hbuffer_dynamic.
6648 */
6649struct duk_hbuffer_external {
6651
6652#if defined(DUK_USE_BUFLEN16)
6653 /* Stored in duk_heaphdr unused flags. */
6654#else
6656#endif
6657
6658 /* Cannot be compressed as a heap pointer because may point to
6659 * an arbitrary address.
6660 */
6661 void *curr_alloc; /* may be NULL if alloc_size == 0 */
6662};
6663
6664/*
6665 * Prototypes
6666 */
6667
6669DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */
6670
6671/* dynamic buffer ops */
6674
6675#endif /* DUK_HBUFFER_H_INCLUDED */
6676#line 1 "duk_heap.h"
6678 * Heap structure.
6679 *
6680 * Heap contains allocated heap objects, interned strings, and built-in
6681 * strings for one or more threads.
6682 */
6683
6684#ifndef DUK_HEAP_H_INCLUDED
6685#define DUK_HEAP_H_INCLUDED
6687/* alloc function typedefs in duktape.h */
6690 * Heap flags
6691 */
6693#define DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING (1 << 0) /* mark-and-sweep is currently running */
6694#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED (1 << 1) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
6695#define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING (1 << 2) /* refcount code is processing refzero list */
6696#define DUK_HEAP_FLAG_ERRHANDLER_RUNNING (1 << 3) /* an error handler (user callback to augment/replace error) is running */
6697#define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1 << 4) /* executor interrupt running (used to avoid nested interrupts) */
6698#define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1 << 5) /* heap destruction ongoing, finalizer rescue no longer possible */
6699
6700#define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits))
6701#define DUK__HEAP_SET_FLAGS(heap,bits) do { \
6702 (heap)->flags |= (bits); \
6703 } while (0)
6704#define DUK__HEAP_CLEAR_FLAGS(heap,bits) do { \
6705 (heap)->flags &= ~(bits); \
6706 } while (0)
6708#define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6709#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6710#define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6711#define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6712#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6713#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6715#define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6716#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6717#define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6718#define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6719#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6720#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6721
6722#define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6723#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6724#define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6725#define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6726#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6727#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6730 * Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
6733#define DUK_LJ_TYPE_UNKNOWN 0 /* unused */
6734#define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */
6735#define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */
6736#define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
6737#define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
6738#define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
6739#define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
6740#define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
6741
6743 * Mark-and-sweep flags
6745 * These are separate from heap level flags now but could be merged.
6746 * The heap structure only contains a 'base mark-and-sweep flags'
6747 * field and the GC caller can impose further flags.
6748 */
6749
6750#define DUK_MS_FLAG_EMERGENCY (1 << 0) /* emergency mode: try extra hard */
6751#define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE (1 << 1) /* don't resize stringtable (but may sweep it); needed during stringtable resize */
6752#define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1 << 2) /* don't compact objects; needed during object property allocation resize */
6753#define DUK_MS_FLAG_NO_FINALIZERS (1 << 3) /* don't run finalizers; leave finalizable objects in finalize_list for next round */
6754#define DUK_MS_FLAG_SKIP_FINALIZERS (1 << 4) /* don't run finalizers; queue finalizable objects back to heap_allocated */
6755
6756/*
6757 * Thread switching
6758 *
6759 * To switch heap->curr_thread, use the macro below so that interrupt counters
6760 * get updated correctly. The macro allows a NULL target thread because that
6761 * happens e.g. in call handling.
6762 */
6763
6764#if defined(DUK_USE_INTERRUPT_COUNTER)
6765#define DUK_HEAP_SWITCH_THREAD(heap,newthr) duk_heap_switch_thread((heap), (newthr))
6766#else
6767#define DUK_HEAP_SWITCH_THREAD(heap,newthr) do { \
6768 (heap)->curr_thread = (newthr); \
6769 } while (0)
6770#endif
6771
6772/*
6773 * Other heap related defines
6774 */
6775
6776/* Mark-and-sweep interval is relative to combined count of objects and
6777 * strings kept in the heap during the latest mark-and-sweep pass.
6778 * Fixed point .8 multiplier and .0 adder. Trigger count (interval) is
6779 * decreased by each (re)allocation attempt (regardless of size), and each
6780 * refzero processed object.
6782 * 'SKIP' indicates how many (re)allocations to wait until a retry if
6783 * GC is skipped because there is no thread do it with yet (happens
6784 * only during init phases).
6785 */
6786#if defined(DUK_USE_MARK_AND_SWEEP)
6787#if defined(DUK_USE_REFERENCE_COUNTING)
6788#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */
6789#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
6790#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
6791#else
6792#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */
6793#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
6794#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
6795#endif
6796#endif
6798/* Stringcache is used for speeding up char-offset-to-byte-offset
6799 * translations for non-ASCII strings.
6800 */
6801#define DUK_HEAP_STRCACHE_SIZE 4
6802#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */
6803
6804/* helper to insert a (non-string) heap object into heap allocated list */
6805#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap),(hdr))
6806
6808 * Stringtable
6809 */
6811/* initial stringtable size, must be prime and higher than DUK_UTIL_MIN_HASH_PRIME */
6812#define DUK_STRTAB_INITIAL_SIZE 17
6813
6814/* indicates a deleted string; any fixed non-NULL, non-hstring pointer works */
6815#define DUK_STRTAB_DELETED_MARKER(heap) ((duk_hstring *) heap)
6816
6817/* resizing parameters */
6818#define DUK_STRTAB_MIN_FREE_DIVISOR 4 /* load factor max 75% */
6819#define DUK_STRTAB_MIN_USED_DIVISOR 4 /* load factor min 25% */
6820#define DUK_STRTAB_GROW_ST_SIZE(n) ((n) + (n)) /* used entries + approx 100% -> reset load to 50% */
6821
6822#define DUK_STRTAB_U32_MAX_STRLEN 10 /* 4'294'967'295 */
6823#define DUK_STRTAB_HIGHEST_32BIT_PRIME 0xfffffffbUL
6824
6825/* probe sequence (open addressing) */
6826#define DUK_STRTAB_HASH_INITIAL(hash,h_size) ((hash) % (h_size))
6827#define DUK_STRTAB_HASH_PROBE_STEP(hash) DUK_UTIL_GET_HASH_PROBE_STEP((hash))
6828
6829/* fixed top level hashtable size (separate chaining) */
6830#define DUK_STRTAB_CHAIN_SIZE DUK_USE_STRTAB_CHAIN_SIZE
6831
6832/*
6833 * Built-in strings
6834 */
6835
6836/* heap string indices are autogenerated in duk_strings.h */
6837#if defined(DUK_USE_ROM_STRINGS)
6838#define DUK_HEAP_GET_STRING(heap,idx) \
6839 ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
6840#else /* DUK_USE_ROM_STRINGS */
6841#if defined(DUK_USE_HEAPPTR16)
6842#define DUK_HEAP_GET_STRING(heap,idx) \
6843 ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
6844#else
6845#define DUK_HEAP_GET_STRING(heap,idx) \
6846 ((heap)->strs[(idx)])
6847#endif
6848#endif /* DUK_USE_ROM_STRINGS */
6850/*
6851 * Raw memory calls: relative to heap, but no GC interaction
6853
6854#define DUK_ALLOC_RAW(heap,size) \
6855 ((heap)->alloc_func((heap)->heap_udata, (size)))
6856
6857#define DUK_REALLOC_RAW(heap,ptr,newsize) \
6858 ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
6859
6860#define DUK_FREE_RAW(heap,ptr) \
6861 ((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
6862
6863/*
6864 * Memory calls: relative to heap, GC interaction, but no error throwing.
6865 *
6866 * XXX: Currently a mark-and-sweep triggered by memory allocation will run
6867 * using the heap->heap_thread. This thread is also used for running
6868 * mark-and-sweep finalization; this is not ideal because it breaks the
6869 * isolation between multiple global environments.
6870 *
6871 * Notes:
6872 *
6873 * - DUK_FREE() is required to ignore NULL and any other possible return
6874 * value of a zero-sized alloc/realloc (same as ANSI C free()).
6875 *
6876 * - There is no DUK_REALLOC_ZEROED because we don't assume to know the
6877 * old size. Caller must zero the reallocated memory.
6878 *
6879 * - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
6880 * by an allocation failure might invalidate the original 'ptr', thus
6881 * causing a realloc retry to use an invalid pointer. Example: we're
6882 * reallocating the value stack and a finalizer resizes the same value
6883 * stack during mark-and-sweep. The indirect variant requests for the
6884 * current location of the pointer being reallocated using a callback
6885 * right before every realloc attempt; this circuitous approach is used
6886 * to avoid strict aliasing issues in a more straightforward indirect
6887 * pointer (void **) approach. Note: the pointer in the storage
6888 * location is read but is NOT updated; the caller must do that.
6891/* callback for indirect reallocs, request for current pointer */
6892typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
6893
6894#define DUK_ALLOC(heap,size) duk_heap_mem_alloc((heap), (size))
6895#define DUK_ALLOC_ZEROED(heap,size) duk_heap_mem_alloc_zeroed((heap), (size))
6896#define DUK_REALLOC(heap,ptr,newsize) duk_heap_mem_realloc((heap), (ptr), (newsize))
6897#define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
6898#define DUK_FREE(heap,ptr) duk_heap_mem_free((heap), (ptr))
6899
6900/*
6901 * Memory constants
6902 */
6903
6904#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT 5 /* Retry allocation after mark-and-sweep for this
6905 * many times. A single mark-and-sweep round is
6906 * not guaranteed to free all unreferenced memory
6907 * because of finalization (in fact, ANY number of
6908 * rounds is strictly not enough).
6909 */
6910
6911#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT 3 /* Starting from this round, use emergency mode
6912 * for mark-and-sweep.
6913 */
6915/*
6916 * Debugger support
6918
6919/* Maximum number of breakpoints. Only breakpoints that are set are
6920 * consulted so increasing this has no performance impact.
6922#define DUK_HEAP_MAX_BREAKPOINTS 16
6924/* Opcode interval for a Date-based status/peek rate limit check. Only
6925 * relevant when debugger is attached. Requesting a timestamp may be a
6926 * slow operation on some platforms so this shouldn't be too low. On the
6927 * other hand a high value makes Duktape react to a pause request slowly.
6928 */
6929#define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000
6930
6931/* Milliseconds between status notify and transport peeks. */
6932#define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200
6933
6934/* Step types */
6935#define DUK_STEP_TYPE_NONE 0
6936#define DUK_STEP_TYPE_INTO 1
6937#define DUK_STEP_TYPE_OVER 2
6938#define DUK_STEP_TYPE_OUT 3
6939
6940struct duk_breakpoint {
6942 duk_uint32_t line;
6943};
6944
6945#if defined(DUK_USE_DEBUGGER_SUPPORT)
6946#define DUK_HEAP_IS_DEBUGGER_ATTACHED(heap) ((heap)->dbg_read_cb != NULL)
6947#define DUK_HEAP_CLEAR_STEP_STATE(heap) do { \
6948 (heap)->dbg_step_type = DUK_STEP_TYPE_NONE; \
6949 (heap)->dbg_step_thread = NULL; \
6950 (heap)->dbg_step_csindex = 0; \
6951 (heap)->dbg_step_startline = 0; \
6952 } while (0)
6953#define DUK_HEAP_SET_PAUSED(heap) do { \
6954 (heap)->dbg_paused = 1; \
6955 (heap)->dbg_state_dirty = 1; \
6956 DUK_HEAP_CLEAR_STEP_STATE((heap)); \
6957 } while (0)
6958#define DUK_HEAP_CLEAR_PAUSED(heap) do { \
6959 (heap)->dbg_paused = 0; \
6960 (heap)->dbg_state_dirty = 1; \
6961 DUK_HEAP_CLEAR_STEP_STATE((heap)); \
6962 } while (0)
6963#define DUK_HEAP_IS_PAUSED(heap) ((heap)->dbg_paused)
6964#endif /* DUK_USE_DEBUGGER_SUPPORT */
6965
6966/*
6967 * String cache should ideally be at duk_hthread level, but that would
6968 * cause string finalization to slow down relative to the number of
6969 * threads; string finalization must check the string cache for "weak"
6970 * references to the string being finalized to avoid dead pointers.
6971 *
6972 * Thus, string caches are now at the heap level now.
6973 */
6974
6975struct duk_strcache {
6976 duk_hstring *h;
6977 duk_uint32_t bidx;
6978 duk_uint32_t cidx;
6979};
6980
6981/*
6982 * Longjmp state, contains the information needed to perform a longjmp.
6983 * Longjmp related values are written to value1, value2, and iserror.
6984 */
6985
6986struct duk_ljstate {
6987 duk_jmpbuf *jmpbuf_ptr; /* current setjmp() catchpoint */
6988 duk_small_uint_t type; /* longjmp type */
6989 duk_bool_t iserror; /* isError flag for yield */
6990 duk_tval value1; /* 1st related value (type specific) */
6991 duk_tval value2; /* 2nd related value (type specific) */
6992};
6993
6994/*
6995 * Stringtable entry for fixed size stringtable
6996 */
6997
6999#if defined(DUK_USE_HEAPPTR16)
7000 /* A 16-bit listlen makes sense with 16-bit heap pointers: there
7001 * won't be space for 64k strings anyway.
7002 */
7003 duk_uint16_t listlen; /* if 0, 'str16' used, if > 0, 'strlist16' used */
7004 union {
7005 duk_uint16_t strlist16;
7006 duk_uint16_t str16;
7007 } u;
7008#else
7009 duk_size_t listlen; /* if 0, 'str' used, if > 0, 'strlist' used */
7010 union {
7013 } u;
7014#endif
7015};
7016
7017/*
7018 * Main heap structure
7019 */
7020
7021struct duk_heap {
7023
7024 /* Allocator functions. */
7028
7029 /* Heap udata, used for allocator functions but also for other heap
7030 * level callbacks like pointer compression, etc.
7031 */
7032 void *heap_udata;
7033
7034 /* Precomputed pointers when using 16-bit heap pointer packing. */
7035#if defined(DUK_USE_HEAPPTR16)
7036 duk_uint16_t heapptr_null16;
7037 duk_uint16_t heapptr_deleted16;
7038#endif
7039
7040 /* Fatal error handling, called e.g. when a longjmp() is needed but
7041 * lj.jmpbuf_ptr is NULL. fatal_func must never return; it's not
7042 * declared as "noreturn" because doing that for typedefs is a bit
7043 * challenging portability-wise.
7044 */
7046
7047 /* allocated heap objects */
7049
7050 /* work list for objects whose refcounts are zero but which have not been
7051 * "finalized"; avoids recursive C calls when refcounts go to zero in a
7052 * chain of objects.
7053 */
7054#if defined(DUK_USE_REFERENCE_COUNTING)
7057#endif
7058
7059#if defined(DUK_USE_MARK_AND_SWEEP)
7060 /* mark-and-sweep control */
7061#if defined(DUK_USE_VOLUNTARY_GC)
7063#endif
7065
7066 /* mark-and-sweep flags automatically active (used for critical sections) */
7068
7069 /* work list for objects to be finalized (by mark-and-sweep) */
7071#endif
7072
7073 /* longjmp state */
7075
7076 /* marker for detecting internal "double faults", see duk_error_throw.c */
7078
7079 /* heap thread, used internally and for finalization */
7081
7082 /* current thread */
7083 duk_hthread *curr_thread; /* currently running thread */
7084
7085 /* heap level "stash" object (e.g., various reachability roots) */
7087
7088 /* duk_handle_call / duk_handle_safe_call recursion depth limiting */
7091
7092 /* mix-in value for computing string hashes; should be reasonably unpredictable */
7093 duk_uint32_t hash_seed;
7094
7095 /* rnd_state for duk_util_tinyrandom.c */
7096 duk_uint32_t rnd_state;
7097
7098 /* For manual debugging: instruction count based on executor and
7099 * interrupt counter book-keeping. Inspect debug logs to see how
7100 * they match up.
7101 */
7102#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
7103 duk_int_t inst_count_exec;
7104 duk_int_t inst_count_interrupt;
7105#endif
7106
7107 /* debugger */
7108
7109#if defined(DUK_USE_DEBUGGER_SUPPORT)
7110 /* callbacks and udata; dbg_read_cb != NULL is used to indicate attached state */
7111 duk_debug_read_function dbg_read_cb; /* required, NULL implies detached */
7112 duk_debug_write_function dbg_write_cb; /* required */
7113 duk_debug_peek_function dbg_peek_cb;
7114 duk_debug_read_flush_function dbg_read_flush_cb;
7115 duk_debug_write_flush_function dbg_write_flush_cb;
7116 duk_debug_request_function dbg_request_cb;
7117 duk_debug_detached_function dbg_detached_cb;
7118 void *dbg_udata;
7119
7120 /* debugger state, only relevant when attached */
7121 duk_bool_t dbg_processing; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
7122 duk_bool_t dbg_paused; /* currently paused: talk with debug client until step/resume */
7123 duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */
7124 duk_bool_t dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
7125 duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */
7126 duk_small_uint_t dbg_step_type; /* step type: none, step into, step over, step out */
7127 duk_hthread *dbg_step_thread; /* borrowed; NULL if no step state (NULLed in unwind) */
7128 duk_size_t dbg_step_csindex; /* callstack index */
7129 duk_uint32_t dbg_step_startline; /* starting line number */
7130 duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS]; /* breakpoints: [0,breakpoint_count[ gc reachable */
7131 duk_small_uint_t dbg_breakpoint_count;
7132 duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1]; /* currently active breakpoints: NULL term, borrowed pointers */
7133 /* XXX: make active breakpoints actual copies instead of pointers? */
7134
7135 /* These are for rate limiting Status notifications and transport peeking. */
7136 duk_uint32_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */
7137 duk_uint32_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */
7138 duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */
7139
7140 /* Used to support single-byte stream lookahead. */
7141 duk_bool_t dbg_have_next_byte;
7142 duk_uint8_t dbg_next_byte;
7143#endif
7144
7145 /* string intern table (weak refs) */
7146#if defined(DUK_USE_STRTAB_PROBE)
7147#if defined(DUK_USE_HEAPPTR16)
7148 duk_uint16_t *strtable16;
7149#else
7151#endif
7152 duk_uint32_t st_size; /* alloc size in elements */
7153 duk_uint32_t st_used; /* used elements (includes DELETED) */
7154#endif
7155
7156 /* XXX: static alloc is OK until separate chaining stringtable
7157 * resizing is implemented.
7158 */
7159#if defined(DUK_USE_STRTAB_CHAIN)
7161#endif
7162
7163 /* string access cache (codepoint offset -> byte offset) for fast string
7164 * character looping; 'weak' reference which needs special handling in GC.
7165 */
7167
7168 /* built-in strings */
7169#if defined(DUK_USE_ROM_STRINGS)
7170 /* No field needed when strings are in ROM. */
7171#else
7172#if defined(DUK_USE_HEAPPTR16)
7173 duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
7174#else
7176#endif
7177#endif
7178};
7179
7180/*
7181 * Prototypes
7182 */
7183
7186 duk_realloc_function realloc_func,
7187 duk_free_function free_func,
7188 void *heap_udata,
7189 duk_fatal_function fatal_func);
7195
7197#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
7199#endif
7200#if defined(DUK_USE_INTERRUPT_COUNTER)
7201DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
7202#endif
7203
7204#if 0 /*unused*/
7205DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7206#endif
7207DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7208DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
7209#if 0 /*unused*/
7210DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val);
7211#endif
7214#if defined(DUK_USE_REFERENCE_COUNTING)
7216#endif
7217#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
7219#endif
7221#if defined(DUK_USE_DEBUG)
7222DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap);
7223#endif
7224
7225
7228
7229#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
7231DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
7232DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
7233#endif
7234
7237DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
7239DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
7240
7241#ifdef DUK_USE_REFERENCE_COUNTING
7242#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
7243DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
7244#endif
7245#if 0 /* unused */
7246DUK_INTERNAL_DECL void duk_tval_incref_allownull(duk_tval *tv);
7247#endif
7249#if 0 /* unused */
7250DUK_INTERNAL_DECL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv);
7251#endif
7252#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
7253DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
7254#endif
7255#if 0 /* unused */
7256DUK_INTERNAL_DECL void duk_heaphdr_incref_allownull(duk_heaphdr *h);
7257#endif
7262#else
7263/* no refcounting */
7264#endif
7266#if defined(DUK_USE_MARK_AND_SWEEP)
7268#endif
7270DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
7271
7272#endif /* DUK_HEAP_H_INCLUDED */
7273#line 1 "duk_debugger.h"
7274#ifndef DUK_DEBUGGER_H_INCLUDED
7275#define DUK_DEBUGGER_H_INCLUDED
7277/* Debugger protocol version is defined in the public API header. */
7279/* Initial bytes for markers. */
7280#define DUK_DBG_IB_EOM 0x00
7281#define DUK_DBG_IB_REQUEST 0x01
7282#define DUK_DBG_IB_REPLY 0x02
7283#define DUK_DBG_IB_ERROR 0x03
7284#define DUK_DBG_IB_NOTIFY 0x04
7286/* Other initial bytes. */
7287#define DUK_DBG_IB_INT4 0x10
7288#define DUK_DBG_IB_STR4 0x11
7289#define DUK_DBG_IB_STR2 0x12
7290#define DUK_DBG_IB_BUF4 0x13
7291#define DUK_DBG_IB_BUF2 0x14
7292#define DUK_DBG_IB_UNUSED 0x15
7293#define DUK_DBG_IB_UNDEFINED 0x16
7294#define DUK_DBG_IB_NULL 0x17
7295#define DUK_DBG_IB_TRUE 0x18
7296#define DUK_DBG_IB_FALSE 0x19
7297#define DUK_DBG_IB_NUMBER 0x1a
7298#define DUK_DBG_IB_OBJECT 0x1b
7299#define DUK_DBG_IB_POINTER 0x1c
7300#define DUK_DBG_IB_LIGHTFUNC 0x1d
7301#define DUK_DBG_IB_HEAPPTR 0x1e
7302/* The short string/integer initial bytes starting from 0x60 don't have
7303 * defines now.
7306/* Error codes. */
7307#define DUK_DBG_ERR_UNKNOWN 0x00
7308#define DUK_DBG_ERR_UNSUPPORTED 0x01
7309#define DUK_DBG_ERR_TOOMANY 0x02
7310#define DUK_DBG_ERR_NOTFOUND 0x03
7311#define DUK_DBG_ERR_APPLICATION 0x04
7313/* Commands and notifys initiated by Duktape. */
7314#define DUK_DBG_CMD_STATUS 0x01
7315#define DUK_DBG_CMD_PRINT 0x02
7316#define DUK_DBG_CMD_ALERT 0x03
7317#define DUK_DBG_CMD_LOG 0x04
7318#define DUK_DBG_CMD_THROW 0x05
7319#define DUK_DBG_CMD_DETACHING 0x06
7320#define DUK_DBG_CMD_APPNOTIFY 0x07
7322/* Commands initiated by debug client. */
7323#define DUK_DBG_CMD_BASICINFO 0x10
7324#define DUK_DBG_CMD_TRIGGERSTATUS 0x11
7325#define DUK_DBG_CMD_PAUSE 0x12
7326#define DUK_DBG_CMD_RESUME 0x13
7327#define DUK_DBG_CMD_STEPINTO 0x14
7328#define DUK_DBG_CMD_STEPOVER 0x15
7329#define DUK_DBG_CMD_STEPOUT 0x16
7330#define DUK_DBG_CMD_LISTBREAK 0x17
7331#define DUK_DBG_CMD_ADDBREAK 0x18
7332#define DUK_DBG_CMD_DELBREAK 0x19
7333#define DUK_DBG_CMD_GETVAR 0x1a
7334#define DUK_DBG_CMD_PUTVAR 0x1b
7335#define DUK_DBG_CMD_GETCALLSTACK 0x1c
7336#define DUK_DBG_CMD_GETLOCALS 0x1d
7337#define DUK_DBG_CMD_EVAL 0x1e
7338#define DUK_DBG_CMD_DETACH 0x1f
7339#define DUK_DBG_CMD_DUMPHEAP 0x20
7340#define DUK_DBG_CMD_GETBYTECODE 0x21
7341#define DUK_DBG_CMD_APPREQUEST 0x22
7342#define DUK_DBG_CMD_GETHEAPOBJINFO 0x23
7343#define DUK_DBG_CMD_GETOBJPROPDESC 0x24
7344#define DUK_DBG_CMD_GETOBJPROPDESCRANGE 0x25
7345
7346/* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
7347 * The remaining flags are specific to the debugger.
7348 */
7349#define DUK_DBG_PROPFLAG_INTERNAL (1 << 8)
7350
7351#if defined(DUK_USE_DEBUGGER_SUPPORT)
7352DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
7353
7354DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
7355DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
7356
7357DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
7358DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
7359
7360DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
7361DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
7362DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
7363DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
7364/* XXX: exposed duk_debug_read_pointer */
7365/* XXX: exposed duk_debug_read_buffer */
7366/* XXX: exposed duk_debug_read_hbuffer */
7367#if 0
7368DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
7369#endif
7370#if defined(DUK_USE_DEBUGGER_INSPECT)
7371DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
7372#endif
7373DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
7374
7375DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
7376DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
7377DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
7378DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
7379#if defined(DUK_USE_DEBUGGER_INSPECT)
7380DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
7381#endif
7382DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
7383DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
7384DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
7385DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
7386DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
7387DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
7388DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
7389DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
7390DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
7391#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
7392DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
7393#endif
7394DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
7395DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
7396#if 0 /* unused */
7397DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
7398#endif
7399DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
7400DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
7401DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
7402DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
7403
7404DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
7405DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
7406#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
7407DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
7408#endif
7409
7410DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
7411DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
7412
7413DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
7414DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
7415#endif
7416
7417#endif /* DUK_DEBUGGER_H_INCLUDED */
7418#line 1 "duk_debug.h"
7419/*
7420 * Debugging macros, DUK_DPRINT() and its variants in particular.
7421 *
7422 * DUK_DPRINT() allows formatted debug prints, and supports standard
7423 * and Duktape specific formatters. See duk_debug_vsnprintf.c for details.
7424 *
7425 * DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
7426 * for technical reasons. They are concretely used to hide 'x' from the
7427 * compiler when the corresponding log level is disabled. This allows
7428 * clean builds on non-C99 compilers, at the cost of more verbose code.
7429 * Examples:
7430 *
7431 * DUK_D(DUK_DPRINT("foo"));
7432 * DUK_DD(DUK_DDPRINT("foo"));
7433 * DUK_DDD(DUK_DDDPRINT("foo"));
7434 *
7435 * This approach is preferable to the old "double parentheses" hack because
7436 * double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
7437 * no longer be added transparently without going through globals, which
7438 * works poorly with threading.
7439 */
7440
7441#ifndef DUK_DEBUG_H_INCLUDED
7442#define DUK_DEBUG_H_INCLUDED
7443
7444#ifdef DUK_USE_DEBUG
7445
7446#if defined(DUK_USE_DPRINT)
7447#define DUK_D(x) x
7448#else
7449#define DUK_D(x) do { } while (0) /* omit */
7450#endif
7451
7452#if defined(DUK_USE_DDPRINT)
7453#define DUK_DD(x) x
7454#else
7455#define DUK_DD(x) do { } while (0) /* omit */
7456#endif
7457
7458#if defined(DUK_USE_DDDPRINT)
7459#define DUK_DDD(x) x
7460#else
7461#define DUK_DDD(x) do { } while (0) /* omit */
7462#endif
7463
7464/*
7465 * Exposed debug macros: debugging enabled
7466 */
7467
7468#define DUK_LEVEL_DEBUG 1
7469#define DUK_LEVEL_DDEBUG 2
7470#define DUK_LEVEL_DDDEBUG 3
7471
7472#ifdef DUK_USE_VARIADIC_MACROS
7473
7474/* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
7475 * possible compile time, but waste some space with shared function names.
7476 */
7477#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__);
7478
7479#define DUK_DPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
7480
7481#ifdef DUK_USE_DDPRINT
7482#define DUK_DDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
7483#else
7484#define DUK_DDPRINT(...)
7485#endif
7486
7487#ifdef DUK_USE_DDDPRINT
7488#define DUK_DDDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
7489#else
7490#define DUK_DDDPRINT(...)
7491#endif
7492
7493#else /* DUK_USE_VARIADIC_MACROS */
7494
7495#define DUK__DEBUG_STASH(lev) \
7496 (void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
7497 duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7498 (void) DUK_SNPRINTF(duk_debug_line_stash, DUK_DEBUG_STASH_SIZE, "%ld", (long) DUK_LINE_MACRO), \
7499 duk_debug_line_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7500 (void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
7501 duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7502 (void) (duk_debug_level_stash = (lev))
7503
7504/* Without variadic macros resort to comma expression trickery to handle debug
7505 * prints. This generates a lot of harmless warnings. These hacks are not
7506 * needed normally because DUK_D() and friends will hide the entire debug log
7507 * statement from the compiler.
7508 */
7509
7510#ifdef DUK_USE_DPRINT
7511#define DUK_DPRINT DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log /* args go here in parens */
7512#else
7513#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
7514#endif
7515
7516#ifdef DUK_USE_DDPRINT
7517#define DUK_DDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log /* args go here in parens */
7518#else
7519#define DUK_DDPRINT 0 && /* args */
7520#endif
7522#ifdef DUK_USE_DDDPRINT
7523#define DUK_DDDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log /* args go here in parens */
7524#else
7525#define DUK_DDDPRINT 0 && /* args */
7526#endif
7527
7528#endif /* DUK_USE_VARIADIC_MACROS */
7529
7530#else /* DUK_USE_DEBUG */
7531
7532/*
7533 * Exposed debug macros: debugging disabled
7536#define DUK_D(x) do { } while (0) /* omit */
7537#define DUK_DD(x) do { } while (0) /* omit */
7538#define DUK_DDD(x) do { } while (0) /* omit */
7539
7540#ifdef DUK_USE_VARIADIC_MACROS
7541
7542#define DUK_DPRINT(...)
7543#define DUK_DDPRINT(...)
7544#define DUK_DDDPRINT(...)
7545
7546#else /* DUK_USE_VARIADIC_MACROS */
7547
7548#define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
7549#define DUK_DDPRINT 0 && /* args */
7550#define DUK_DDDPRINT 0 && /* args */
7551
7552#endif /* DUK_USE_VARIADIC_MACROS */
7553
7554#endif /* DUK_USE_DEBUG */
7555
7556/*
7557 * Structs
7558 */
7559
7560#ifdef DUK_USE_DEBUG
7561struct duk_fixedbuffer {
7562 duk_uint8_t *buffer;
7563 duk_size_t length;
7564 duk_size_t offset;
7565 duk_bool_t truncated;
7566};
7567#endif
7568
7569/*
7570 * Prototypes
7571 */
7572
7573#ifdef DUK_USE_DEBUG
7574DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
7575#if 0 /*unused*/
7576DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
7577#endif
7578DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
7579
7580#ifdef DUK_USE_VARIADIC_MACROS
7581DUK_INTERNAL_DECL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
7582#else /* DUK_USE_VARIADIC_MACROS */
7583/* parameter passing, not thread safe */
7584#define DUK_DEBUG_STASH_SIZE 128
7585#if !defined(DUK_SINGLE_FILE)
7586DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
7587DUK_INTERNAL_DECL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
7588DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
7589DUK_INTERNAL_DECL duk_small_int_t duk_debug_level_stash;
7590#endif
7591DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
7592#endif /* DUK_USE_VARIADIC_MACROS */
7593
7594DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
7595DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
7596DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
7597DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
7598DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
7599DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
7600
7601#endif /* DUK_USE_DEBUG */
7602
7603#endif /* DUK_DEBUG_H_INCLUDED */
7604#line 1 "duk_error.h"
7606 * Error handling macros, assertion macro, error codes.
7607 *
7608 * There are three level of 'errors':
7609 *
7610 * 1. Ordinary errors, relative to a thread, cause a longjmp, catchable.
7611 * 2. Fatal errors, relative to a heap, cause fatal handler to be called.
7612 * 3. Panic errors, unrelated to a heap and cause a process exit.
7613 *
7614 * Panics are used by the default fatal error handler and by debug code
7615 * such as assertions. By providing a proper fatal error handler, user
7616 * code can avoid panics in non-debug builds.
7617 */
7618
7619#ifndef DUK_ERROR_H_INCLUDED
7620#define DUK_ERROR_H_INCLUDED
7621
7622/*
7623 * Error codes: defined in duktape.h
7624 *
7625 * Error codes are used as a shorthand to throw exceptions from inside
7626 * the implementation. The appropriate Ecmascript object is constructed
7627 * based on the code. Ecmascript code throws objects directly. The error
7628 * codes are defined in the public API header because they are also used
7629 * by calling code.
7630 */
7631
7632/*
7633 * Normal error
7634 *
7635 * Normal error is thrown with a longjmp() through the current setjmp()
7636 * catchpoint record in the duk_heap. The 'curr_thread' of the duk_heap
7637 * identifies the throwing thread.
7638 *
7639 * Error formatting is usually unnecessary. The error macros provide a
7640 * zero argument version (no formatting) and separate macros for small
7641 * argument counts. Variadic macros are not used to avoid portability
7642 * issues and avoid the need for stash-based workarounds when they're not
7643 * available. Vararg calls are avoided for non-formatted error calls
7644 * because vararg call sites are larger than normal, and there are a lot
7645 * of call sites with no formatting.
7646 *
7647 * Note that special formatting provided by debug macros is NOT available.
7648 *
7649 * The _RAW variants allow the caller to specify file and line. This makes
7650 * it easier to write checked calls which want to use the call site of the
7651 * checked function, not the error macro call inside the checked function.
7652 */
7653
7654#if defined(DUK_USE_VERBOSE_ERRORS)
7656/* Because there are quite many call sites, pack error code (require at most
7657 * 8-bit) into a single argument.
7658 */
7659#define DUK_ERROR(thr,err,msg) do { \
7660 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7661 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7662 duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
7663 } while (0)
7664#define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
7665 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7666 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7667 duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
7668 } while (0)
7669
7670#define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
7671 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7672 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7673 duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
7674 } while (0)
7675#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
7676 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7677 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7678 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
7679 } while (0)
7680
7681#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
7682 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7683 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7684 duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
7685 } while (0)
7686#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
7687 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7688 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7689 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
7690 } while (0)
7691
7692#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
7693 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7694 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7695 duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
7696 } while (0)
7697#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
7698 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7699 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7700 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
7701 } while (0)
7702
7703#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
7704 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7705 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7706 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)); \
7707 } while (0)
7708#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
7709 duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7710 DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7711 duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
7712 } while (0)
7713
7714#else /* DUK_USE_VERBOSE_ERRORS */
7715
7716#define DUK_ERROR(thr,err,msg) duk_err_handle_error((thr), (err))
7717#define DUK_ERROR_RAW(thr,file,line,err,msg) duk_err_handle_error((thr), (err))
7718
7719#define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
7720#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7721
7722#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
7723#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7724
7725#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
7726#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7727
7728#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
7729#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7730
7731#endif /* DUK_USE_VERBOSE_ERRORS */
7732
7733/*
7734 * Fatal error
7735 *
7736 * There are no fatal error macros at the moment. There are so few call
7737 * sites that the fatal error handler is called directly.
7738 */
7739
7740/*
7741 * Panic error
7742 *
7743 * Panic errors are not relative to either a heap or a thread, and cause
7744 * DUK_PANIC() macro to be invoked. Unless a user provides DUK_USE_PANIC_HANDLER,
7745 * DUK_PANIC() calls a helper which prints out the error and causes a process
7746 * exit.
7747 *
7748 * The user can override the macro to provide custom handling. A macro is
7749 * used to allow the user to have inline panic handling if desired (without
7750 * causing a potentially risky function call).
7751 *
7752 * Panics are only used in debug code such as assertions, and by the default
7753 * fatal error handler.
7754 */
7755
7756#if defined(DUK_USE_PANIC_HANDLER)
7757/* already defined, good */
7758#define DUK_PANIC(code,msg) DUK_USE_PANIC_HANDLER((code),(msg))
7759#else
7760#define DUK_PANIC(code,msg) duk_default_panic_handler((code),(msg))
7761#endif /* DUK_USE_PANIC_HANDLER */
7762
7763/*
7764 * Assert macro: failure causes panic.
7765 */
7766
7767#if defined(DUK_USE_ASSERTIONS)
7768
7769/* the message should be a compile time constant without formatting (less risk);
7770 * we don't care about assertion text size because they're not used in production
7771 * builds.
7772 */
7773#define DUK_ASSERT(x) do { \
7774 if (!(x)) { \
7775 DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
7776 "assertion failed: " #x \
7777 " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
7778 } \
7779 } while (0)
7780
7781/* Assertion compatible inside a comma expression, evaluates to void.
7782 * Currently not compatible with DUK_USE_PANIC_HANDLER() which may have
7783 * a statement block.
7785#if defined(DUK_USE_PANIC_HANDLER)
7786/* XXX: resolve macro definition issue or call through a helper function? */
7787#define DUK_ASSERT_EXPR(x) ((void) 0)
7788#else
7789#define DUK_ASSERT_EXPR(x) \
7790 ((void) ((x) ? 0 : (DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
7791 "assertion failed: " #x \
7792 " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
7793#endif
7794
7795#else /* DUK_USE_ASSERTIONS */
7796
7797#define DUK_ASSERT(x) do { /* assertion omitted */ } while (0)
7798
7799#define DUK_ASSERT_EXPR(x) ((void) 0)
7800
7801#endif /* DUK_USE_ASSERTIONS */
7802
7803/* this variant is used when an assert would generate a compile warning by
7804 * being always true (e.g. >= 0 comparison for an unsigned value
7805 */
7806#define DUK_ASSERT_DISABLE(x) do { /* assertion disabled */ } while (0)
7809 * Assertion helpers
7810 */
7812#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
7813#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) do { \
7814 DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
7815 } while (0)
7816#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) do { \
7817 if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
7818 DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
7819 } \
7820 } while (0)
7821#else
7822#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) /* no refcount check */
7823#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) /* no refcount check */
7824#endif
7825
7826#define DUK_ASSERT_TOP(ctx,n) DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
7827
7828#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
7829#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) do { \
7830 duk_double_union duk__assert_tmp_du; \
7831 duk__assert_tmp_du.d = (dval); \
7832 DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
7833 } while (0)
7834#else
7835#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) /* nop */
7836#endif
7837
7839 * Helper for valstack space
7840 *
7841 * Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
7842 * required for its own use, and any child calls which are not (a) Duktape API calls
7843 * or (b) Duktape calls which involve extending the valstack (e.g. getter call).
7844 */
7845
7846#define DUK_VALSTACK_ASSERT_EXTRA 5 /* this is added to checks to allow for Duktape
7847 * API calls in addition to function's own use
7848 */
7849#if defined(DUK_USE_ASSERTIONS)
7850#define DUK_ASSERT_VALSTACK_SPACE(thr,n) do { \
7851 DUK_ASSERT((thr) != NULL); \
7852 DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
7853 } while (0)
7854#else
7855#define DUK_ASSERT_VALSTACK_SPACE(thr,n) /* no valstack space check */
7856#endif
7857
7858/*
7859 * Error throwing helpers
7860 *
7861 * The goal is to provide verbose and configurable error messages. Call
7862 * sites should be clean in source code and compile to a small footprint.
7863 * Small footprint is also useful for performance because small cold paths
7864 * reduce code cache pressure. Adding macros here only makes sense if there
7865 * are enough call sites to get concrete benefits.
7867
7868#if defined(DUK_USE_VERBOSE_ERRORS)
7869/* Verbose errors with key/value summaries (non-paranoid) or without key/value
7870 * summaries (paranoid, for some security sensitive environments), the paranoid
7871 * vs. non-paranoid distinction affects only a few specific errors.
7873#if defined(DUK_USE_PARANOID_ERRORS)
7874#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7875 duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index), (expectname)); \
7876 } while (0)
7877#else /* DUK_USE_PARANOID_ERRORS */
7878#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7879 duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index), (expectname)); \
7880 } while (0)
7881#endif /* DUK_USE_PARANOID_ERRORS */
7882
7883#define DUK_ERROR_UNIMPLEMENTED(thr,msg) do { \
7884 DUK_ERROR((thr), DUK_ERR_UNIMPLEMENTED_ERROR, (msg)); \
7885 } while (0)
7886#define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr) do { \
7887 duk_err_unimplemented_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7888 } while (0)
7889#define DUK_ERROR_UNSUPPORTED(thr,msg) do { \
7890 DUK_ERROR((thr), DUK_ERR_UNSUPPORTED_ERROR, (msg)); \
7891 } while (0)
7892#if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
7893#define DUK_ERROR_UNSUPPORTED_DEFMSG(thr) do { \
7894 duk_err_unsupported_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7895 } while (0)
7896#endif
7897#define DUK_ERROR_INTERNAL(thr,msg) do { \
7898 duk_err_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7899 } while (0)
7900#define DUK_ERROR_INTERNAL_DEFMSG(thr) do { \
7901 duk_err_internal_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7902 } while (0)
7903#define DUK_ERROR_ALLOC(thr,msg) do { \
7904 duk_err_alloc((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7905 } while (0)
7906#define DUK_ERROR_ALLOC_DEFMSG(thr) do { \
7907 DUK_ERROR_ALLOC((thr), DUK_STR_ALLOC_FAILED); \
7908 } while (0)
7909/* DUK_ERR_ASSERTION_ERROR: no macros needed */
7910#define DUK_ERROR_API_INDEX(thr,index) do { \
7911 duk_err_api_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index)); \
7912 } while (0)
7913#define DUK_ERROR_API(thr,msg) do { \
7914 duk_err_api((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7915 } while (0)
7916/* DUK_ERR_UNCAUGHT_ERROR: no macros needed */
7917/* DUK_ERR_ERROR: no macros needed */
7918/* DUK_ERR_EVAL: no macros needed */
7919#define DUK_ERROR_RANGE(thr,msg) do { \
7920 duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7921 } while (0)
7922/* DUK_ERR_REFERENCE_ERROR: no macros needed */
7923#define DUK_ERROR_SYNTAX(thr,msg) do { \
7924 DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
7925 } while (0)
7926#define DUK_ERROR_TYPE(thr,msg) do { \
7927 DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
7928 } while (0)
7929/* DUK_ERR_URI_ERROR: no macros needed */
7930#else /* DUK_USE_VERBOSE_ERRORS */
7931/* Non-verbose errors for low memory targets: no file, line, or message. */
7932
7933#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7934 duk_err_type((thr)); \
7935 } while (0)
7936
7937#define DUK_ERROR_UNIMPLEMENTED(thr,msg) do { \
7938 duk_err_unimplemented((thr)); \
7939 } while (0)
7940#define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr) do { \
7941 duk_err_unimplemented((thr)); \
7942 } while (0)
7943#define DUK_ERROR_UNSUPPORTED(thr,msg) do { \
7944 duk_err_unsupported((thr)); \
7945 } while (0)
7946#define DUK_ERROR_UNSUPPORTED_DEFMSG(thr) do { \
7947 duk_err_unsupported((thr)); \
7948 } while (0)
7949#define DUK_ERROR_INTERNAL(thr,msg) do { \
7950 duk_err_internal((thr)); \
7951 } while (0)
7952#define DUK_ERROR_INTERNAL_DEFMSG(thr) do { \
7953 duk_err_internal((thr)); \
7954 } while (0)
7955#define DUK_ERROR_ALLOC(thr,msg) do { \
7956 duk_err_alloc((thr)); \
7957 } while (0)
7958#define DUK_ERROR_ALLOC_DEFMSG(thr) do { \
7959 duk_err_alloc((thr)); \
7960 } while (0)
7961#define DUK_ERROR_API_INDEX(thr,index) do { \
7962 duk_err_api((thr)); \
7963 } while (0)
7964#define DUK_ERROR_API(thr,msg) do { \
7965 duk_err_api((thr)); \
7966 } while (0)
7967#define DUK_ERROR_RANGE(thr,msg) do { \
7968 duk_err_range((thr)); \
7969 } while (0)
7970#define DUK_ERROR_SYNTAX(thr,msg) do { \
7971 duk_err_syntax((thr)); \
7972 } while (0)
7973#define DUK_ERROR_TYPE(thr,msg) do { \
7974 duk_err_type((thr)); \
7975 } while (0)
7976#endif /* DUK_USE_VERBOSE_ERRORS */
7977
7979 * Prototypes
7980 */
7981
7982#if defined(DUK_USE_VERBOSE_ERRORS)
7983DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));
7984DUK_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, ...));
7985#else /* DUK_USE_VERBOSE_ERRORS */
7987#endif /* DUK_USE_VERBOSE_ERRORS */
7988
7989#if defined(DUK_USE_VERBOSE_ERRORS)
7990DUK_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));
7991#else
7993#endif
7997#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
7998DUK_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);
7999#endif
8000#if defined(DUK_USE_AUGMENT_ERROR_THROW)
8002#endif
8003
8004#if defined(DUK_USE_VERBOSE_ERRORS)
8005#if defined(DUK_USE_PARANOID_ERRORS)
8006DUK_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));
8007#else
8008DUK_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));
8009#endif
8010DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index));
8011DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
8012DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
8013DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8014#if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
8015DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unsupported_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8016#endif
8017DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8018DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
8019DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
8020#else /* DUK_VERBOSE_ERRORS */
8022DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
8023DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
8025DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unimplemented(duk_hthread *thr));
8026DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unsupported(duk_hthread *thr));
8029#endif /* DUK_VERBOSE_ERRORS */
8030
8032
8034
8035#if !defined(DUK_USE_PANIC_HANDLER)
8037#endif
8038
8043#endif /* DUK_ERROR_H_INCLUDED */
8044#line 1 "duk_unicode.h"
8045/*
8046 * Unicode helpers
8047 */
8048
8049#ifndef DUK_UNICODE_H_INCLUDED
8050#define DUK_UNICODE_H_INCLUDED
8053 * UTF-8 / XUTF-8 / CESU-8 constants
8054 */
8055
8056#define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */
8057#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
8058#define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */
8059#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
8060
8061/*
8062 * Useful Unicode codepoints
8063 *
8064 * Integer constants must be signed to avoid unexpected coercions
8065 * in comparisons.
8068#define DUK_UNICODE_CP_ZWNJ 0x200cL /* zero-width non-joiner */
8069#define DUK_UNICODE_CP_ZWJ 0x200dL /* zero-width joiner */
8070#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER 0xfffdL /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
8073 * ASCII character constants
8075 * C character literals like 'x' have a platform specific value and do
8076 * not match ASCII (UTF-8) values on e.g. EBCDIC platforms. So, use
8077 * these (admittedly awkward) constants instead. These constants must
8078 * also have signed values to avoid unexpected coercions in comparisons.
8080 * http://en.wikipedia.org/wiki/ASCII
8083#define DUK_ASC_NUL 0x00
8084#define DUK_ASC_SOH 0x01
8085#define DUK_ASC_STX 0x02
8086#define DUK_ASC_ETX 0x03
8087#define DUK_ASC_EOT 0x04
8088#define DUK_ASC_ENQ 0x05
8089#define DUK_ASC_ACK 0x06
8090#define DUK_ASC_BEL 0x07
8091#define DUK_ASC_BS 0x08
8092#define DUK_ASC_HT 0x09
8093#define DUK_ASC_LF 0x0a
8094#define DUK_ASC_VT 0x0b
8095#define DUK_ASC_FF 0x0c
8096#define DUK_ASC_CR 0x0d
8097#define DUK_ASC_SO 0x0e
8098#define DUK_ASC_SI 0x0f
8099#define DUK_ASC_DLE 0x10
8100#define DUK_ASC_DC1 0x11
8101#define DUK_ASC_DC2 0x12
8102#define DUK_ASC_DC3 0x13
8103#define DUK_ASC_DC4 0x14
8104#define DUK_ASC_NAK 0x15
8105#define DUK_ASC_SYN 0x16
8106#define DUK_ASC_ETB 0x17
8107#define DUK_ASC_CAN 0x18
8108#define DUK_ASC_EM 0x19
8109#define DUK_ASC_SUB 0x1a
8110#define DUK_ASC_ESC 0x1b
8111#define DUK_ASC_FS 0x1c
8112#define DUK_ASC_GS 0x1d
8113#define DUK_ASC_RS 0x1e
8114#define DUK_ASC_US 0x1f
8115#define DUK_ASC_SPACE 0x20
8116#define DUK_ASC_EXCLAMATION 0x21
8117#define DUK_ASC_DOUBLEQUOTE 0x22
8118#define DUK_ASC_HASH 0x23
8119#define DUK_ASC_DOLLAR 0x24
8120#define DUK_ASC_PERCENT 0x25
8121#define DUK_ASC_AMP 0x26
8122#define DUK_ASC_SINGLEQUOTE 0x27
8123#define DUK_ASC_LPAREN 0x28
8124#define DUK_ASC_RPAREN 0x29
8125#define DUK_ASC_STAR 0x2a
8126#define DUK_ASC_PLUS 0x2b
8127#define DUK_ASC_COMMA 0x2c
8128#define DUK_ASC_MINUS 0x2d
8129#define DUK_ASC_PERIOD 0x2e
8130#define DUK_ASC_SLASH 0x2f
8131#define DUK_ASC_0 0x30
8132#define DUK_ASC_1 0x31
8133#define DUK_ASC_2 0x32
8134#define DUK_ASC_3 0x33
8135#define DUK_ASC_4 0x34
8136#define DUK_ASC_5 0x35
8137#define DUK_ASC_6 0x36
8138#define DUK_ASC_7 0x37
8139#define DUK_ASC_8 0x38
8140#define DUK_ASC_9 0x39
8141#define DUK_ASC_COLON 0x3a
8142#define DUK_ASC_SEMICOLON 0x3b
8143#define DUK_ASC_LANGLE 0x3c
8144#define DUK_ASC_EQUALS 0x3d
8145#define DUK_ASC_RANGLE 0x3e
8146#define DUK_ASC_QUESTION 0x3f
8147#define DUK_ASC_ATSIGN 0x40
8148#define DUK_ASC_UC_A 0x41
8149#define DUK_ASC_UC_B 0x42
8150#define DUK_ASC_UC_C 0x43
8151#define DUK_ASC_UC_D 0x44
8152#define DUK_ASC_UC_E 0x45
8153#define DUK_ASC_UC_F 0x46
8154#define DUK_ASC_UC_G 0x47
8155#define DUK_ASC_UC_H 0x48
8156#define DUK_ASC_UC_I 0x49
8157#define DUK_ASC_UC_J 0x4a
8158#define DUK_ASC_UC_K 0x4b
8159#define DUK_ASC_UC_L 0x4c
8160#define DUK_ASC_UC_M 0x4d
8161#define DUK_ASC_UC_N 0x4e
8162#define DUK_ASC_UC_O 0x4f
8163#define DUK_ASC_UC_P 0x50
8164#define DUK_ASC_UC_Q 0x51
8165#define DUK_ASC_UC_R 0x52
8166#define DUK_ASC_UC_S 0x53
8167#define DUK_ASC_UC_T 0x54
8168#define DUK_ASC_UC_U 0x55
8169#define DUK_ASC_UC_V 0x56
8170#define DUK_ASC_UC_W 0x57
8171#define DUK_ASC_UC_X 0x58
8172#define DUK_ASC_UC_Y 0x59
8173#define DUK_ASC_UC_Z 0x5a
8174#define DUK_ASC_LBRACKET 0x5b
8175#define DUK_ASC_BACKSLASH 0x5c
8176#define DUK_ASC_RBRACKET 0x5d
8177#define DUK_ASC_CARET 0x5e
8178#define DUK_ASC_UNDERSCORE 0x5f
8179#define DUK_ASC_GRAVE 0x60
8180#define DUK_ASC_LC_A 0x61
8181#define DUK_ASC_LC_B 0x62
8182#define DUK_ASC_LC_C 0x63
8183#define DUK_ASC_LC_D 0x64
8184#define DUK_ASC_LC_E 0x65
8185#define DUK_ASC_LC_F 0x66
8186#define DUK_ASC_LC_G 0x67
8187#define DUK_ASC_LC_H 0x68
8188#define DUK_ASC_LC_I 0x69
8189#define DUK_ASC_LC_J 0x6a
8190#define DUK_ASC_LC_K 0x6b
8191#define DUK_ASC_LC_L 0x6c
8192#define DUK_ASC_LC_M 0x6d
8193#define DUK_ASC_LC_N 0x6e
8194#define DUK_ASC_LC_O 0x6f
8195#define DUK_ASC_LC_P 0x70
8196#define DUK_ASC_LC_Q 0x71
8197#define DUK_ASC_LC_R 0x72
8198#define DUK_ASC_LC_S 0x73
8199#define DUK_ASC_LC_T 0x74
8200#define DUK_ASC_LC_U 0x75
8201#define DUK_ASC_LC_V 0x76
8202#define DUK_ASC_LC_W 0x77
8203#define DUK_ASC_LC_X 0x78
8204#define DUK_ASC_LC_Y 0x79
8205#define DUK_ASC_LC_Z 0x7a
8206#define DUK_ASC_LCURLY 0x7b
8207#define DUK_ASC_PIPE 0x7c
8208#define DUK_ASC_RCURLY 0x7d
8209#define DUK_ASC_TILDE 0x7e
8210#define DUK_ASC_DEL 0x7f
8211
8212/*
8213 * Unicode tables
8214 */
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_ids_noa[791];
8222#else
8223/*
8224 * Automatically generated by extract_chars.py, do not edit!
8225 */
8226
8227extern const duk_uint8_t duk_unicode_ids_noabmp[611];
8228#endif
8229
8230#ifdef DUK_USE_SOURCE_NONBMP
8231/*
8232 * Automatically generated by extract_chars.py, do not edit!
8233 */
8234
8235extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
8236#else
8237/*
8238 * Automatically generated by extract_chars.py, do not edit!
8239 */
8240
8241extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
8242#endif
8243
8244#ifdef DUK_USE_SOURCE_NONBMP
8245/*
8246 * Automatically generated by extract_chars.py, do not edit!
8247 */
8248
8249extern const duk_uint8_t duk_unicode_idp_m_ids_noa[397];
8250#else
8251/*
8252 * Automatically generated by extract_chars.py, do not edit!
8253 */
8254
8255extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348];
8256#endif
8257
8258/*
8259 * Automatically generated by extract_caseconv.py, do not edit!
8260 */
8261
8262extern const duk_uint8_t duk_unicode_caseconv_uc[1288];
8263extern const duk_uint8_t duk_unicode_caseconv_lc[616];
8264
8265#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
8266/*
8267 * Automatically generated by extract_caseconv.py, do not edit!
8268 */
8269
8270extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
8271#endif
8272
8273/*
8274 * Extern
8275 */
8276
8277/* duk_unicode_support.c */
8278#if !defined(DUK_SINGLE_FILE)
8279DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
8281DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
8286DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
8287#endif /* !DUK_SINGLE_FILE */
8288
8289/*
8290 * Prototypes
8291 */
8292
8294#if defined(DUK_USE_ASSERTIONS)
8295DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
8296#endif
8299DUK_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);
8300DUK_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);
8311#endif /* DUK_UNICODE_H_INCLUDED */
8312#line 1 "duk_json.h"
8314 * Defines for JSON, especially duk_bi_json.c.
8315 */
8317#ifndef DUK_JSON_H_INCLUDED
8318#define DUK_JSON_H_INCLUDED
8319
8320/* Encoding/decoding flags */
8321#define DUK_JSON_FLAG_ASCII_ONLY (1 << 0) /* escape any non-ASCII characters */
8322#define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1 << 1) /* avoid key quotes when key is an ASCII Identifier */
8323#define DUK_JSON_FLAG_EXT_CUSTOM (1 << 2) /* extended types: custom encoding */
8324#define DUK_JSON_FLAG_EXT_COMPATIBLE (1 << 3) /* extended types: compatible encoding */
8325
8326/* How much stack to require on entry to object/array encode */
8327#define DUK_JSON_ENC_REQSTACK 32
8328
8329/* How much stack to require on entry to object/array decode */
8330#define DUK_JSON_DEC_REQSTACK 32
8331
8332/* How large a loop detection stack to use */
8333#define DUK_JSON_ENC_LOOPARRAY 64
8334
8335/* Encoding state. Heap object references are all borrowed. */
8336typedef struct {
8337 duk_hthread *thr;
8338 duk_bufwriter_ctx bw; /* output bufwriter */
8339 duk_hobject *h_replacer; /* replacer function */
8340 duk_hstring *h_gap; /* gap (if empty string, NULL) */
8341 duk_idx_t idx_proplist; /* explicit PropertyList */
8342 duk_idx_t idx_loop; /* valstack index of loop detection object */
8343 duk_small_uint_t flags;
8344 duk_small_uint_t flag_ascii_only;
8345 duk_small_uint_t flag_avoid_key_quotes;
8346#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8347 duk_small_uint_t flag_ext_custom;
8348 duk_small_uint_t flag_ext_compatible;
8349 duk_small_uint_t flag_ext_custom_or_compatible;
8350#endif
8351 duk_int_t recursion_depth;
8352 duk_int_t recursion_limit;
8353 duk_uint_t mask_for_undefined; /* type bit mask: types which certainly produce 'undefined' */
8354#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8355 duk_small_uint_t stridx_custom_undefined;
8356 duk_small_uint_t stridx_custom_nan;
8357 duk_small_uint_t stridx_custom_neginf;
8358 duk_small_uint_t stridx_custom_posinf;
8359 duk_small_uint_t stridx_custom_function;
8360#endif
8361 duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY]; /* indexed by recursion_depth */
8363
8364typedef struct {
8365 duk_hthread *thr;
8366 const duk_uint8_t *p;
8367 const duk_uint8_t *p_start;
8368 const duk_uint8_t *p_end;
8369 duk_idx_t idx_reviver;
8371#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8372 duk_small_uint_t flag_ext_custom;
8373 duk_small_uint_t flag_ext_compatible;
8374 duk_small_uint_t flag_ext_custom_or_compatible;
8375#endif
8376 duk_int_t recursion_depth;
8377 duk_int_t recursion_limit;
8379
8380#endif /* DUK_JSON_H_INCLUDED */
8381#line 1 "duk_js.h"
8382/*
8383 * Ecmascript execution, support primitives.
8386#ifndef DUK_JS_H_INCLUDED
8387#define DUK_JS_H_INCLUDED
8388
8389/* Flags for call handling. */
8390#define DUK_CALL_FLAG_IGNORE_RECLIMIT (1 << 0) /* duk_handle_call_xxx: call ignores C recursion limit (for errhandler calls) */
8391#define DUK_CALL_FLAG_CONSTRUCTOR_CALL (1 << 1) /* duk_handle_call_xxx: constructor call (i.e. called as 'new Foo()') */
8392#define DUK_CALL_FLAG_IS_RESUME (1 << 2) /* duk_handle_ecma_call_setup: setup for a resume() */
8393#define DUK_CALL_FLAG_IS_TAILCALL (1 << 3) /* duk_handle_ecma_call_setup: setup for a tail call */
8394#define DUK_CALL_FLAG_DIRECT_EVAL (1 << 4) /* call is a direct eval call */
8395
8396/* Flags for duk_js_equals_helper(). */
8397#define DUK_EQUALS_FLAG_SAMEVALUE (1 << 0) /* use SameValue instead of non-strict equality */
8398#define DUK_EQUALS_FLAG_STRICT (1 << 1) /* use strict equality instead of non-strict equality */
8399
8400/* Flags for duk_js_compare_helper(). */
8401#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST (1 << 0) /* eval left argument first */
8402#define DUK_COMPARE_FLAG_NEGATE (1 << 1) /* negate result */
8403
8404/* conversions, coercions, comparison, etc */
8415DUK_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);
8418DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
8419#endif
8425#define duk_js_equals(thr,tv_x,tv_y) \
8426 duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
8427#define duk_js_strict_equals(tv_x,tv_y) \
8428 duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
8429#define duk_js_samevalue(tv_x,tv_y) \
8430 duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
8431
8432/* E5 Sections 11.8.1, 11.8.5; x < y */
8433#define duk_js_lessthan(thr,tv_x,tv_y) \
8434 duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
8435
8436/* E5 Sections 11.8.2, 11.8.5; x > y --> y < x */
8437#define duk_js_greaterthan(thr,tv_x,tv_y) \
8438 duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
8439
8440/* E5 Sections 11.8.3, 11.8.5; x <= y --> not (x > y) --> not (y < x) */
8441#define duk_js_lessthanorequal(thr,tv_x,tv_y) \
8442 duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
8443
8444/* E5 Sections 11.8.4, 11.8.5; x >= y --> not (x < y) */
8445#define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
8446 duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
8447
8448/* identifiers and environment handling */
8449#if 0 /*unused*/
8450DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
8451#endif
8456#if 0 /*unused*/
8457DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
8458#endif
8467 duk_hobject *outer_var_env,
8468 duk_hobject *outer_lex_env,
8469 duk_bool_t add_auto_proto);
8470
8471/* call handling */
8477/* bytecode execution */
8480#endif /* DUK_JS_H_INCLUDED */
8481#line 1 "duk_numconv.h"
8482#ifndef DUK_NUMCONV_H_INCLUDED
8483#define DUK_NUMCONV_H_INCLUDED
8484
8485/*
8486 * Number-to-string conversion. The semantics of these is very tightly
8487 * bound with the Ecmascript semantics required for call sites.
8488 */
8489
8490/* Output a specified number of digits instead of using the shortest
8491 * form. Used for toPrecision() and toFixed().
8493#define DUK_N2S_FLAG_FIXED_FORMAT (1 << 0)
8494
8495/* Force exponential format. Used for toExponential(). */
8496#define DUK_N2S_FLAG_FORCE_EXP (1 << 1)
8497
8498/* If number would need zero padding (for whole number part), use
8499 * exponential format instead. E.g. if input number is 12300, 3
8500 * digits are generated ("123"), output "1.23e+4" instead of "12300".
8501 * Used for toPrecision().
8503#define DUK_N2S_FLAG_NO_ZERO_PAD (1 << 2)
8504
8505/* Digit count indicates number of fractions (i.e. an absolute
8506 * digit index instead of a relative one). Used together with
8507 * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
8509#define DUK_N2S_FLAG_FRACTION_DIGITS (1 << 3)
8510
8512 * String-to-number conversion
8513 */
8515/* Maximum exponent value when parsing numbers. This is not strictly
8516 * compliant as there should be no upper limit, but as we parse the
8517 * exponent without a bigint, impose some limit.
8518 */
8519#define DUK_S2N_MAX_EXPONENT 1000000000
8521/* Trim white space (= allow leading and trailing whitespace) */
8522#define DUK_S2N_FLAG_TRIM_WHITE (1 << 0)
8524/* Allow exponent */
8525#define DUK_S2N_FLAG_ALLOW_EXP (1 << 1)
8527/* Allow trailing garbage (e.g. treat "123foo" as "123) */
8528#define DUK_S2N_FLAG_ALLOW_GARBAGE (1 << 2)
8530/* Allow leading plus sign */
8531#define DUK_S2N_FLAG_ALLOW_PLUS (1 << 3)
8533/* Allow leading minus sign */
8534#define DUK_S2N_FLAG_ALLOW_MINUS (1 << 4)
8536/* Allow 'Infinity' */
8537#define DUK_S2N_FLAG_ALLOW_INF (1 << 5)
8538
8539/* Allow fraction part */
8540#define DUK_S2N_FLAG_ALLOW_FRAC (1 << 6)
8541
8542/* Allow naked fraction (e.g. ".123") */
8543#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC (1 << 7)
8544
8545/* Allow empty fraction (e.g. "123.") */
8546#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC (1 << 8)
8547
8548/* Allow empty string to be interpreted as 0 */
8549#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO (1 << 9)
8550
8551/* Allow leading zeroes (e.g. "0123" -> "123") */
8552#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO (1 << 10)
8553
8554/* Allow automatic detection of hex base ("0x" or "0X" prefix),
8555 * overrides radix argument and forces integer mode.
8556 */
8557#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT (1 << 11)
8558
8559/* Allow automatic detection of octal base, overrides radix
8560 * argument and forces integer mode.
8561 */
8562#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT (1 << 12)
8563
8564/*
8565 * Prototypes
8566 */
8567
8571#endif /* DUK_NUMCONV_H_INCLUDED */
8572#line 1 "duk_bi_protos.h"
8573/*
8574 * Prototypes for built-in functions not automatically covered by the
8575 * header declarations emitted by genbuiltins.py.
8577
8578#ifndef DUK_BUILTIN_PROTOS_H_INCLUDED
8579#define DUK_BUILTIN_PROTOS_H_INCLUDED
8580
8581/* Buffer size needed for duk_bi_date_format_timeval().
8582 * Accurate value is 32 + 1 for NUL termination:
8583 * >>> len('+123456-01-23T12:34:56.123+12:34')
8584 * 32
8585 * Include additional space to be safe.
8586 */
8587#define DUK_BI_DATE_ISO8601_BUFSIZE 48
8588
8589/* Maximum length of CommonJS module identifier to resolve. Length includes
8590 * both current module ID, requested (possibly relative) module ID, and a
8591 * slash in between.
8592 */
8593#define DUK_BI_COMMONJS_MODULE_ID_LIMIT 256
8594
8595/* Helpers exposed for internal use */
8598DUK_INTERNAL_DECL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf);
8603/* Built-in providers */
8604#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
8605DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx);
8606#endif
8607#if defined(DUK_USE_DATE_NOW_TIME)
8609#endif
8610#if defined(DUK_USE_DATE_NOW_WINDOWS)
8611DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
8612#endif
8613#if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
8615#endif
8616#if defined(DUK_USE_DATE_TZO_WINDOWS)
8617DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
8618#endif
8619#if defined(DUK_USE_DATE_PRS_STRPTIME)
8620DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str);
8621#endif
8622#if defined(DUK_USE_DATE_PRS_GETDATE)
8623DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str);
8624#endif
8625#if defined(DUK_USE_DATE_FMT_STRFTIME)
8626DUK_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);
8627#endif
8628
8631 duk_idx_t idx_value,
8632 duk_idx_t idx_reviver,
8633 duk_small_uint_t flags);
8636 duk_idx_t idx_value,
8637 duk_idx_t idx_replacer,
8638 duk_idx_t idx_space,
8639 duk_small_uint_t flags);
8640
8641#endif /* DUK_BUILTIN_PROTOS_H_INCLUDED */
8642#line 1 "duk_selftest.h"
8643/*
8644 * Selftest code
8645 */
8646
8647#ifndef DUK_SELFTEST_H_INCLUDED
8648#define DUK_SELFTEST_H_INCLUDED
8649
8650#if defined(DUK_USE_SELF_TESTS)
8651DUK_INTERNAL_DECL void duk_selftest_run_tests(void);
8652#endif
8653
8654#endif /* DUK_SELFTEST_H_INCLUDED */
8655#line 78 "duk_internal.h"
8656
8657#endif /* DUK_INTERNAL_H_INCLUDED */
8658#line 1 "duk_replacements.c"
8659/*
8660 * Replacements for missing platform functions.
8662 * Unlike the originals, fpclassify() and signbit() replacements don't
8663 * work on any floating point types, only doubles. The C typing here
8664 * mimics the standard prototypes.
8665 */
8666
8667/* include removed: duk_internal.h */
8668
8669#if defined(DUK_USE_COMPUTED_NAN)
8670DUK_INTERNAL double duk_computed_nan;
8671#endif
8672
8673#if defined(DUK_USE_COMPUTED_INFINITY)
8674DUK_INTERNAL double duk_computed_infinity;
8675#endif
8676
8677#if defined(DUK_USE_REPL_FPCLASSIFY)
8678DUK_INTERNAL int duk_repl_fpclassify(double x) {
8680 duk_uint_fast16_t expt;
8681 duk_small_int_t mzero;
8682
8683 u.d = x;
8684 expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
8685 if (expt > 0x0000UL && expt < 0x7ff0UL) {
8686 /* expt values [0x001,0x7fe] = normal */
8687 return DUK_FP_NORMAL;
8688 }
8689
8690 mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
8691 if (expt == 0x0000UL) {
8692 /* expt 0x000 is zero/subnormal */
8693 if (mzero) {
8694 return DUK_FP_ZERO;
8695 } else {
8696 return DUK_FP_SUBNORMAL;
8697 }
8698 } else {
8699 /* expt 0xfff is infinite/nan */
8700 if (mzero) {
8702 } else {
8703 return DUK_FP_NAN;
8704 }
8705 }
8706}
8707#endif
8708
8709#if defined(DUK_USE_REPL_SIGNBIT)
8710DUK_INTERNAL int duk_repl_signbit(double x) {
8712 u.d = x;
8713 return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
8714}
8715#endif
8716
8717#if defined(DUK_USE_REPL_ISFINITE)
8718DUK_INTERNAL int duk_repl_isfinite(double x) {
8719 int c = DUK_FPCLASSIFY(x);
8720 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
8721 return 0;
8722 } else {
8723 return 1;
8724 }
8725}
8726#endif
8727
8728#if defined(DUK_USE_REPL_ISNAN)
8729DUK_INTERNAL int duk_repl_isnan(double x) {
8730 int c = DUK_FPCLASSIFY(x);
8731 return (c == DUK_FP_NAN);
8732}
8733#endif
8734
8735#if defined(DUK_USE_REPL_ISINF)
8737 int c = DUK_FPCLASSIFY(x);
8738 return (c == DUK_FP_INFINITE);
8740#endif
8741#line 1 "duk_strings.c"
8743 * Shared error message strings
8744 *
8745 * To minimize code footprint, try to share error messages inside Duktape
8746 * code. Modern compilers will do this automatically anyway, this is mostly
8747 * for older compilers.
8750/* include removed: duk_internal.h */
8752/* Mostly API and built-in method related */
8753DUK_INTERNAL const char *duk_str_internal_error = "internal error";
8754DUK_INTERNAL const char *duk_str_invalid_count = "invalid count";
8755DUK_INTERNAL const char *duk_str_invalid_call_args = "invalid call args";
8756DUK_INTERNAL const char *duk_str_not_constructable = "not constructable";
8757DUK_INTERNAL const char *duk_str_not_callable = "not callable";
8758DUK_INTERNAL const char *duk_str_not_extensible = "not extensible";
8759DUK_INTERNAL const char *duk_str_not_writable = "not writable";
8760DUK_INTERNAL const char *duk_str_not_configurable = "not configurable";
8762DUK_INTERNAL const char *duk_str_invalid_context = "invalid context";
8763DUK_INTERNAL const char *duk_str_push_beyond_alloc_stack = "attempt to push beyond currently allocated stack";
8764DUK_INTERNAL const char *duk_str_not_buffer = "not buffer"; /* still in use with verbose messages */
8765DUK_INTERNAL const char *duk_str_unexpected_type = "unexpected type";
8766DUK_INTERNAL const char *duk_str_defaultvalue_coerce_failed = "[[DefaultValue]] coerce failed";
8767DUK_INTERNAL const char *duk_str_number_outside_range = "number outside range";
8768DUK_INTERNAL const char *duk_str_not_object_coercible = "not object coercible";
8769DUK_INTERNAL const char *duk_str_string_too_long = "string too long";
8770DUK_INTERNAL const char *duk_str_buffer_too_long = "buffer too long";
8771DUK_INTERNAL const char *duk_str_sprintf_too_long = "sprintf message too long";
8772DUK_INTERNAL const char *duk_str_alloc_failed = "alloc failed";
8773DUK_INTERNAL const char *duk_str_pop_too_many = "attempt to pop too many entries";
8774DUK_INTERNAL const char *duk_str_wrong_buffer_type = "wrong buffer type";
8775DUK_INTERNAL const char *duk_str_encode_failed = "encode failed";
8776DUK_INTERNAL const char *duk_str_decode_failed = "decode failed";
8777DUK_INTERNAL const char *duk_str_no_sourcecode = "no sourcecode";
8778DUK_INTERNAL const char *duk_str_concat_result_too_long = "concat result too long";
8779DUK_INTERNAL const char *duk_str_unimplemented = "unimplemented";
8780DUK_INTERNAL const char *duk_str_unsupported = "unsupported";
8781DUK_INTERNAL const char *duk_str_array_length_over_2g = "array length over 2G";
8783/* JSON */
8785DUK_INTERNAL const char *duk_str_fmt_invalid_json = "invalid json (at offset %ld)";
8786DUK_INTERNAL const char *duk_str_jsondec_reclimit = "json decode recursion limit";
8787DUK_INTERNAL const char *duk_str_jsonenc_reclimit = "json encode recursion limit";
8788DUK_INTERNAL const char *duk_str_cyclic_input = "cyclic input";
8790/* Object property access */
8791DUK_INTERNAL const char *duk_str_proxy_revoked = "proxy revoked";
8792DUK_INTERNAL const char *duk_str_invalid_base = "invalid base value";
8793DUK_INTERNAL const char *duk_str_strict_caller_read = "attempt to read strict 'caller'";
8794DUK_INTERNAL const char *duk_str_proxy_rejected = "proxy rejected";
8795DUK_INTERNAL const char *duk_str_invalid_array_length = "invalid array length";
8796DUK_INTERNAL const char *duk_str_array_length_write_failed = "array length write failed";
8797DUK_INTERNAL const char *duk_str_array_length_not_writable = "array length non-writable";
8798DUK_INTERNAL const char *duk_str_setter_undefined = "setter undefined";
8799DUK_INTERNAL const char *duk_str_redefine_virt_prop = "attempt to redefine virtual property";
8800DUK_INTERNAL const char *duk_str_invalid_descriptor = "invalid descriptor";
8801DUK_INTERNAL const char *duk_str_property_is_virtual = "property is virtual";
8803/* Compiler */
8804DUK_INTERNAL const char *duk_str_parse_error = "parse error";
8805DUK_INTERNAL const char *duk_str_duplicate_label = "duplicate label";
8806DUK_INTERNAL const char *duk_str_invalid_label = "invalid label";
8807DUK_INTERNAL const char *duk_str_invalid_array_literal = "invalid array literal";
8808DUK_INTERNAL const char *duk_str_invalid_object_literal = "invalid object literal";
8809DUK_INTERNAL const char *duk_str_invalid_var_declaration = "invalid variable declaration";
8810DUK_INTERNAL const char *duk_str_cannot_delete_identifier = "cannot delete identifier";
8811DUK_INTERNAL const char *duk_str_invalid_expression = "invalid expression";
8812DUK_INTERNAL const char *duk_str_invalid_lvalue = "invalid lvalue";
8813DUK_INTERNAL const char *duk_str_expected_identifier = "expected identifier";
8814DUK_INTERNAL const char *duk_str_empty_expr_not_allowed = "empty expression not allowed";
8815DUK_INTERNAL const char *duk_str_invalid_for = "invalid for statement";
8816DUK_INTERNAL const char *duk_str_invalid_switch = "invalid switch statement";
8817DUK_INTERNAL const char *duk_str_invalid_break_cont_label = "invalid break/continue label";
8818DUK_INTERNAL const char *duk_str_invalid_return = "invalid return";
8819DUK_INTERNAL const char *duk_str_invalid_try = "invalid try";
8820DUK_INTERNAL const char *duk_str_invalid_throw = "invalid throw";
8821DUK_INTERNAL const char *duk_str_with_in_strict_mode = "with in strict mode";
8822DUK_INTERNAL const char *duk_str_func_stmt_not_allowed = "function statement not allowed";
8823DUK_INTERNAL const char *duk_str_unterminated_stmt = "unterminated statement";
8824DUK_INTERNAL const char *duk_str_invalid_arg_name = "invalid argument name";
8825DUK_INTERNAL const char *duk_str_invalid_func_name = "invalid function name";
8826DUK_INTERNAL const char *duk_str_invalid_getset_name = "invalid getter/setter name";
8827DUK_INTERNAL const char *duk_str_func_name_required = "function name required";
8829/* Regexp */
8830DUK_INTERNAL const char *duk_str_invalid_quantifier_no_atom = "quantifier without preceding atom";
8831DUK_INTERNAL const char *duk_str_invalid_quantifier_values = "quantifier values invalid (qmin > qmax)";
8832DUK_INTERNAL const char *duk_str_quantifier_too_many_copies = "quantifier expansion requires too many atom copies";
8833DUK_INTERNAL const char *duk_str_unexpected_closing_paren = "unexpected closing parenthesis";
8834DUK_INTERNAL const char *duk_str_unexpected_end_of_pattern = "unexpected end of pattern";
8835DUK_INTERNAL const char *duk_str_unexpected_regexp_token = "unexpected token in regexp";
8836DUK_INTERNAL const char *duk_str_invalid_regexp_flags = "invalid regexp flags";
8837DUK_INTERNAL const char *duk_str_invalid_backrefs = "invalid backreference(s)";
8838
8839/* Limits */
8840DUK_INTERNAL const char *duk_str_valstack_limit = "valstack limit";
8841DUK_INTERNAL const char *duk_str_callstack_limit = "callstack limit";
8842DUK_INTERNAL const char *duk_str_catchstack_limit = "catchstack limit";
8843DUK_INTERNAL const char *duk_str_prototype_chain_limit = "prototype chain limit";
8844DUK_INTERNAL const char *duk_str_bound_chain_limit = "function call bound chain limit";
8845DUK_INTERNAL const char *duk_str_c_callstack_limit = "C call stack depth limit";
8846DUK_INTERNAL const char *duk_str_compiler_recursion_limit = "compiler recursion limit";
8847DUK_INTERNAL const char *duk_str_bytecode_limit = "bytecode limit";
8848DUK_INTERNAL const char *duk_str_reg_limit = "register limit";
8849DUK_INTERNAL const char *duk_str_temp_limit = "temp limit";
8850DUK_INTERNAL const char *duk_str_const_limit = "const limit";
8851DUK_INTERNAL const char *duk_str_func_limit = "function limit";
8852DUK_INTERNAL const char *duk_str_regexp_compiler_recursion_limit = "regexp compiler recursion limit";
8853DUK_INTERNAL const char *duk_str_regexp_executor_recursion_limit = "regexp executor recursion limit";
8854DUK_INTERNAL const char *duk_str_regexp_executor_step_limit = "regexp step limit";
8855
8856/* Misc */
8857#line 1 "duk_debug_macros.c"
8858/*
8859 * Debugging macro calls.
8860 */
8861
8862/* include removed: duk_internal.h */
8863
8864#ifdef DUK_USE_DEBUG
8865
8866/*
8867 * Debugging enabled
8868 */
8869
8870#include <stdio.h>
8871#include <stdlib.h>
8872#include <stdarg.h>
8873
8874#define DUK__DEBUG_BUFSIZE DUK_USE_DEBUG_BUFSIZE
8875DUK_LOCAL char duk__debug_buf[DUK__DEBUG_BUFSIZE];
8876
8877DUK_LOCAL const char *duk__get_level_string(duk_small_int_t level) {
8878 switch ((int) level) {
8879 case DUK_LEVEL_DEBUG:
8880 return "D";
8881 case DUK_LEVEL_DDEBUG:
8882 return "DD";
8883 case DUK_LEVEL_DDDEBUG:
8884 return "DDD";
8885 }
8886 return "???";
8887}
8888
8889#ifdef DUK_USE_DPRINT_COLORS
8890
8891/* http://en.wikipedia.org/wiki/ANSI_escape_code */
8892#define DUK__TERM_REVERSE "\x1b[7m"
8893#define DUK__TERM_BRIGHT "\x1b[1m"
8894#define DUK__TERM_RESET "\x1b[0m"
8895#define DUK__TERM_BLUE "\x1b[34m"
8896#define DUK__TERM_RED "\x1b[31m"
8897
8898DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
8899 DUK_UNREF(level);
8900 return (const char *) DUK__TERM_RED;
8901}
8902
8903DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
8904 switch ((int) level) {
8905 case DUK_LEVEL_DEBUG:
8906 return (const char *) (DUK__TERM_RESET DUK__TERM_BRIGHT);
8907 case DUK_LEVEL_DDEBUG:
8908 return (const char *) (DUK__TERM_RESET);
8909 case DUK_LEVEL_DDDEBUG:
8910 return (const char *) (DUK__TERM_RESET DUK__TERM_BLUE);
8911 }
8912 return (const char *) DUK__TERM_RESET;
8913}
8914
8915DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
8916 DUK_UNREF(level);
8917 return (const char *) DUK__TERM_RESET;
8918}
8919
8920#else
8921
8922DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
8923 DUK_UNREF(level);
8924 return (const char *) "";
8925}
8926
8927DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
8928 DUK_UNREF(level);
8929 return (const char *) "";
8930}
8931
8932DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
8933 DUK_UNREF(level);
8934 return (const char *) "";
8935}
8936
8937#endif /* DUK_USE_DPRINT_COLORS */
8938
8939#ifdef DUK_USE_VARIADIC_MACROS
8940
8941DUK_INTERNAL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
8942 va_list ap;
8943
8944 va_start(ap, fmt);
8945
8946 DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
8947 duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
8948
8949 DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%ld (%s):%s %s%s\n",
8950 (const char *) duk__get_term_1(level),
8951 (const char *) duk__get_level_string(level),
8952 (const char *) file,
8953 (long) line,
8954 (const char *) func,
8955 (const char *) duk__get_term_2(level),
8956 (const char *) duk__debug_buf,
8957 (const char *) duk__get_term_3(level));
8959
8960 va_end(ap);
8961}
8962
8963#else /* DUK_USE_VARIADIC_MACROS */
8964
8965DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
8966DUK_INTERNAL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
8967DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
8968DUK_INTERNAL duk_small_int_t duk_debug_level_stash;
8969
8970DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
8971 va_list ap;
8972 duk_small_int_t level = duk_debug_level_stash;
8973
8974 va_start(ap, fmt);
8975
8976 DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
8977 duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
8978
8979 DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%s (%s):%s %s%s\n",
8980 (const char *) duk__get_term_1(level),
8981 (const char *) duk__get_level_string(duk_debug_level_stash),
8982 (const char *) duk_debug_file_stash,
8983 (const char *) duk_debug_line_stash,
8984 (const char *) duk_debug_func_stash,
8985 (const char *) duk__get_term_2(level),
8986 (const char *) duk__debug_buf,
8987 (const char *) duk__get_term_3(level));
8989
8990 va_end(ap);
8991}
8992
8993#endif /* DUK_USE_VARIADIC_MACROS */
8994
8995#else /* DUK_USE_DEBUG */
8996
8997/*
8998 * Debugging disabled
8999 */
9000
9001#endif /* DUK_USE_DEBUG */
9002#line 1 "duk_builtins.c"
9003/*
9004 * Automatically generated by genbuiltins.py, do not edit!
9005 */
9006
9007/* include removed: duk_internal.h */
9008
9009#if defined(DUK_USE_ROM_STRINGS)
9010#error ROM support not enabled, rerun make_dist.py with --rom-support
9011#else /* DUK_USE_ROM_STRINGS */
9012DUK_INTERNAL const duk_uint8_t duk_strings_data[1049] = {
901379,104,209,144,168,105,6,78,182,139,90,122,8,154,140,35,103,35,117,193,73,
90145,52,116,180,104,166,135,52,189,4,98,12,27,178,156,80,211,31,161,115,150,
901564,52,221,109,24,18,68,157,24,38,67,118,36,55,73,119,151,164,140,93,18,117,
9016128,153,201,228,201,205,2,250,8,196,24,232,104,82,146,40,232,193,48,118,
9017168,37,147,212,54,127,113,208,70,32,194,187,68,54,127,113,208,70,32,196,
9018123,68,54,127,113,209,44,12,121,7,208,70,32,194,186,134,207,236,126,219,
9019160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253,159,217,
9020116,17,136,48,190,209,13,159,217,253,151,65,24,131,12,233,86,224,79,236,
9021254,203,160,140,65,134,116,171,112,39,246,223,105,208,70,32,193,140,183,4,
902211,55,92,20,244,141,169,186,50,11,164,109,77,208,208,165,36,79,215,185,13,
9023153,34,110,204,241,32,6,66,84,11,112,200,84,52,157,124,92,242,70,120,45,64,
9024186,17,22,138,38,0,172,140,19,154,84,26,145,0,86,69,17,180,97,34,0,172,132,
902575,144,215,77,221,91,132,5,147,178,156,80,211,30,160,93,9,215,21,115,119,
9026169,49,75,211,138,26,101,205,222,68,157,47,78,40,105,151,55,120,204,156,
9027189,56,161,166,52,157,72,136,138,65,154,232,147,162,4,136,150,81,115,66,
9028208,210,37,96,148,250,134,140,151,39,212,125,255,221,125,73,80,209,146,233,
9029124,93,55,79,15,34,196,230,202,113,160,166,232,157,132,148,128,98,28,46,
9030114,200,6,153,180,96,73,19,74,113,67,76,103,5,36,20,211,70,140,133,67,72,
903149,245,160,235,81,212,52,168,106,39,132,253,111,80,210,161,168,158,5,245,
9032191,96,31,172,15,208,23,226,190,131,232,62,131,232,11,251,127,93,245,223,
903393,251,172,234,27,80,45,3,250,14,140,19,34,65,19,81,132,108,228,97,1,107,
903433,12,32,45,100,136,206,9,12,196,155,134,69,146,100,235,226,231,146,51,194,
903572,218,48,145,4,200,119,89,189,81,49,39,72,147,235,226,233,186,120,121,58,
9036226,167,90,124,93,55,107,71,137,33,68,68,130,64,206,75,189,209,156,144,84,
903744,141,3,8,137,187,178,156,80,211,26,110,242,100,230,146,120,121,8,48,76,6,
903889,26,105,157,65,196,201,213,145,166,153,212,28,76,157,113,75,34,78,62,14,
903938,73,105,228,142,136,178,48,141,152,228,73,150,83,0,148,39,137,75,67,73,
9040214,209,129,36,85,190,206,32,17,6,9,128,141,3,8,130,161,100,235,64,194,24,
904152,41,73,19,189,200,108,201,19,111,181,2,232,66,239,173,37,230,157,244,56,
9042153,4,225,145,27,233,93,22,1,114,62,251,80,69,128,121,247,213,146,228,109,
904379,190,212,17,35,106,125,246,78,164,68,68,111,175,23,217,45,13,33,119,208,
904468,210,38,250,192,61,91,233,80,208,45,25,36,81,190,156,13,26,201,19,239,
9045162,2,214,66,31,125,153,226,64,13,27,236,72,96,130,68,62,251,48,68,196,153,
9046119,217,157,18,56,156,199,161,100,42,26,250,77,36,140,122,40,144,19,34,9,
904724,246,103,139,172,150,56,125,145,1,17,29,44,112,250,183,0,100,24,200,218,
9048140,228,185,130,9,19,237,190,208,73,184,146,35,68,146,163,8,50,178,99,136,
904944,89,196,2,33,70,64,208,196,67,74,226,88,17,105,73,24,186,37,40,38,5,133,
9050161,89,4,183,25,115,119,86,227,118,83,138,26,103,255,223,209,106,141,25,11,
9051244,95,117,56,208,159,250,223,251,250,45,52,13,250,47,186,156,104,79,253,
9052111,253,253,22,144,210,253,23,221,78,52,39,254,187,254,254,139,77,67,75,
9053244,95,117,56,208,159,250,239,251,250,45,22,141,23,209,125,212,227,66,127,
9054235,63,239,69,163,69,247,83,141,9,255,165,12,72,5,16,64,145,10,32,76,71,64,
9055156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,147,32,134,226,
905617,114,33,202,134,129,107,192,202,232,160,180,104,166,135,52,72,40,144,213,
905733,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,98,57,38,116,72,
9058179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,42,228,12,182,
905958,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,94,100,104,
9060228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,46,68,82,24,
9061245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,33,223,20,
906284,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,130,44,96,
9063};
9064#endif /* DUK_USE_ROM_STRINGS */
9065
9066#if defined(DUK_USE_ROM_OBJECTS)
9067#error ROM support not enabled, rerun make_dist.py with --rom-support
9068#else /* DUK_USE_ROM_OBJECTS */
9069/* native functions: 149 */
9220};
9221#if defined(DUK_USE_BUILTIN_INITJS)
9222DUK_INTERNAL const duk_uint8_t duk_initjs_data[204] = {
922340,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
9224105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
9225102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
9226108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
9227109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
9228108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
9229108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
923041,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,79,98,106,
9231101,99,116,46,99,114,101,97,116,101,40,110,117,108,108,41,41,125,41,40,116,
9232104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
9233};
9234#endif /* DUK_USE_BUILTIN_INITJS */
9235#if defined(DUK_USE_DOUBLE_LE)
9236DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9237105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9238152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9239240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
924014,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9241203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9242176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9243148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9244243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
924521,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9246145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9247158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9248228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9249202,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,
9250136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
925140,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9252200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9253119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9254138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9255166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
925619,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
925717,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9258100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
925930,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9260240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9261236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9262135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9263208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9264240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
926582,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9266158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9267135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9268217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
926946,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9270230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9271205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9272230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9273237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9274223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9275119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9276195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9277135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9278128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
927961,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9280123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9281250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9282102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9283105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9284183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
928515,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9286195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9287202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9288131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9289133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9290195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9291121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9292179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9293242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9294148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9295122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9296150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
929748,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,31,
9298255,255,255,255,255,253,239,240,153,178,103,95,173,6,101,88,176,0,64,0,0,0,
92990,0,0,3,168,0,0,0,0,0,0,31,15,241,26,19,233,201,169,38,180,91,242,103,70,
9300147,58,77,75,48,0,0,0,0,0,0,60,31,226,51,162,199,131,82,77,104,183,228,206,
9301141,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,
93020,0,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,248,
9303190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,167,
9304126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,64,
9305247,111,238,56,0,127,199,2,49,72,0,0,0,0,0,0,248,127,180,81,36,4,51,166,
9306248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9307244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9308195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
930959,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
931080,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9311184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
93120,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9313238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9314196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9315171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
931694,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9317101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
931843,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9319113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9320187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9321251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9322151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9323121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9324167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
932543,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9326231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9327211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9328208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
932915,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9330189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9331224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9332233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9333200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
933424,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
93350,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9336240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9337115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9338252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9339111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9340143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9341238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
934260,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9343165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,105,87,20,139,10,191,5,
934464,130,76,156,197,132,1,101,91,91,187,22,176,36,8,28,201,204,160,119,156,
9345253,127,33,23,115,31,193,102,79,142,202,44,15,232,34,182,84,113,95,115,248,
934652,201,241,216,176,139,0,59,148,152,85,239,47,108,254,5,66,76,1,130,212,69,
934779,178,16,148,8,61,58,52,170,49,190,202,6,105,219,251,52,245,7,49,252,22,
9348157,26,85,25,64,205,59,127,102,158,160,246,63,74,7,135,23,53,2,65,48,227,
9349223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,195,
9350211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,15,
935147,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9352136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
935388,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
935421,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9355134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9356191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,0,0,0,0,0,65,226,
935732,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,
935860,56,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9359147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9360252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9361167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9362184,2,172,254,0,0,255,171,8,137,144,0,0,0,0,0,0,0,128,68,73,4,195,187,126,
9363226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
93640,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9365153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9366163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9367245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9368244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9369207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9370186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9371221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9372179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9373208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9374195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9375119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9376115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9377102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
93780,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,
93790,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,
9380151,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,
9381177,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,
9382203,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,
9383128,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,
9384101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9385143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9386124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
938739,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9388100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
938940,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
939057,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
939150,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
939295,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9393101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9394150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9395108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9396200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9397186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9398101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9399209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9400181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
940198,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
94022,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9403213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9404155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
940567,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9406203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
940770,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9408229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
940989,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
941010,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9411119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
941229,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9413243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9414};
9415#elif defined(DUK_USE_DOUBLE_BE)
9416DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9417105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9418152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9419240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
942014,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9421203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9422176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9423148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9424243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
942521,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9426145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9427158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9428228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9429202,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,
9430136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
943140,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9432200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9433119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9434138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9435166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
943619,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
943717,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9438100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
943930,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9440240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9441236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9442135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9443208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9444240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
944582,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9446158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9447135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9448217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
944946,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9450230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9451205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9452230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9453237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9454223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9455119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9456195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9457135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9458128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
945961,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9460123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9461250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9462102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9463105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9464183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
946515,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9466195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9467202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9468131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9469133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9470195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9471121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9472179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9473242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9474148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9475122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9476150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
947748,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,15,
9478253,255,255,255,255,255,255,240,153,178,103,95,173,6,101,88,176,0,0,0,0,0,
94790,0,0,67,168,15,255,0,0,0,0,0,0,17,26,19,233,201,169,38,180,91,242,103,70,
9480147,58,77,75,48,31,252,0,0,0,0,0,0,34,51,162,199,131,82,77,104,183,228,206,
9481141,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,
94820,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,248,
9483190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,167,
9484126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,64,
9485247,111,238,56,0,127,199,2,49,72,127,248,0,0,0,0,0,0,180,81,36,4,51,166,
9486248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9487244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9488195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
948959,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
949080,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9491184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
94920,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9493238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9494196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9495171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
949694,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9497101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
949843,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9499113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9500187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9501251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9502151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9503121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9504167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
950543,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9506231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9507211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9508208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
950915,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9510189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9511224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9512233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9513200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
951424,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
95150,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9516240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9517115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9518252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9519111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9520143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9521238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
952260,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9523165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,64,5,191,10,139,20,87,
9524105,130,76,156,197,132,4,0,38,187,27,187,85,81,104,28,201,204,160,31,243,
952523,33,127,125,28,247,193,102,79,142,202,44,3,255,113,84,118,82,184,47,232,
952652,201,241,216,176,139,0,255,111,45,236,84,155,148,58,5,66,76,4,0,146,31,
9527181,68,66,209,136,61,58,52,170,49,190,202,1,255,53,4,243,51,249,222,108,22,
9528157,26,85,25,64,63,246,160,158,102,127,59,205,74,7,135,23,53,2,65,48,227,
9529223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,195,
9530211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,15,
953147,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9532136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
953388,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
953421,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9535134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9536191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,32,98,65,128,0,0,
95370,0,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,
953860,56,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9539147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9540252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9541167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9542184,2,172,254,0,0,255,171,8,137,144,128,0,0,0,0,0,0,0,68,73,4,195,187,126,
9543226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
95440,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9545153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9546163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9547245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9548244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9549207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9550186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9551221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9552179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9553208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9554195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9555119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9556115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9557102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
95580,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,
9559255,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,
9560151,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,
9561177,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,
9562203,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,
9563128,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,
9564101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9565143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9566124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
956739,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9568100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
956940,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
957057,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
957150,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
957295,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9573101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9574150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9575108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9576200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9577186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9578101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9579209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9580181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
958198,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
95822,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9583213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9584155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
958567,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9586203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
958770,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9588229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
958989,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
959010,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9591119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
959229,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9593243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9594};
9595#elif defined(DUK_USE_DOUBLE_ME)
9596DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9597105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9598152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9599240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
960014,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9601203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9602176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9603148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9604243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
960521,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9606145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9607158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9608228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9609202,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,
9610136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
961140,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9612200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9613119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9614138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9615166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
961619,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
961717,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9618100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
961930,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9620240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9621236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9622135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9623208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9624240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
962582,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9626158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9627135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9628217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
962946,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9630230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9631205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9632230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9633237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9634223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9635119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9636195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9637135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9638128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
963961,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9640123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9641250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9642102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9643105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9644183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
964515,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9646195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9647202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9648131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9649133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9650195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9651121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9652179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9653242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9654148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9655122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9656150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
965748,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,31,
9658255,253,239,255,255,255,255,240,153,178,103,95,173,6,101,88,176,0,0,0,0,0,
965964,0,0,3,168,0,0,31,15,224,0,0,0,17,26,19,233,201,169,38,180,91,242,103,70,
9660147,58,77,75,48,0,0,60,31,192,0,0,0,34,51,162,199,131,82,77,104,183,228,
9661206,141,38,116,154,150,96,0,0,120,127,128,0,0,0,0,15,248,192,70,40,0,0,0,0,
96620,0,0,0,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,
9663248,190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,
9664167,126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,
966564,247,111,238,56,0,127,199,2,49,72,0,0,248,127,0,0,0,0,180,81,36,4,51,166,
9666248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9667244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9668195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
966959,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
967080,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9671184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
96720,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9673238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9674196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9675171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
967694,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9677101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
967843,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9679113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9680187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9681251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9682151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9683121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9684167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
968543,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9686231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9687211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9688208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
968915,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9690189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9691224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9692233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9693200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
969424,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
96950,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9696240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9697115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9698252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9699111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9700143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9701238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
970260,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9703165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,10,191,5,64,105,87,20,
9704139,130,76,156,197,132,11,22,176,36,1,101,91,91,184,28,201,204,160,33,23,
9705115,31,247,156,253,127,65,102,79,142,202,44,4,113,95,115,255,232,34,182,88,
970652,201,241,216,176,139,1,239,47,108,252,59,148,152,86,5,66,76,15,178,16,
9707148,1,130,212,69,72,61,58,52,170,49,190,202,4,245,7,49,254,105,219,251,52,
970822,157,26,85,25,64,158,160,246,63,205,59,127,102,74,7,135,23,53,2,65,48,
9709227,223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,
9710195,211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,
971115,47,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9712136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
971388,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
971421,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9715134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9716191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,0,65,226,32,0,0,0,
97170,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,60,
971856,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9719147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9720252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9721167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9722184,2,172,254,0,0,255,171,8,137,144,0,0,0,128,0,0,0,0,68,73,4,195,187,126,
9723226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
97240,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9725153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9726163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9727245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9728244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9729207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9730186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9731221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9732179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9733208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9734195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9735119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9736115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9737102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
97380,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,
97390,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,
9740151,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,
9741177,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,
9742203,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,
9743128,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,
9744101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9745143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9746124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
974739,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9748100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
974940,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
975057,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
975150,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
975295,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9753101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9754150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9755108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9756200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9757186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9758101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9759209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9760181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
976198,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
97622,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9763213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9764155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
976567,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9766203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
976770,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9768229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
976989,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
977010,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9771119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
977229,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9773243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9774};
9775#else
9776#error invalid endianness defines
9777#endif
9778#endif /* DUK_USE_ROM_OBJECTS */
9779#line 1 "duk_error_macros.c"
9780/*
9781 * Error, fatal, and panic handling.
9782 */
9784/* include removed: duk_internal.h */
9785
9786#define DUK__ERRFMT_BUFSIZE 256 /* size for formatting buffers */
9787
9788#if defined(DUK_USE_VERBOSE_ERRORS)
9789
9790DUK_INTERNAL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
9791 va_list ap;
9792 char msg[DUK__ERRFMT_BUFSIZE];
9793 va_start(ap, fmt);
9794 (void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
9795 msg[sizeof(msg) - 1] = (char) 0;
9796 duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
9797 va_end(ap); /* dead code, but ensures portability (see Linux man page notes) */
9798}
9799
9800DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
9801 duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
9802}
9803
9804#else /* DUK_USE_VERBOSE_ERRORS */
9805
9810#endif /* DUK_USE_VERBOSE_ERRORS */
9812/*
9813 * Error throwing helpers
9815
9816#if defined(DUK_USE_VERBOSE_ERRORS)
9817#if defined(DUK_USE_PARANOID_ERRORS)
9818DUK_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) {
9819 DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
9820 expect_name, duk_get_type_name((duk_context *) thr, index), (long) index);
9821}
9822#else
9823DUK_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) {
9824 DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
9825 expect_name, duk_push_string_readable((duk_context *) thr, index), (long) index);
9826}
9827#endif
9828DUK_INTERNAL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9829 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
9830}
9831DUK_INTERNAL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index) {
9832 DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_API_ERROR, "invalid stack index %ld", (long) (index));
9833}
9834DUK_INTERNAL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9835 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_API_ERROR, message);
9836}
9837DUK_INTERNAL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9839}
9840#if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
9841DUK_INTERNAL void duk_err_unsupported_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9842 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_UNSUPPORTED_ERROR, DUK_STR_UNSUPPORTED);
9843}
9844#endif
9845DUK_INTERNAL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9846 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
9847}
9848DUK_INTERNAL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9849 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, message);
9850}
9851DUK_INTERNAL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9852 DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ALLOC_ERROR, message);
9853}
9854#else
9855/* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
9856 * when non-verbose errors are used.
9857 */
9858DUK_INTERNAL void duk_err_type(duk_hthread *thr) {
9860}
9863}
9866}
9867DUK_INTERNAL void duk_err_syntax(duk_hthread *thr) {
9869}
9870DUK_INTERNAL void duk_err_unimplemented(duk_hthread *thr) {
9872}
9873DUK_INTERNAL void duk_err_unsupported(duk_hthread *thr) {
9875}
9878}
9881}
9882#endif
9883
9884/*
9885 * Default fatal error handler
9886 */
9887
9888DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) {
9890#if defined(DUK_USE_FILE_IO)
9891 DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null"));
9893#else
9894 /* omit print */
9895#endif
9896 DUK_D(DUK_DPRINT("default fatal handler called, code %ld -> calling DUK_PANIC()", (long) code));
9897 DUK_PANIC(code, msg);
9899}
9900
9901/*
9902 * Default panic handler
9903 */
9904
9905#if !defined(DUK_USE_PANIC_HANDLER)
9906DUK_INTERNAL void duk_default_panic_handler(duk_errcode_t code, const char *msg) {
9907#if defined(DUK_USE_FILE_IO)
9908 DUK_FPRINTF(DUK_STDERR, "PANIC %ld: %s ("
9909#if defined(DUK_USE_PANIC_ABORT)
9910 "calling abort"
9911#elif defined(DUK_USE_PANIC_EXIT)
9912 "calling exit"
9913#elif defined(DUK_USE_PANIC_SEGFAULT)
9914 "segfaulting on purpose"
9915#else
9916#error no DUK_USE_PANIC_xxx macro defined
9917#endif
9918 ")\n", (long) code, (const char *) (msg ? msg : "null"));
9920#else
9921 /* omit print */
9922 DUK_UNREF(code);
9923 DUK_UNREF(msg);
9924#endif
9925
9926#if defined(DUK_USE_PANIC_ABORT)
9927 DUK_ABORT();
9928#elif defined(DUK_USE_PANIC_EXIT)
9929 DUK_EXIT(-1);
9930#elif defined(DUK_USE_PANIC_SEGFAULT)
9931 /* exit() afterwards to satisfy "noreturn" */
9932 DUK_CAUSE_SEGFAULT(); /* SCANBUILD: "Dereference of null pointer", normal */
9933 DUK_EXIT(-1);
9934#else
9935#error no DUK_USE_PANIC_xxx macro defined
9936#endif
9937
9940#endif /* !DUK_USE_PANIC_HANDLER */
9941
9942#undef DUK__ERRFMT_BUFSIZE
9943#line 1 "duk_unicode_support.c"
9944/*
9945 * Various Unicode help functions for character classification predicates,
9946 * case conversion, decoding, etc.
9947 */
9948
9949/* include removed: duk_internal.h */
9950
9951/*
9952 * Fast path tables
9953 */
9954
9955#if defined(DUK_USE_IDCHAR_FASTPATH)
9956DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
9957 /* 0: not IdentifierStart or IdentifierPart
9958 * 1: IdentifierStart and IdentifierPart
9959 * -1: IdentifierPart only
9960 */
9961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00...0x0f */
9962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10...0x1f */
9963 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20...0x2f */
9964 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, /* 0x30...0x3f */
9965 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40...0x4f */
9966 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50...0x5f */
9967 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60...0x6f */
9968 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70...0x7f */
9969};
9970#endif
9971
9972/*
9973 * XUTF-8 and CESU-8 encoding/decoding
9974 */
9975
9978 if (x < 0x80UL) {
9979 /* 7 bits */
9980 return 1;
9981 } else if (x < 0x800UL) {
9982 /* 11 bits */
9983 return 2;
9984 } else if (x < 0x10000UL) {
9985 /* 16 bits */
9986 return 3;
9987 } else if (x < 0x200000UL) {
9988 /* 21 bits */
9989 return 4;
9990 } else if (x < 0x4000000UL) {
9991 /* 26 bits */
9992 return 5;
9993 } else if (x < (duk_ucodepoint_t) 0x80000000UL) {
9994 /* 31 bits */
9995 return 6;
9996 } else {
9997 /* 36 bits */
9998 return 7;
9999 }
10000}
10001
10002#if defined(DUK_USE_ASSERTIONS)
10003DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
10005 if (x < 0x80UL) {
10006 /* 7 bits */
10007 return 1;
10008 } else if (x < 0x800UL) {
10009 /* 11 bits */
10010 return 2;
10011 } else if (x < 0x10000UL) {
10012 /* 16 bits */
10013 return 3;
10014 } else {
10015 /* Encoded as surrogate pair, each encoding to 3 bytes for
10016 * 6 bytes total. Codepoints above U+10FFFF encode as 6 bytes
10017 * too, see duk_unicode_encode_cesu8().
10018 */
10019 return 3 + 3;
10020 }
10021}
10022#endif /* DUK_USE_ASSERTIONS */
10023
10024DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
10025 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
10026};
10027
10028/* Encode to extended UTF-8; 'out' must have space for at least
10029 * DUK_UNICODE_MAX_XUTF8_LENGTH bytes. Allows encoding of any
10030 * 32-bit (unsigned) codepoint.
10031 */
10034 duk_small_int_t len;
10035 duk_uint8_t marker;
10037
10039 DUK_ASSERT(len > 0);
10040
10041 marker = duk_unicode_xutf8_markers[len - 1]; /* 64-bit OK because always >= 0 */
10042
10043 i = len;
10044 DUK_ASSERT(i > 0);
10045 do {
10046 i--;
10047 if (i > 0) {
10048 out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
10049 x >>= 6;
10050 } else {
10051 /* Note: masking of 'x' is not necessary because of
10052 * range check and shifting -> no bits overlapping
10053 * the marker should be set.
10054 */
10055 out[0] = (duk_uint8_t) (marker + x);
10056 }
10057 } while (i > 0);
10058
10059 return len;
10060}
10061
10062/* Encode to CESU-8; 'out' must have space for at least
10063 * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
10064 * will encode to garbage but won't overwrite the output buffer.
10065 */
10068 duk_small_int_t len;
10069
10070 if (x < 0x80UL) {
10071 out[0] = (duk_uint8_t) x;
10072 len = 1;
10073 } else if (x < 0x800UL) {
10074 out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
10075 out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
10076 len = 2;
10077 } else if (x < 0x10000UL) {
10078 /* surrogate pairs get encoded here */
10079 out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
10080 out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
10081 out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
10082 len = 3;
10083 } else {
10084 /*
10085 * Unicode codepoints above U+FFFF are encoded as surrogate
10086 * pairs here. This ensures that all CESU-8 codepoints are
10087 * 16-bit values as expected in Ecmascript. The surrogate
10088 * pairs always get a 3-byte encoding (each) in CESU-8.
10089 * See: http://en.wikipedia.org/wiki/Surrogate_pair
10090 *
10091 * 20-bit codepoint, 10 bits (A and B) per surrogate pair:
10092 *
10093 * x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
10094 * sp1 = 0b110110AA AAAAAAAA (0xd800 + ((x >> 10) & 0x3ff))
10095 * sp2 = 0b110111BB BBBBBBBB (0xdc00 + (x & 0x3ff))
10096 *
10097 * Encoded into CESU-8:
10098 *
10099 * sp1 -> 0b11101101 (0xe0 + ((sp1 >> 12) & 0x0f))
10100 * -> 0b1010AAAA (0x80 + ((sp1 >> 6) & 0x3f))
10101 * -> 0b10AAAAAA (0x80 + (sp1 & 0x3f))
10102 * sp2 -> 0b11101101 (0xe0 + ((sp2 >> 12) & 0x0f))
10103 * -> 0b1011BBBB (0x80 + ((sp2 >> 6) & 0x3f))
10104 * -> 0b10BBBBBB (0x80 + (sp2 & 0x3f))
10105 *
10106 * Note that 0x10000 must be subtracted first. The code below
10107 * avoids the sp1, sp2 temporaries which saves around 20 bytes
10108 * of code.
10110
10111 x -= 0x10000UL;
10112
10113 out[0] = (duk_uint8_t) (0xed);
10114 out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
10115 out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
10116 out[3] = (duk_uint8_t) (0xed);
10117 out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
10118 out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
10119 len = 6;
10120 }
10121
10122 return len;
10123}
10124
10125/* Decode helper. Return zero on error. */
10126DUK_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) {
10127 const duk_uint8_t *p;
10128 duk_uint32_t res;
10131
10132 DUK_UNREF(thr);
10133
10134 p = *ptr;
10135 if (p < ptr_start || p >= ptr_end) {
10136 goto fail;
10137 }
10138
10139 /*
10140 * UTF-8 decoder which accepts longer than standard byte sequences.
10141 * This allows full 32-bit code points to be used.
10142 */
10143
10144 ch = (duk_uint_fast8_t) (*p++);
10145 if (ch < 0x80) {
10146 /* 0xxx xxxx [7 bits] */
10147 res = (duk_uint32_t) (ch & 0x7f);
10148 n = 0;
10149 } else if (ch < 0xc0) {
10150 /* 10xx xxxx -> invalid */
10151 goto fail;
10152 } else if (ch < 0xe0) {
10153 /* 110x xxxx 10xx xxxx [11 bits] */
10154 res = (duk_uint32_t) (ch & 0x1f);
10155 n = 1;
10156 } else if (ch < 0xf0) {
10157 /* 1110 xxxx 10xx xxxx 10xx xxxx [16 bits] */
10158 res = (duk_uint32_t) (ch & 0x0f);
10159 n = 2;
10160 } else if (ch < 0xf8) {
10161 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx [21 bits] */
10162 res = (duk_uint32_t) (ch & 0x07);
10163 n = 3;
10164 } else if (ch < 0xfc) {
10165 /* 1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [26 bits] */
10166 res = (duk_uint32_t) (ch & 0x03);
10167 n = 4;
10168 } else if (ch < 0xfe) {
10169 /* 1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [31 bits] */
10170 res = (duk_uint32_t) (ch & 0x01);
10171 n = 5;
10172 } else if (ch < 0xff) {
10173 /* 1111 1110 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [36 bits] */
10174 res = (duk_uint32_t) (0);
10175 n = 6;
10176 } else {
10177 /* 8-byte format could be:
10178 * 1111 1111 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [41 bits]
10179 *
10180 * However, this format would not have a zero bit following the
10181 * leading one bits and would not allow 0xFF to be used as an
10182 * "invalid xutf-8" marker for internal keys. Further, 8-byte
10183 * encodings (up to 41 bit code points) are not currently needed.
10184 */
10185 goto fail;
10186 }
10187
10188 DUK_ASSERT(p >= ptr_start); /* verified at beginning */
10189 if (p + n > ptr_end) {
10190 /* check pointer at end */
10191 goto fail;
10192 }
10194 while (n > 0) {
10195 DUK_ASSERT(p >= ptr_start && p < ptr_end);
10196 res = res << 6;
10197 res += (duk_uint32_t) ((*p++) & 0x3f);
10198 n--;
10199 }
10200
10201 *ptr = p;
10202 *out_cp = res;
10203 return 1;
10204
10205 fail:
10206 return 0;
10207}
10208
10209/* used by e.g. duk_regexp_executor.c, string built-ins */
10210DUK_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) {
10212
10213 if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
10214 return cp;
10215 }
10216 DUK_ERROR_INTERNAL(thr, "utf-8 decode failed"); /* XXX: 'internal error' is a bit of a misnomer */
10218 return 0;
10219}
10220
10221/* Compute (extended) utf-8 length without codepoint encoding validation,
10222 * used for string interning.
10223 *
10224 * NOTE: This algorithm is performance critical, more so than string hashing
10225 * in some cases. It is needed when interning a string and needs to scan
10226 * every byte of the string with no skipping. Having an ASCII fast path
10227 * is useful if possible in the algorithm. The current algorithms were
10228 * chosen from several variants, based on x64 gcc -O2 testing. See:
10229 * https://github.com/svaarala/duktape/pull/422
10230 *
10231 * NOTE: must match src/dukutil.py:duk_unicode_unvalidated_utf8_length().
10232 */
10233
10234#if defined(DUK_USE_PREFER_SIZE)
10235/* Small variant; roughly 150 bytes smaller than the fast variant. */
10237 const duk_uint8_t *p;
10238 const duk_uint8_t *p_end;
10239 duk_size_t ncont;
10240 duk_size_t clen;
10241
10242 p = data;
10243 p_end = data + blen;
10244 ncont = 0;
10245 while (p != p_end) {
10246 duk_uint8_t x;
10247 x = *p++;
10248 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10249 ncont++;
10250 }
10251 }
10252
10253 DUK_ASSERT(ncont <= blen);
10254 clen = blen - ncont;
10255 DUK_ASSERT(clen <= blen);
10256 return clen;
10257}
10258#else /* DUK_USE_PREFER_SIZE */
10259/* This seems like a good overall approach. Fast path for ASCII in 4 byte
10260 * blocks.
10261 */
10263 const duk_uint8_t *p;
10264 const duk_uint8_t *p_end;
10265 const duk_uint32_t *p32_end;
10266 const duk_uint32_t *p32;
10267 duk_size_t ncont;
10268 duk_size_t clen;
10269
10270 ncont = 0; /* number of continuation (non-initial) bytes in [0x80,0xbf] */
10271 p = data;
10272 p_end = data + blen;
10273 if (blen < 16) {
10274 goto skip_fastpath;
10275 }
10276
10277 /* Align 'p' to 4; the input data may have arbitrary alignment.
10278 * End of string check not needed because blen >= 16.
10279 */
10280 while (((duk_size_t) (const void *) p) & 0x03U) {
10281 duk_uint8_t x;
10282 x = *p++;
10283 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10284 ncont++;
10285 }
10286 }
10287
10288 /* Full, aligned 4-byte reads. */
10289 p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
10290 p32 = (const duk_uint32_t *) (const void *) p;
10291 while (p32 != (const duk_uint32_t *) p32_end) {
10292 duk_uint32_t x;
10293 x = *p32++;
10294 if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
10295 ; /* ASCII fast path */
10296 } else {
10297 /* Flip highest bit of each byte which changes
10298 * the bit pattern 10xxxxxx into 00xxxxxx which
10299 * allows an easy bit mask test.
10300 */
10301 x ^= 0x80808080UL;
10302 if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
10303 ncont++;
10304 }
10305 if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
10306 ncont++;
10307 }
10308 if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
10309 ncont++;
10310 }
10311 if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
10312 ncont++;
10313 }
10314 }
10315 }
10316 p = (const duk_uint8_t *) p32;
10317 /* Fall through to handle the rest. */
10318
10319 skip_fastpath:
10320 while (p != p_end) {
10321 duk_uint8_t x;
10322 x = *p++;
10323 if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10324 ncont++;
10325 }
10327
10328 DUK_ASSERT(ncont <= blen);
10329 clen = blen - ncont;
10330 DUK_ASSERT(clen <= blen);
10331 return clen;
10332}
10333#endif /* DUK_USE_PREFER_SIZE */
10334
10335/*
10336 * Unicode range matcher
10337 *
10338 * Matches a codepoint against a packed bitstream of character ranges.
10339 * Used for slow path Unicode matching.
10340 */
10341
10342/* Must match src/extract_chars.py, generate_match_table3(). */
10344 duk_uint32_t t;
10345
10346 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
10347 if (t <= 0x0eU) {
10348 return t;
10349 }
10350 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
10351 if (t <= 0xfdU) {
10352 return t + 0x0f;
10353 }
10354 if (t == 0xfeU) {
10355 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
10356 return t + 0x0fU + 0xfeU;
10357 } else {
10358 t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
10359 return t + 0x0fU + 0xfeU + 0x1000UL;
10360 }
10361}
10362
10363DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
10364 duk_bitdecoder_ctx bd_ctx;
10365 duk_codepoint_t prev_re;
10366
10367 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
10368 bd_ctx.data = (const duk_uint8_t *) unitab;
10369 bd_ctx.length = (duk_size_t) unilen;
10370
10371 prev_re = 0;
10372 for (;;) {
10373 duk_codepoint_t r1, r2;
10374 r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10375 if (r1 == 0) {
10376 break;
10377 }
10378 r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10379
10380 r1 = prev_re + r1;
10381 r2 = r1 + r2;
10382 prev_re = r2;
10384 /* [r1,r2] is the range */
10385
10386 DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
10387 (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
10388 if (cp >= r1 && cp <= r2) {
10389 return 1;
10390 }
10391 }
10392
10393 return 0;
10394}
10395
10396/*
10397 * "WhiteSpace" production check.
10398 */
10399
10401 /*
10402 * E5 Section 7.2 specifies six characters specifically as
10403 * white space:
10404 *
10405 * 0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
10406 * 000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
10407 * 000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
10408 * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
10409 * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
10410 * FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
10411 *
10412 * It also specifies any Unicode category 'Zs' characters as white
10413 * space. These can be extracted with the "src/extract_chars.py" script.
10414 * Current result:
10415 *
10416 * RAW OUTPUT:
10417 * ===========
10418 * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
10419 * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
10420 * 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
10421 * 180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
10422 * 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
10423 * 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
10424 * 2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10425 * 2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10426 * 2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10427 * 2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10428 * 2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10429 * 2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
10430 * 2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10431 * 2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10432 * 200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10433 * 202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
10434 * 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10435 * 3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
10436 *
10437 * RANGES:
10438 * =======
10439 * 0x0020
10440 * 0x00a0
10441 * 0x1680
10442 * 0x180e
10443 * 0x2000 ... 0x200a
10444 * 0x202f
10445 * 0x205f
10446 * 0x3000
10447 *
10448 * A manual decoder (below) is probably most compact for this.
10449 */
10450
10453
10454 /* cp == -1 (EOF) never matches and causes return value 0 */
10455
10456 lo = (duk_uint_fast8_t) (cp & 0xff);
10457 hi = (duk_uint_fast32_t) (cp >> 8); /* does not fit into an uchar */
10458
10459 if (hi == 0x0000UL) {
10460 if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
10461 lo == 0x20U || lo == 0xa0U) {
10462 return 1;
10464 } else if (hi == 0x0020UL) {
10465 if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
10466 return 1;
10467 }
10468 } else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
10469 cp == 0xfeffL) {
10470 return 1;
10471 }
10472
10473 return 0;
10474}
10475
10476/*
10477 * "LineTerminator" production check.
10478 */
10479
10481 /*
10482 * E5 Section 7.3
10484 * A LineTerminatorSequence essentially merges <CR> <LF> sequences
10485 * into a single line terminator. This must be handled by the caller.
10486 */
10487
10488 if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
10489 cp == 0x2029L) {
10490 return 1;
10491 }
10492
10493 return 0;
10494}
10495
10496/*
10497 * "IdentifierStart" production check.
10498 */
10499
10501 /*
10502 * E5 Section 7.6:
10503 *
10504 * IdentifierStart:
10505 * UnicodeLetter
10506 * $
10507 * _
10508 * \ UnicodeEscapeSequence
10509 *
10510 * IdentifierStart production has one multi-character production:
10511 *
10512 * \ UnicodeEscapeSequence
10513 *
10514 * The '\' character is -not- matched by this function. Rather, the caller
10515 * should decode the escape and then call this function to check whether the
10516 * decoded character is acceptable (see discussion in E5 Section 7.6).
10517 *
10518 * The "UnicodeLetter" alternative of the production allows letters
10519 * from various Unicode categories. These can be extracted with the
10520 * "src/extract_chars.py" script.
10521 *
10522 * Because the result has hundreds of Unicode codepoint ranges, matching
10523 * for any values >= 0x80 are done using a very slow range-by-range scan
10524 * and a packed range format.
10525 *
10526 * The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
10527 * it matters the most. The ASCII related ranges of IdentifierStart are:
10528 *
10529 * 0x0041 ... 0x005a ['A' ... 'Z']
10530 * 0x0061 ... 0x007a ['a' ... 'z']
10531 * 0x0024 ['$']
10532 * 0x005f ['_']
10533 */
10534
10535 /* ASCII (and EOF) fast path -- quick accept and reject */
10536 if (cp <= 0x7fL) {
10537#if defined(DUK_USE_IDCHAR_FASTPATH)
10538 return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
10539#else
10540 if ((cp >= 'a' && cp <= 'z') ||
10541 (cp >= 'A' && cp <= 'Z') ||
10542 cp == '_' || cp == '$') {
10543 return 1;
10544 }
10545 return 0;
10546#endif
10547 }
10548
10549 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
10550
10551#ifdef DUK_USE_SOURCE_NONBMP
10554 (duk_codepoint_t) cp)) {
10555 return 1;
10556 }
10557 return 0;
10558#else
10559 if (cp < 0x10000L) {
10561 sizeof(duk_unicode_ids_noabmp),
10563 return 1;
10564 }
10565 return 0;
10566 } else {
10567 /* without explicit non-BMP support, assume non-BMP characters
10568 * are always accepted as identifier characters.
10569 */
10570 return 1;
10571 }
10572#endif
10573}
10574
10575/*
10576 * "IdentifierPart" production check.
10577 */
10578
10580 /*
10581 * E5 Section 7.6:
10582 *
10583 * IdentifierPart:
10584 * IdentifierStart
10585 * UnicodeCombiningMark
10586 * UnicodeDigit
10587 * UnicodeConnectorPunctuation
10588 * <ZWNJ> [U+200C]
10589 * <ZWJ> [U+200D]
10590 *
10591 * IdentifierPart production has one multi-character production
10592 * as part of its IdentifierStart alternative. The '\' character
10593 * of an escape sequence is not matched here, see discussion in
10594 * duk_unicode_is_identifier_start().
10595 *
10596 * To match non-ASCII characters (codepoints >= 0x80), a very slow
10597 * linear range-by-range scan is used. The codepoint is first compared
10598 * to the IdentifierStart ranges, and if it doesn't match, then to a
10599 * set consisting of code points in IdentifierPart but not in
10600 * IdentifierStart. This is done to keep the unicode range data small,
10601 * at the expense of speed.
10602 *
10603 * The ASCII fast path consists of:
10604 *
10605 * 0x0030 ... 0x0039 ['0' ... '9', UnicodeDigit]
10606 * 0x0041 ... 0x005a ['A' ... 'Z', IdentifierStart]
10607 * 0x0061 ... 0x007a ['a' ... 'z', IdentifierStart]
10608 * 0x0024 ['$', IdentifierStart]
10609 * 0x005f ['_', IdentifierStart and
10610 * UnicodeConnectorPunctuation]
10611 *
10612 * UnicodeCombiningMark has no code points <= 0x7f.
10613 *
10614 * The matching code reuses the "identifier start" tables, and then
10615 * consults a separate range set for characters in "identifier part"
10616 * but not in "identifier start". These can be extracted with the
10617 * "src/extract_chars.py" script.
10618 *
10619 * UnicodeCombiningMark -> categories Mn, Mc
10620 * UnicodeDigit -> categories Nd
10621 * UnicodeConnectorPunctuation -> categories Pc
10622 */
10623
10624 /* ASCII (and EOF) fast path -- quick accept and reject */
10625 if (cp <= 0x7fL) {
10626#if defined(DUK_USE_IDCHAR_FASTPATH)
10627 return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
10628#else
10629 if ((cp >= 'a' && cp <= 'z') ||
10630 (cp >= 'A' && cp <= 'Z') ||
10631 (cp >= '0' && cp <= '9') ||
10632 cp == '_' || cp == '$') {
10633 return 1;
10634 }
10635 return 0;
10636#endif
10637 }
10638
10639 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
10640
10641#ifdef DUK_USE_SOURCE_NONBMP
10643 sizeof(duk_unicode_ids_noa),
10644 (duk_codepoint_t) cp) ||
10647 (duk_codepoint_t) cp)) {
10648 return 1;
10649 }
10650 return 0;
10651#else
10652 if (cp < 0x10000L) {
10654 sizeof(duk_unicode_ids_noabmp),
10655 (duk_codepoint_t) cp) ||
10659 return 1;
10660 }
10661 return 0;
10662 } else {
10663 /* without explicit non-BMP support, assume non-BMP characters
10664 * are always accepted as identifier characters.
10665 */
10666 return 1;
10667 }
10668#endif
10669}
10670
10671/*
10672 * Unicode letter check.
10673 */
10674
10676 /*
10677 * Unicode letter is now taken to be the categories:
10678 *
10679 * Lu, Ll, Lt, Lm, Lo
10680 *
10681 * (Not sure if this is exactly correct.)
10682 *
10683 * The ASCII fast path consists of:
10684 *
10685 * 0x0041 ... 0x005a ['A' ... 'Z']
10686 * 0x0061 ... 0x007a ['a' ... 'z']
10687 */
10688
10689 /* ASCII (and EOF) fast path -- quick accept and reject */
10690 if (cp <= 0x7fL) {
10691 if ((cp >= 'a' && cp <= 'z') ||
10692 (cp >= 'A' && cp <= 'Z')) {
10693 return 1;
10694 }
10695 return 0;
10696 }
10697
10698 /* Non-ASCII slow path (range-by-range linear comparison), very slow */
10699
10700#ifdef DUK_USE_SOURCE_NONBMP
10702 sizeof(duk_unicode_ids_noa),
10703 (duk_codepoint_t) cp) &&
10706 (duk_codepoint_t) cp)) {
10707 return 1;
10708 }
10709 return 0;
10710#else
10711 if (cp < 0x10000L) {
10713 sizeof(duk_unicode_ids_noabmp),
10714 (duk_codepoint_t) cp) &&
10717 (duk_codepoint_t) cp)) {
10718 return 1;
10719 }
10720 return 0;
10721 } else {
10722 /* without explicit non-BMP support, assume non-BMP characters
10723 * are always accepted as letters.
10724 */
10725 return 1;
10726 }
10727#endif
10728}
10729
10730/*
10731 * Complex case conversion helper which decodes a bit-packed conversion
10732 * control stream generated by unicode/extract_caseconv.py. The conversion
10733 * is very slow because it runs through the conversion data in a linear
10734 * fashion to save space (which is why ASCII characters have a special
10735 * fast path before arriving here).
10736 *
10737 * The particular bit counts etc have been determined experimentally to
10738 * be small but still sufficient, and must match the Python script
10739 * (src/extract_caseconv.py).
10740 *
10741 * The return value is the case converted codepoint or -1 if the conversion
10742 * results in multiple characters (this is useful for regexp Canonicalization
10743 * operation). If 'buf' is not NULL, the result codepoint(s) are also
10744 * appended to the hbuffer.
10745 *
10746 * Context and locale specific rules must be checked before consulting
10747 * this function.
10748 */
10749
10753 duk_codepoint_t cp,
10754 duk_bitdecoder_ctx *bd_ctx) {
10755 duk_small_int_t skip = 0;
10758 duk_small_int_t count;
10759 duk_codepoint_t tmp_cp;
10760 duk_codepoint_t start_i;
10761 duk_codepoint_t start_o;
10762
10763 DUK_UNREF(thr);
10764 DUK_ASSERT(bd_ctx != NULL);
10765
10766 DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
10767
10768 /* range conversion with a "skip" */
10769 DUK_DDD(DUK_DDDPRINT("checking ranges"));
10770 for (;;) {
10771 skip++;
10772 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
10773 if (n == 0x3f) {
10774 /* end marker */
10775 break;
10776 }
10777 DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
10778
10779 while (n--) {
10780 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10781 start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10782 count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
10783 DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
10784 (long) start_i, (long) start_o, (long) count, (long) skip));
10785
10786 if (cp >= start_i) {
10787 tmp_cp = cp - start_i; /* always >= 0 */
10788 if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
10789 (tmp_cp % (duk_codepoint_t) skip) == 0) {
10790 DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
10791 cp = start_o + tmp_cp;
10792 goto single;
10793 }
10794 }
10795 }
10796 }
10797
10798 /* 1:1 conversion */
10799 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
10800 DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
10801 while (n--) {
10802 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10803 start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10804 DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
10805 if (cp == start_i) {
10806 DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
10807 cp = start_o;
10808 goto single;
10809 }
10810 }
10811
10812 /* complex, multicharacter conversion */
10813 n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
10814 DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
10815 while (n--) {
10816 start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10817 t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
10818 DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
10819 if (cp == start_i) {
10820 DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
10821 if (bw != NULL) {
10822 while (t--) {
10823 tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10824 DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
10825 }
10826 }
10827 return -1;
10828 } else {
10829 while (t--) {
10830 (void) duk_bd_decode(bd_ctx, 16);
10831 }
10832 }
10833 }
10834
10835 /* default: no change */
10836 DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
10837 /* fall through */
10838
10839 single:
10840 if (bw != NULL) {
10842 }
10843 return cp;
10844}
10845
10846/*
10847 * Case conversion helper, with context/local sensitivity.
10848 * For proper case conversion, one needs to know the character
10849 * and the preceding and following characters, as well as
10850 * locale/language.
10851 */
10852
10853/* XXX: add 'language' argument when locale/language sensitive rule
10854 * support added.
10855 */
10859 duk_codepoint_t cp,
10860 duk_codepoint_t prev,
10862 duk_bool_t uppercase) {
10863 duk_bitdecoder_ctx bd_ctx;
10864
10865 /* fast path for ASCII */
10866 if (cp < 0x80L) {
10867 /* XXX: there are language sensitive rules for the ASCII range.
10868 * If/when language/locale support is implemented, they need to
10869 * be implemented here for the fast path. There are no context
10870 * sensitive rules for ASCII range.
10871 */
10872
10873 if (uppercase) {
10874 if (cp >= 'a' && cp <= 'z') {
10875 cp = cp - 'a' + 'A';
10876 }
10877 } else {
10878 if (cp >= 'A' && cp <= 'Z') {
10879 cp = cp - 'A' + 'a';
10880 }
10881 }
10882
10883 if (bw != NULL) {
10884 DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
10885 }
10886 return cp;
10887 }
10888
10889 /* context and locale specific rules which cannot currently be represented
10890 * in the caseconv bitstream: hardcoded rules in C
10891 */
10892 if (uppercase) {
10893 /* XXX: turkish / azeri */
10894 } else {
10895 /*
10896 * Final sigma context specific rule. This is a rather tricky
10897 * rule and this handling is probably not 100% correct now.
10898 * The rule is not locale/language specific so it is supported.
10899 */
10900
10901 if (cp == 0x03a3L && /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
10902 duk_unicode_is_letter(prev) && /* prev exists and is not a letter */
10903 !duk_unicode_is_letter(next)) { /* next does not exist or next is not a letter */
10904 /* Capital sigma occurred at "end of word", lowercase to
10905 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA. Otherwise
10906 * fall through and let the normal rules lowercase it to
10907 * U+03C3 = GREEK SMALL LETTER SIGMA.
10908 */
10909 cp = 0x03c2L;
10910 goto singlechar;
10911 }
10912
10913 /* XXX: lithuanian not implemented */
10914 /* XXX: lithuanian, explicit dot rules */
10915 /* XXX: turkish / azeri, lowercase rules */
10916 }
10917
10918 /* 1:1 or special conversions, but not locale/context specific: script generated rules */
10919 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
10920 if (uppercase) {
10921 bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
10922 bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
10923 } else {
10924 bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
10925 bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
10926 }
10927 return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
10928
10929 singlechar:
10930 if (bw != NULL) {
10932 }
10933 return cp;
10934
10935 /* unused now, not needed until Turkish/Azeri */
10936#if 0
10937 nochar:
10938 return -1;
10939#endif
10940}
10941
10942/*
10943 * Replace valstack top with case converted version.
10944 */
10945
10947 duk_context *ctx = (duk_context *) thr;
10948 duk_hstring *h_input;
10949 duk_bufwriter_ctx bw_alloc;
10951 const duk_uint8_t *p, *p_start, *p_end;
10952 duk_codepoint_t prev, curr, next;
10953
10954 h_input = duk_require_hstring(ctx, -1);
10955 DUK_ASSERT(h_input != NULL);
10956
10957 bw = &bw_alloc;
10959
10960 /* [ ... input buffer ] */
10961
10962 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
10963 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
10964 p = p_start;
10965
10966 prev = -1; DUK_UNREF(prev);
10967 curr = -1;
10968 next = -1;
10969 for (;;) {
10970 prev = curr;
10971 curr = next;
10972 next = -1;
10973 if (p < p_end) {
10974 next = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
10975 } else {
10976 /* end of input and last char has been processed */
10977 if (curr < 0) {
10978 break;
10979 }
10980 }
10981
10982 /* on first round, skip */
10983 if (curr >= 0) {
10984 /* XXX: could add a fast path to process chunks of input codepoints,
10985 * but relative benefit would be quite small.
10986 */
10987
10988 /* Ensure space for maximum multi-character result; estimate is overkill. */
10990
10992 bw,
10993 (duk_codepoint_t) curr,
10994 prev,
10995 next,
10996 uppercase);
10998 }
10999
11000 DUK_BW_COMPACT(thr, bw);
11001 duk_to_string(ctx, -1); /* invalidates h_buf pointer */
11002 duk_remove(ctx, -2);
11003}
11004
11005#ifdef DUK_USE_REGEXP_SUPPORT
11006
11007/*
11008 * Canonicalize() abstract operation needed for canonicalization of individual
11009 * codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
11010 * Note that codepoints are canonicalized one character at a time, so no context
11011 * specific rules can apply. Locale specific rules can apply, though.
11012 */
11013
11015#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
11016 /* Fast canonicalization lookup at the cost of 128kB footprint. */
11017 DUK_ASSERT(cp >= 0);
11018 DUK_UNREF(thr);
11019 if (DUK_LIKELY(cp < 0x10000L)) {
11020 return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
11021 }
11022 return cp;
11023#else /* DUK_USE_REGEXP_CANON_WORKAROUND */
11025
11027 NULL, /* NULL is allowed, no output */
11028 cp, /* curr char */
11029 -1, /* prev char */
11030 -1, /* next char */
11031 1); /* uppercase */
11033 if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
11034 /* multiple codepoint conversion or non-ASCII mapped to ASCII
11035 * --> leave as is.
11036 */
11037 return cp;
11038 }
11039
11040 return y;
11041#endif /* DUK_USE_REGEXP_CANON_WORKAROUND */
11042}
11043
11044/*
11045 * E5 Section 15.10.2.6 "IsWordChar" abstract operation. Assume
11046 * x < 0 for characters read outside the string.
11047 */
11048
11050 /*
11051 * Note: the description in E5 Section 15.10.2.6 has a typo, it
11052 * contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
11053 */
11054 if ((x >= '0' && x <= '9') ||
11055 (x >= 'a' && x <= 'z') ||
11056 (x >= 'A' && x <= 'Z') ||
11057 (x == '_')) {
11058 return 1;
11059 }
11060 return 0;
11061}
11062
11063/*
11064 * Regexp range tables
11065 */
11066
11067/* exposed because lexer needs these too */
11068DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
11069 (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11070};
11071DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
11072 (duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
11073 (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
11074 (duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
11075 (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
11076 (duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
11077 (duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
11078 (duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
11079 (duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
11080 (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
11081 (duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
11082 (duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
11083};
11084DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
11085 (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11086 (duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
11087 (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
11088 (duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
11089};
11090DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
11091 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11092 (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
11093};
11094DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
11095 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
11096 (duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
11097 (duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
11098 (duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
11099 (duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
11100 (duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
11101 (duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
11102 (duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
11103 (duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
11104 (duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
11105 (duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
11106 (duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
11107};
11108DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
11109 (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11110 (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
11111 (duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
11112 (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
11113 (duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
11114};
11115
11116#endif /* DUK_USE_REGEXP_SUPPORT */
11117#line 1 "duk_util_misc.c"
11118/*
11119 * Misc util stuff
11120 */
11121
11122/* include removed: duk_internal.h */
11123
11125 * Lowercase digits for radix values 2 to 36. Also doubles as lowercase
11126 * hex nybble table.
11127 */
11128
11129DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
11139};
11140
11141DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
11146};
11147
11148/*
11149 * Table for hex decoding ASCII hex digits
11150 */
11151
11152DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
11153 /* -1 if invalid */
11154 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
11155 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
11156 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
11157 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
11158 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
11159 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
11160 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
11161 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
11162 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
11163 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
11164 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
11165 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
11166 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
11167 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
11168 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
11169 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
11170};
11171
11172#if defined(DUK_USE_HEX_FASTPATH)
11173/* Preshifted << 4. Must use 16-bit entry to allow negative value signaling. */
11174DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
11175 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
11176 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
11177 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
11178 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
11179 -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
11180 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
11181 -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
11182 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
11183 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
11184 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
11185 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
11186 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
11187 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
11188 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
11189 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
11190 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
11191};
11192#endif
11194/*
11195 * Table for hex encoding bytes
11196 */
11197
11198#if defined(DUK_USE_HEX_FASTPATH)
11199/* Lookup to encode one byte directly into 2 characters:
11200 *
11201 * def genhextab(bswap):
11202 * for i in xrange(256):
11203 * t = chr(i).encode('hex')
11204 * if bswap:
11205 * t = t[1] + t[0]
11206 * print('0x' + t.encode('hex') + 'U')
11207 * print('big endian'); genhextab(False)
11208 * print('little endian'); genhextab(True)
11209*/
11210DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
11211#if defined(DUK_USE_INTEGER_BE)
11212 0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
11213 0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
11214 0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
11215 0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
11216 0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
11217 0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
11218 0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
11219 0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
11220 0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
11221 0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
11222 0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
11223 0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
11224 0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
11225 0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
11226 0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
11227 0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
11228 0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
11229 0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
11230 0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
11231 0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
11232 0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
11233 0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
11234 0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
11235 0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
11236 0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
11237 0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
11238 0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
11239 0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
11240 0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
11241 0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
11242 0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
11243 0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
11244#else /* DUK_USE_INTEGER_BE */
11245 0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
11246 0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
11247 0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
11248 0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
11249 0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
11250 0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
11251 0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
11252 0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
11253 0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
11254 0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
11255 0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
11256 0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
11257 0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
11258 0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
11259 0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
11260 0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
11261 0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
11262 0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
11263 0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
11264 0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
11265 0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
11266 0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
11267 0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
11268 0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
11269 0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
11270 0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
11271 0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
11272 0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
11273 0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
11274 0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
11275 0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
11276 0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
11277#endif /* DUK_USE_INTEGER_BE */
11278};
11279#endif /* DUK_USE_HEX_FASTPATH */
11280
11281/*
11282 * Table for base-64 encoding
11283 */
11284
11285#if defined(DUK_USE_BASE64_FASTPATH)
11286DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {
11287 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* A...P */
11288 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, /* Q...f */
11289 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, /* g...v */
11290 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f /* w.../ */
11291};
11292#endif /* DUK_USE_BASE64_FASTPATH */
11293
11294/*
11295 * Table for base-64 decoding
11296 */
11297
11298#if defined(DUK_USE_BASE64_FASTPATH)
11299DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
11300 /* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */
11301 -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, /* 0x00...0x0f */
11302 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10...0x1f */
11303 -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20...0x2f */
11304 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, /* 0x30...0x3f */
11305 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */
11306 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50...0x5f */
11307 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */
11308 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70...0x7f */
11309 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80...0x8f */
11310 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90...0x9f */
11311 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0...0xaf */
11312 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0...0xbf */
11313 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0...0xcf */
11314 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0...0xdf */
11315 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0...0xef */
11316 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0...0xff */
11317};
11318#endif /* DUK_USE_BASE64_FASTPATH */
11319
11320/*
11321 * Arbitrary byteswap for potentially unaligned values
11322 *
11323 * Used to byteswap pointers e.g. in debugger code.
11324 */
11325
11326#if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
11327DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
11328 duk_uint8_t tmp;
11329 duk_uint8_t *q = p + len - 1;
11330
11331 while (p - q < 0) {
11332 tmp = *p;
11333 *p = *q;
11334 *q = tmp;
11335 p++;
11336 q--;
11337 }
11338}
11339#endif
11340#line 1 "duk_util_hashprime.c"
11341/*
11342 * Round a number upwards to a prime (not usually the nearest one).
11343 *
11344 * Uses a table of successive 32-bit primes whose ratio is roughly
11345 * constant. This keeps the relative upwards 'rounding error' bounded
11346 * and the data size small. A simple 'predict-correct' compression is
11347 * used to compress primes to one byte per prime. See genhashsizes.py
11348 * for details.
11349 *
11350 * The minimum prime returned here must be coordinated with the possible
11351 * probe sequence steps in duk_hobject and duk_heap stringtable.
11352 */
11353
11354/* include removed: duk_internal.h */
11355
11356/* Awkward inclusion condition: drop out of compilation if not needed by any
11357 * call site: object hash part or probing stringtable.
11358 */
11359#if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
11360
11361/* hash size ratio goal, must match genhashsizes.py */
11362#define DUK__HASH_SIZE_RATIO 1177 /* floor(1.15 * (1 << 10)) */
11364/* prediction corrections for prime list (see genhashsizes.py) */
11365DUK_LOCAL const duk_int8_t duk__hash_size_corrections[] = {
11366 17, /* minimum prime */
11367 4, 3, 4, 1, 4, 1, 1, 2, 2, 2, 2, 1, 6, 6, 9, 5, 1, 2, 2, 5, 1, 3, 3, 3,
11368 5, 4, 4, 2, 4, 8, 3, 4, 23, 2, 4, 7, 8, 11, 2, 12, 15, 10, 1, 1, 5, 1, 5,
11369 8, 9, 17, 14, 10, 7, 5, 2, 46, 21, 1, 9, 9, 4, 4, 10, 23, 36, 6, 20, 29,
11370 18, 6, 19, 21, 16, 11, 5, 5, 48, 9, 1, 39, 14, 8, 4, 29, 9, 1, 15, 48, 12,
11371 22, 6, 15, 27, 4, 2, 17, 28, 8, 9, 4, 5, 8, 3, 3, 8, 37, 11, 15, 8, 30,
11372 43, 6, 33, 41, 5, 20, 32, 41, 38, 24, 77, 14, 19, 11, 4, 35, 18, 19, 41,
11373 10, 23, 16, 9, 2,
11374 -1
11375};
11376
11377/* probe steps (see genhashsizes.py), currently assumed to be 32 entries long
11378 * (DUK_UTIL_GET_HASH_PROBE_STEP macro).
11379 */
11380DUK_INTERNAL duk_uint8_t duk_util_probe_steps[32] = {
11381 2, 3, 5, 7, 11, 13, 19, 31, 41, 47, 59, 67, 73, 79, 89, 101, 103, 107,
11382 109, 127, 137, 139, 149, 157, 163, 167, 173, 181, 191, 193, 197, 199
11383};
11384
11385DUK_INTERNAL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) {
11386 const duk_int8_t *p = duk__hash_size_corrections;
11387 duk_uint32_t curr;
11388
11389 curr = (duk_uint32_t) *p++;
11390 for (;;) {
11392 if (t < 0) {
11393 /* may happen if size is very close to 2^32-1 */
11394 break;
11395 }
11396
11397 /* prediction: portable variant using doubles if 64-bit values not available */
11398#ifdef DUK_USE_64BIT_OPS
11399 curr = (duk_uint32_t) ((((duk_uint64_t) curr) * ((duk_uint64_t) DUK__HASH_SIZE_RATIO)) >> 10);
11400#else
11401 /* 32-bit x 11-bit = 43-bit, fits accurately into a double */
11402 curr = (duk_uint32_t) DUK_FLOOR(((double) curr) * ((double) DUK__HASH_SIZE_RATIO) / 1024.0);
11403#endif
11404
11405 /* correction */
11406 curr += t;
11407
11408 DUK_DDD(DUK_DDDPRINT("size=%ld, curr=%ld", (long) size, (long) curr));
11409
11410 if (curr >= size) {
11411 return curr;
11412 }
11413 }
11414 return 0;
11415}
11416
11417#endif /* DUK_USE_HOBJECT_HASH_PART || DUK_USE_STRTAB_PROBE */
11418#line 1 "duk_hobject_class.c"
11419/*
11420 * Hobject Ecmascript [[Class]].
11421 */
11422
11423/* include removed: duk_internal.h */
11424
11425#if (DUK_STRIDX_UC_ARGUMENTS > 255)
11426#error constant too large
11427#endif
11428#if (DUK_STRIDX_ARRAY > 255)
11429#error constant too large
11430#endif
11431#if (DUK_STRIDX_UC_BOOLEAN > 255)
11432#error constant too large
11433#endif
11434#if (DUK_STRIDX_DATE > 255)
11435#error constant too large
11436#endif
11437#if (DUK_STRIDX_UC_ERROR > 255)
11438#error constant too large
11439#endif
11440#if (DUK_STRIDX_UC_FUNCTION > 255)
11441#error constant too large
11442#endif
11443#if (DUK_STRIDX_JSON > 255)
11444#error constant too large
11445#endif
11446#if (DUK_STRIDX_MATH > 255)
11447#error constant too large
11448#endif
11449#if (DUK_STRIDX_UC_NUMBER > 255)
11450#error constant too large
11451#endif
11452#if (DUK_STRIDX_UC_OBJECT > 255)
11453#error constant too large
11454#endif
11455#if (DUK_STRIDX_REG_EXP > 255)
11456#error constant too large
11457#endif
11458#if (DUK_STRIDX_UC_STRING > 255)
11459#error constant too large
11460#endif
11461#if (DUK_STRIDX_GLOBAL > 255)
11462#error constant too large
11463#endif
11464#if (DUK_STRIDX_OBJ_ENV > 255)
11465#error constant too large
11466#endif
11467#if (DUK_STRIDX_DEC_ENV > 255)
11468#error constant too large
11469#endif
11470#if (DUK_STRIDX_UC_BUFFER > 255)
11471#error constant too large
11472#endif
11473#if (DUK_STRIDX_UC_POINTER > 255)
11474#error constant too large
11475#endif
11476#if (DUK_STRIDX_UC_THREAD > 255)
11477#error constant too large
11478#endif
11479#if (DUK_STRIDX_ARRAY_BUFFER > 255)
11480#error constant too large
11481#endif
11482#if (DUK_STRIDX_DATA_VIEW > 255)
11483#error constant too large
11484#endif
11485#if (DUK_STRIDX_INT8_ARRAY > 255)
11486#error constant too large
11487#endif
11488#if (DUK_STRIDX_UINT8_ARRAY > 255)
11489#error constant too large
11490#endif
11491#if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
11492#error constant too large
11493#endif
11494#if (DUK_STRIDX_INT16_ARRAY > 255)
11495#error constant too large
11496#endif
11497#if (DUK_STRIDX_UINT16_ARRAY > 255)
11498#error constant too large
11499#endif
11500#if (DUK_STRIDX_INT32_ARRAY > 255)
11501#error constant too large
11502#endif
11503#if (DUK_STRIDX_UINT32_ARRAY > 255)
11504#error constant too large
11505#endif
11506#if (DUK_STRIDX_FLOAT32_ARRAY > 255)
11507#error constant too large
11508#endif
11509#if (DUK_STRIDX_FLOAT64_ARRAY > 255)
11510#error constant too large
11511#endif
11512#if (DUK_STRIDX_EMPTY_STRING > 255)
11513#error constant too large
11514#endif
11515
11516/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
11517DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
11518 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
11548 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
11549 DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
11550};
11551#line 1 "duk_alloc_default.c"
11552/*
11553 * Default allocation functions.
11555 * Assumes behavior such as malloc allowing zero size, yielding
11556 * a NULL or a unique pointer which is a no-op for free.
11557 */
11558
11559/* include removed: duk_internal.h */
11560
11561#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
11562DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
11563 void *res;
11564 DUK_UNREF(udata);
11565 res = DUK_ANSI_MALLOC(size);
11566 DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
11567 (unsigned long) size, (void *) res));
11568 return res;
11569}
11570
11571DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
11572 void *res;
11573 DUK_UNREF(udata);
11574 res = DUK_ANSI_REALLOC(ptr, newsize);
11575 DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
11576 (void *) ptr, (unsigned long) newsize, (void *) res));
11577 return res;
11578}
11579
11580DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
11581 DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
11582 DUK_UNREF(udata);
11583 DUK_ANSI_FREE(ptr);
11584}
11585#endif /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
11586#line 1 "duk_api_buffer.c"
11587/*
11588 * Buffer
11589 */
11590
11591/* include removed: duk_internal.h */
11592
11594 duk_hthread *thr = (duk_hthread *) ctx;
11596
11598
11600 DUK_ASSERT(h != NULL);
11601
11604 }
11605
11606 /* maximum size check is handled by callee */
11607 duk_hbuffer_resize(thr, h, new_size);
11608
11609 return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
11610}
11611
11613 duk_hthread *thr = (duk_hthread *) ctx;
11615 void *ptr;
11616 duk_size_t sz;
11617
11618 DUK_ASSERT(ctx != NULL);
11619
11621 DUK_ASSERT(h != NULL);
11622
11625 }
11627 /* Forget the previous allocation, setting size to 0 and alloc to
11628 * NULL. Caller is responsible for freeing the previous allocation.
11629 * Getting the allocation and clearing it is done in the same API
11630 * call to avoid any chance of a realloc.
11631 */
11634 if (out_size) {
11635 *out_size = sz;
11636 }
11639
11640 return ptr;
11641}
11642
11644 duk_hthread *thr = (duk_hthread *) ctx;
11646
11647 DUK_ASSERT(ctx != NULL);
11648
11650 DUK_ASSERT(h != NULL);
11651
11652 if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
11654 }
11656
11659}
11660#line 1 "duk_api_bytecode.c"
11662 * Bytecode dump/load
11664 * The bytecode load primitive is more important performance-wise than the
11665 * dump primitive.
11666 *
11667 * Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
11668 * memory safe for invalid arguments - caller beware! There's little point
11669 * in trying to achieve memory safety unless bytecode instructions are also
11670 * validated which is not easy to do with indirect register references etc.
11671 */
11672
11673/* include removed: duk_internal.h */
11674
11675#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
11676
11677#define DUK__SER_MARKER 0xff
11678#define DUK__SER_VERSION 0x00
11679#define DUK__SER_STRING 0x00
11680#define DUK__SER_NUMBER 0x01
11681#define DUK__BYTECODE_INITIAL_ALLOC 256
11682
11683/*
11684 * Dump/load helpers, xxx_raw() helpers do no buffer checks
11685 */
11686
11687DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) {
11688 duk_uint32_t len;
11689
11690 len = DUK_RAW_READ_U32_BE(p);
11691 duk_push_lstring(ctx, (const char *) p, len);
11692 p += len;
11693 return p;
11694}
11695
11696DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) {
11697 duk_uint32_t len;
11698 duk_uint8_t *buf;
11699
11700 len = DUK_RAW_READ_U32_BE(p);
11701 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
11702 DUK_ASSERT(buf != NULL);
11703 DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);
11704 p += len;
11705 return p;
11706}
11707
11708DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
11709 duk_size_t len;
11710 duk_uint32_t tmp32;
11711
11712 DUK_ASSERT(h != NULL);
11713
11714 len = DUK_HSTRING_GET_BYTELEN(h);
11715 DUK_ASSERT(len <= 0xffffffffUL); /* string limits */
11716 tmp32 = (duk_uint32_t) len;
11717 DUK_RAW_WRITE_U32_BE(p, tmp32);
11718 DUK_MEMCPY((void *) p,
11719 (const void *) DUK_HSTRING_GET_DATA(h),
11720 len);
11721 p += len;
11722 return p;
11723}
11724
11725DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
11726 duk_size_t len;
11727 duk_uint32_t tmp32;
11728
11729 DUK_ASSERT(thr != NULL);
11730 DUK_ASSERT(h != NULL);
11731 DUK_UNREF(thr);
11732
11733 len = DUK_HBUFFER_GET_SIZE(h);
11734 DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */
11735 tmp32 = (duk_uint32_t) len;
11736 DUK_RAW_WRITE_U32_BE(p, tmp32);
11737 DUK_MEMCPY((void *) p,
11738 (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
11739 len);
11740 p += len;
11741 return p;
11742}
11743
11744DUK_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) {
11746 duk_tval *tv;
11747
11749 if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
11750 h_str = DUK_TVAL_GET_STRING(tv);
11751 DUK_ASSERT(h_str != NULL);
11752 } else {
11754 DUK_ASSERT(h_str != NULL);
11755 }
11756 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11757 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), p);
11758 p = duk__dump_hstring_raw(p, h_str);
11759 return p;
11760}
11761
11762DUK_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) {
11764
11766 if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
11767 duk_hbuffer *h_buf;
11768 h_buf = DUK_TVAL_GET_BUFFER(tv);
11769 DUK_ASSERT(h_buf != NULL);
11770 DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11771 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HBUFFER_GET_SIZE(h_buf), p);
11772 p = duk__dump_hbuffer_raw(thr, p, h_buf);
11773 } else {
11774 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11776 }
11777 return p;
11779
11780DUK_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) {
11781 duk_tval *tv;
11782 duk_uint32_t val;
11783
11785 if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
11786 val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
11787 } else {
11788 val = def_value;
11789 }
11790 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11791 DUK_RAW_WRITE_U32_BE(p, val);
11792 return p;
11793}
11794
11795DUK_LOCAL duk_uint8_t *duk__dump_varmap(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 _Varmap only has own properties so walk property
11807 * table directly. We also know _Varmap is dense and all
11808 * values are numbers; assert for these. GC and finalizers
11809 * shouldn't affect _Varmap so side effects should be fine.
11810 */
11811 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
11812 duk_hstring *key;
11813 duk_tval *tv_val;
11814 duk_uint32_t val;
11815
11816 key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
11817 DUK_ASSERT(key != NULL); /* _Varmap is dense */
11819 tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
11820 DUK_ASSERT(tv_val != NULL);
11821 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */
11822#if defined(DUK_USE_FASTINT)
11823 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
11824 DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */
11825 val = DUK_TVAL_GET_FASTINT_U32(tv_val);
11826#else
11827 val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
11828#endif
11829
11830 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11831 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(key) + 4, p);
11832 p = duk__dump_hstring_raw(p, key);
11833 DUK_RAW_WRITE_U32_BE(p, val);
11834 }
11835 }
11836 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11837 DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Varmap */
11838 return p;
11839}
11840
11841DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
11842 duk_tval *tv;
11843
11845 if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
11846 duk_hobject *h;
11848
11849 h = DUK_TVAL_GET_OBJECT(tv);
11850 DUK_ASSERT(h != NULL);
11851
11852 /* We know _Formals is dense and all entries will be in the
11853 * array part. GC and finalizers shouldn't affect _Formals
11854 * so side effects should be fine.
11855 */
11856 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
11857 duk_tval *tv_val;
11858 duk_hstring *varname;
11859
11860 tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i);
11861 DUK_ASSERT(tv_val != NULL);
11862 if (DUK_TVAL_IS_STRING(tv_val)) {
11863 /* Array is dense and contains only strings, but ASIZE may
11864 * be larger than used part and there are UNUSED entries.
11865 */
11866 varname = DUK_TVAL_GET_STRING(tv_val);
11867 DUK_ASSERT(varname != NULL);
11868
11869 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11870 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p);
11871 p = duk__dump_hstring_raw(p, varname);
11872 }
11873 }
11874 }
11875 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11876 DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Formals */
11877 return p;
11878}
11879
11880static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
11881 duk_hthread *thr;
11882 duk_tval *tv, *tv_end;
11883 duk_instr_t *ins, *ins_end;
11884 duk_hobject **fn, **fn_end;
11885 duk_hstring *h_str;
11886 duk_uint32_t count_instr;
11887 duk_uint32_t tmp32;
11888 duk_uint16_t tmp16;
11889 duk_double_t d;
11890
11891 thr = (duk_hthread *) ctx;
11892 DUK_UNREF(ctx);
11893 DUK_UNREF(thr);
11894
11895 DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
11896 "consts=[%p,%p[ (%ld bytes, %ld items), "
11897 "funcs=[%p,%p[ (%ld bytes, %ld items), "
11898 "code=[%p,%p[ (%ld bytes, %ld items)",
11899 (void *) func,
11900 (void *) p,
11901 (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func),
11902 (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func),
11905 (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func),
11906 (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func),
11907 (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(thr->heap, func),
11909 (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func),
11910 (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func),
11911 (long) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(thr->heap, func),
11912 (long) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func)));
11913
11914 DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */
11915 count_instr = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func);
11916 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr * 4, p);
11917
11918 /* Fixed header info. */
11919 tmp32 = count_instr;
11920 DUK_RAW_WRITE_U32_BE(p, tmp32);
11921 tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func);
11922 DUK_RAW_WRITE_U32_BE(p, tmp32);
11923 tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func);
11924 DUK_RAW_WRITE_U32_BE(p, tmp32);
11925 tmp16 = func->nregs;
11926 DUK_RAW_WRITE_U16_BE(p, tmp16);
11927 tmp16 = func->nargs;
11928 DUK_RAW_WRITE_U16_BE(p, tmp16);
11929#if defined(DUK_USE_DEBUGGER_SUPPORT)
11930 tmp32 = func->start_line;
11931 DUK_RAW_WRITE_U32_BE(p, tmp32);
11932 tmp32 = func->end_line;
11933 DUK_RAW_WRITE_U32_BE(p, tmp32);
11934#else
11937#endif
11938 tmp32 = ((duk_heaphdr *) func)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK;
11939 DUK_RAW_WRITE_U32_BE(p, tmp32);
11940
11941 /* Bytecode instructions: endian conversion needed unless
11942 * platform is big endian.
11943 */
11944 ins = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func);
11945 ins_end = DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func);
11946 DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
11947#if defined(DUK_USE_INTEGER_BE)
11948 DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));
11949 p += (size_t) (ins_end - ins);
11950#else
11951 while (ins != ins_end) {
11952 tmp32 = (duk_uint32_t) (*ins);
11953 DUK_RAW_WRITE_U32_BE(p, tmp32);
11954 ins++;
11955 }
11956#endif
11957
11958 /* Constants: variable size encoding. */
11960 tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func);
11961 while (tv != tv_end) {
11962 /* constants are strings or numbers now */
11964 DUK_TVAL_IS_NUMBER(tv));
11965
11966 if (DUK_TVAL_IS_STRING(tv)) {
11967 h_str = DUK_TVAL_GET_STRING(tv);
11968 DUK_ASSERT(h_str != NULL);
11969 DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
11970 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + DUK_HSTRING_GET_BYTELEN(h_str), p),
11971 *p++ = DUK__SER_STRING;
11972 p = duk__dump_hstring_raw(p, h_str);
11973 } else {
11975 p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p);
11976 *p++ = DUK__SER_NUMBER;
11977 d = DUK_TVAL_GET_NUMBER(tv);
11979 }
11980 tv++;
11981 }
11982
11983 /* Inner functions recursively. */
11985 fn_end = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func);
11986 while (fn != fn_end) {
11987 /* XXX: This causes recursion up to inner function depth
11988 * which is normally not an issue, e.g. mark-and-sweep uses
11989 * a recursion limiter to avoid C stack issues. Avoiding
11990 * this would mean some sort of a work list or just refusing
11991 * to serialize deep functions.
11992 */
11994 p = duk__dump_func(ctx, (duk_hcompiledfunction *) *fn, bw_ctx, p);
11995 fn++;
11996 }
11997
11998 /* Object extra properties.
11999 *
12000 * There are some difference between function templates and functions.
12001 * For example, function templates don't have .length and nargs is
12002 * normally used to instantiate the functions.
12003 */
12004
12005 p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
12006 p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
12007 p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
12008 p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
12009 p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
12010 p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
12011
12012 DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
12013
12014 return p;
12015}
12016
12017/* Load a function from bytecode. The function object returned here must
12018 * match what is created by duk_js_push_closure() with respect to its flags,
12019 * properties, etc.
12020 *
12021 * NOTE: there are intentionally no input buffer length / bound checks.
12022 * Adding them would be easy but wouldn't ensure memory safety as untrusted
12023 * or broken bytecode is unsafe during execution unless the opcodes themselves
12024 * are validated (which is quite complex, especially for indirect opcodes).
12025 */
12026
12027#define DUK__ASSERT_LEFT(n) do { \
12028 DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
12029 } while (0)
12030
12031static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end) {
12032 duk_hthread *thr;
12033 duk_hcompiledfunction *h_fun;
12034 duk_hbuffer *h_data;
12035 duk_size_t data_size;
12036 duk_uint32_t count_instr, count_const, count_funcs;
12037 duk_uint32_t n;
12038 duk_uint32_t tmp32;
12039 duk_small_uint_t const_type;
12040 duk_uint8_t *fun_data;
12041 duk_uint8_t *q;
12042 duk_idx_t idx_base;
12043 duk_tval *tv1;
12044 duk_uarridx_t arr_idx;
12045
12046 /* XXX: There's some overlap with duk_js_closure() here, but
12047 * seems difficult to share code. Ensure that the final function
12048 * looks the same as created by duk_js_closure().
12049 */
12050
12051 DUK_ASSERT(ctx != NULL);
12052 thr = (duk_hthread *) ctx;
12053
12054 DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
12055
12056 DUK__ASSERT_LEFT(3 * 4);
12057 count_instr = DUK_RAW_READ_U32_BE(p);
12058 count_const = DUK_RAW_READ_U32_BE(p);
12059 count_funcs = DUK_RAW_READ_U32_BE(p);
12060
12061 data_size = sizeof(duk_tval) * count_const +
12062 sizeof(duk_hobject *) * count_funcs +
12063 sizeof(duk_instr_t) * count_instr;
12064
12065 DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
12066 (long) count_instr, (long) count_const,
12067 (long) count_const, (long) data_size));
12068
12069 /* Value stack is used to ensure reachability of constants and
12070 * inner functions being loaded. Require enough space to handle
12071 * large functions correctly.
12072 */
12073 duk_require_stack(ctx, 2 + count_const + count_funcs);
12074 idx_base = duk_get_top(ctx);
12075
12076 /* Push function object, init flags etc. This must match
12077 * duk_js_push_closure() quite carefully.
12078 */
12080 h_fun = duk_get_hcompiledfunction(ctx, -1);
12081 DUK_ASSERT(h_fun != NULL);
12086
12087 h_fun->nregs = DUK_RAW_READ_U16_BE(p);
12088 h_fun->nargs = DUK_RAW_READ_U16_BE(p);
12089#if defined(DUK_USE_DEBUGGER_SUPPORT)
12090 h_fun->start_line = DUK_RAW_READ_U32_BE(p);
12091 h_fun->end_line = DUK_RAW_READ_U32_BE(p);
12092#else
12093 p += 8; /* skip line info */
12094#endif
12095
12096 /* duk_hcompiledfunction flags; quite version specific */
12097 tmp32 = DUK_RAW_READ_U32_BE(p);
12098 DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);
12099
12100 /* standard prototype */
12102
12103 /* assert just a few critical flags */
12112
12113 /* Create function 'data' buffer but don't attach it yet. */
12114 fun_data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, data_size);
12115 DUK_ASSERT(fun_data != NULL);
12116
12117 /* Load bytecode instructions. */
12118 DUK_ASSERT(sizeof(duk_instr_t) == 4);
12119 DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
12120#if defined(DUK_USE_INTEGER_BE)
12121 q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12122 DUK_MEMCPY((void *) q,
12123 (const void *) p,
12124 sizeof(duk_instr_t) * count_instr);
12125 p += sizeof(duk_instr_t) * count_instr;
12126#else
12127 q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12128 for (n = count_instr; n > 0; n--) {
12129 *((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
12130 q += sizeof(duk_instr_t);
12131 }
12132#endif
12133
12134 /* Load constants onto value stack but don't yet copy to buffer. */
12135 for (n = count_const; n > 0; n--) {
12137 const_type = DUK_RAW_READ_U8(p);
12138 switch (const_type) {
12139 case DUK__SER_STRING: {
12140 p = duk__load_string_raw(ctx, p);
12141 break;
12142 }
12143 case DUK__SER_NUMBER: {
12144 /* Important to do a fastint check so that constants are
12145 * properly read back as fastints.
12146 */
12147 duk_tval tv_tmp;
12148 duk_double_t val;
12150 val = DUK_RAW_READ_DOUBLE_BE(p);
12151 DUK_TVAL_SET_NUMBER_CHKFAST(&tv_tmp, val);
12152 duk_push_tval(ctx, &tv_tmp);
12153 break;
12154 }
12155 default: {
12156 goto format_error;
12157 }
12158 }
12159 }
12160
12161 /* Load inner functions to value stack, but don't yet copy to buffer. */
12162 for (n = count_funcs; n > 0; n--) {
12163 p = duk__load_func(ctx, p, p_end);
12164 if (p == NULL) {
12165 goto format_error;
12166 }
12167 }
12168
12169 /* With constants and inner functions on value stack, we can now
12170 * atomically finish the function 'data' buffer, bump refcounts,
12171 * etc.
12172 *
12173 * Here we take advantage of the value stack being just a duk_tval
12174 * array: we can just memcpy() the constants as long as we incref
12175 * them afterwards.
12176 */
12177
12178 h_data = (duk_hbuffer *) duk_get_hbuffer(ctx, idx_base + 1);
12179 DUK_ASSERT(h_data != NULL);
12181 DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_fun, h_data);
12182 DUK_HBUFFER_INCREF(thr, h_data);
12183
12184 tv1 = duk_get_tval(ctx, idx_base + 2); /* may be NULL if no constants or inner funcs */
12185 DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
12186
12187 q = fun_data;
12188 if (count_const > 0) {
12189 /* Explicit zero size check to avoid NULL 'tv1'. */
12190 DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
12191 for (n = count_const; n > 0; n--) {
12192 DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */
12193 q += sizeof(duk_tval);
12194 }
12195 tv1 += count_const;
12196 }
12197
12198 DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
12199 for (n = count_funcs; n > 0; n--) {
12200 duk_hobject *h_obj;
12201
12203 h_obj = DUK_TVAL_GET_OBJECT(tv1);
12204 DUK_ASSERT(h_obj != NULL);
12205 tv1++;
12206 DUK_HOBJECT_INCREF(thr, h_obj);
12207
12208 *((duk_hobject **) (void *) q) = h_obj;
12209 q += sizeof(duk_hobject *);
12210 }
12211
12212 DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
12213
12214 /* The function object is now reachable and refcounts are fine,
12215 * so we can pop off all the temporaries.
12216 */
12217 DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(ctx, idx_base)));
12218 duk_set_top(ctx, idx_base + 1);
12219
12220 /* Setup function properties. */
12221 tmp32 = DUK_RAW_READ_U32_BE(p);
12222 duk_push_u32(ctx, tmp32);
12224
12225 p = duk__load_string_raw(ctx, p);
12227 /* Original function instance/template had NAMEBINDING.
12228 * Must create a lexical environment on loading to allow
12229 * recursive functions like 'function foo() { foo(); }'.
12230 */
12232
12237 proto);
12238 duk_dup(ctx, -2); /* -> [ func funcname env funcname ] */
12239 duk_dup(ctx, idx_base); /* -> [ func funcname env funcname func ] */
12240 duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */
12242 /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
12243 * will be ignored anyway
12244 */
12245 }
12247
12248 p = duk__load_string_raw(ctx, p);
12250
12251 duk_push_object(ctx);
12252 duk_dup(ctx, -2);
12253 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */
12254 duk_compact(ctx, -1);
12256
12257 p = duk__load_buffer_raw(ctx, p);
12259
12260 duk_push_object(ctx); /* _Varmap */
12261 for (;;) {
12262 /* XXX: awkward */
12263 p = duk__load_string_raw(ctx, p);
12264 if (duk_get_length(ctx, -1) == 0) {
12265 duk_pop(ctx);
12266 break;
12267 }
12268 tmp32 = DUK_RAW_READ_U32_BE(p);
12269 duk_push_u32(ctx, tmp32);
12270 duk_put_prop(ctx, -3);
12271 }
12272 duk_compact(ctx, -1);
12274
12275 duk_push_array(ctx); /* _Formals */
12276 for (arr_idx = 0; ; arr_idx++) {
12277 /* XXX: awkward */
12278 p = duk__load_string_raw(ctx, p);
12279 if (duk_get_length(ctx, -1) == 0) {
12281 break;
12282 }
12283 duk_put_prop_index(ctx, -2, arr_idx);
12284 }
12285 duk_compact(ctx, -1);
12287
12288 /* Return with final function pushed on stack top. */
12289 DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, -1)));
12290 DUK_ASSERT_TOP(ctx, idx_base + 1);
12291 return p;
12292
12293 format_error:
12294 return NULL;
12295}
12296
12298 duk_hthread *thr;
12300 duk_bufwriter_ctx bw_ctx_alloc;
12301 duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
12302 duk_uint8_t *p;
12303
12304 DUK_ASSERT(ctx != NULL);
12305 thr = (duk_hthread *) ctx;
12306
12307 /* Bound functions don't have all properties so we'd either need to
12308 * lookup the non-bound target function or reject bound functions.
12309 * For now, bound functions are rejected.
12310 */
12311 func = duk_require_hcompiledfunction(ctx, -1);
12312 DUK_ASSERT(func != NULL);
12315 /* Estimating the result size beforehand would be costly, so
12316 * start with a reasonable size and extend as needed.
12317 */
12319 p = DUK_BW_GET_PTR(thr, bw_ctx);
12320 *p++ = DUK__SER_MARKER;
12321 *p++ = DUK__SER_VERSION;
12322 p = duk__dump_func(ctx, func, bw_ctx, p);
12323 DUK_BW_SET_PTR(thr, bw_ctx, p);
12324 DUK_BW_COMPACT(thr, bw_ctx);
12325
12326 DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1)));
12327
12328 duk_remove(ctx, -2); /* [ ... func buf ] -> [ ... buf ] */
12329}
12330
12332 duk_hthread *thr;
12333 duk_uint8_t *p_buf, *p, *p_end;
12334 duk_size_t sz;
12335
12336 DUK_ASSERT(ctx != NULL);
12337 thr = (duk_hthread *) ctx;
12338 DUK_UNREF(ctx);
12339
12340 p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz);
12341 DUK_ASSERT(p_buf != NULL);
12342
12343 /* The caller is responsible for being sure that bytecode being loaded
12344 * is valid and trusted. Invalid bytecode can cause memory unsafe
12345 * behavior directly during loading or later during bytecode execution
12346 * (instruction validation would be quite complex to implement).
12347 *
12348 * This signature check is the only sanity check for detecting
12349 * accidental invalid inputs. The initial 0xFF byte ensures no
12350 * ordinary string will be accepted by accident.
12351 */
12352 p = p_buf;
12353 p_end = p_buf + sz;
12354 if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) {
12355 goto format_error;
12356 }
12357 p += 2;
12358
12359 p = duk__load_func(ctx, p, p_end);
12360 if (p == NULL) {
12361 goto format_error;
12362 }
12363
12364 duk_remove(ctx, -2); /* [ ... buf func ] -> [ ... func ] */
12365 return;
12366
12367 format_error:
12369}
12370
12371#undef DUK__SER_MARKER
12372#undef DUK__SER_VERSION
12373#undef DUK__SER_STRING
12374#undef DUK__SER_NUMBER
12375#undef DUK__BYTECODE_INITIAL_ALLOC
12376
12377#else /* DUK_USE_BYTECODE_DUMP_SUPPORT */
12378
12381}
12382
12385}
12386
12387#endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */
12388#line 1 "duk_api_call.c"
12389/*
12390 * Calls.
12391 *
12392 * Protected variants should avoid ever throwing an error.
12393 */
12394
12395/* include removed: duk_internal.h */
12396
12397/* Prepare value stack for a method call through an object property.
12398 * May currently throw an error e.g. when getting the property.
12399 */
12400DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs) {
12402
12403 DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_index=%ld, nargs=%ld, stacktop=%ld",
12404 (long) normalized_obj_index, (long) nargs, (long) duk_get_top(ctx)));
12405
12406 /* [... key arg1 ... argN] */
12407
12408 /* duplicate key */
12409 duk_dup(ctx, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */
12410 duk_get_prop(ctx, normalized_obj_index);
12411
12412 DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
12413
12414 /* [... key arg1 ... argN func] */
12415
12416 duk_replace(ctx, -nargs - 2);
12417
12418 /* [... func arg1 ... argN] */
12419
12420 duk_dup(ctx, normalized_obj_index);
12421 duk_insert(ctx, -nargs - 1);
12422
12423 /* [... func this arg1 ... argN] */
12424}
12425
12426DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) {
12427 duk_hthread *thr = (duk_hthread *) ctx;
12428 duk_small_uint_t call_flags;
12429 duk_idx_t idx_func;
12430
12432 DUK_ASSERT(thr != NULL);
12433
12434 idx_func = duk_get_top(ctx) - nargs - 1;
12435 if (idx_func < 0 || nargs < 0) {
12436 /* note that we can't reliably pop anything here */
12438 }
12439
12440 /* XXX: awkward; we assume there is space for this, overwrite
12441 * directly instead?
12442 */
12443 duk_push_undefined(ctx);
12444 duk_insert(ctx, idx_func + 1);
12445
12446 call_flags = 0; /* not protected, respect reclimit, not constructor */
12447
12448 duk_handle_call_unprotected(thr, /* thread */
12449 nargs, /* num_stack_args */
12450 call_flags); /* call_flags */
12451}
12452
12454 duk_hthread *thr = (duk_hthread *) ctx;
12455 duk_small_uint_t call_flags;
12456 duk_idx_t idx_func;
12459 DUK_ASSERT(thr != NULL);
12460
12461 idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */
12462 if (idx_func < 0 || nargs < 0) {
12463 /* note that we can't reliably pop anything here */
12465 }
12466
12467 call_flags = 0; /* not protected, respect reclimit, not constructor */
12468
12469 duk_handle_call_unprotected(thr, /* thread */
12470 nargs, /* num_stack_args */
12471 call_flags); /* call_flags */
12472}
12473
12475 /*
12476 * XXX: if duk_handle_call() took values through indices, this could be
12477 * made much more sensible. However, duk_handle_call() needs to fudge
12478 * the 'this' and 'func' values to handle bound function chains, which
12479 * is now done "in-place", so this is not a trivial change.
12480 */
12481
12483
12484 obj_index = duk_require_normalize_index(ctx, obj_index); /* make absolute */
12485
12486 duk__call_prop_prep_stack(ctx, obj_index, nargs);
12487
12488 duk_call_method(ctx, nargs);
12489}
12490
12492 duk_hthread *thr = (duk_hthread *) ctx;
12493 duk_small_uint_t call_flags;
12494 duk_idx_t idx_func;
12495 duk_int_t rc;
12496
12498 DUK_ASSERT(thr != NULL);
12499
12500 idx_func = duk_get_top(ctx) - nargs - 1; /* must work for nargs <= 0 */
12501 if (idx_func < 0 || nargs < 0) {
12502 /* We can't reliably pop anything here because the stack input
12503 * shape is incorrect. So we throw an error; if the caller has
12504 * no catch point for this, a fatal error will occur. Another
12505 * alternative would be to just return an error. But then the
12506 * stack would be in an unknown state which might cause some
12507 * very hard to diagnose problems later on. Also note that even
12508 * if we did not throw an error here, the underlying call handler
12509 * might STILL throw an out-of-memory error or some other internal
12510 * fatal error.
12511 */
12513 return DUK_EXEC_ERROR; /* unreachable */
12514 }
12515
12516 /* awkward; we assume there is space for this */
12517 duk_push_undefined(ctx);
12518 duk_insert(ctx, idx_func + 1);
12519
12520 call_flags = 0; /* respect reclimit, not constructor */
12521
12522 rc = duk_handle_call_protected(thr, /* thread */
12523 nargs, /* num_stack_args */
12524 call_flags); /* call_flags */
12525
12526 return rc;
12527}
12528
12530 duk_hthread *thr = (duk_hthread *) ctx;
12531 duk_small_uint_t call_flags;
12532 duk_idx_t idx_func;
12533 duk_int_t rc;
12534
12536 DUK_ASSERT(thr != NULL);
12538 idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */
12539 if (idx_func < 0 || nargs < 0) {
12540 /* See comments in duk_pcall(). */
12542 return DUK_EXEC_ERROR; /* unreachable */
12543 }
12544
12545 call_flags = 0; /* respect reclimit, not constructor */
12546
12547 rc = duk_handle_call_protected(thr, /* thread */
12548 nargs, /* num_stack_args */
12549 call_flags); /* call_flags */
12550
12551 return rc;
12552}
12553
12555 duk_idx_t obj_index;
12556 duk_idx_t nargs;
12558 /* Get the original arguments. Note that obj_index may be a relative
12559 * index so the stack must have the same top when we use it.
12560 */
12561
12563
12564 obj_index = (duk_idx_t) duk_get_int(ctx, -2);
12565 nargs = (duk_idx_t) duk_get_int(ctx, -1);
12566 duk_pop_2(ctx);
12567
12568 obj_index = duk_require_normalize_index(ctx, obj_index); /* make absolute */
12569 duk__call_prop_prep_stack(ctx, obj_index, nargs);
12570 duk_call_method(ctx, nargs);
12571 return 1;
12572}
12573
12576 * Must be careful to catch errors related to value stack manipulation
12577 * and property lookup, not just the call itself.
12578 */
12579
12581
12582 duk_push_idx(ctx, obj_index);
12583 duk_push_idx(ctx, nargs);
12584
12585 /* Inputs: explicit arguments (nargs), +1 for key, +2 for obj_index/nargs passing.
12586 * If the value stack does not contain enough args, an error is thrown; this matches
12587 * behavior of the other protected call API functions.
12588 */
12589 return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 1 /*nrets*/);
12590}
12591
12593 duk_hthread *thr = (duk_hthread *) ctx;
12594 duk_int_t rc;
12595
12597 DUK_ASSERT(thr != NULL);
12598
12599 if (duk_get_top(ctx) < nargs || nrets < 0) {
12600 /* See comments in duk_pcall(). */
12602 return DUK_EXEC_ERROR; /* unreachable */
12603 }
12604
12605 rc = duk_handle_safe_call(thr, /* thread */
12606 func, /* func */
12607 nargs, /* num_stack_args */
12608 nrets); /* num_stack_res */
12609
12610 return rc;
12611}
12612
12613DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) {
12614 /*
12615 * There are two [[Construct]] operations in the specification:
12616 *
12617 * - E5 Section 13.2.2: for Function objects
12618 * - E5 Section 15.3.4.5.2: for "bound" Function objects
12619 *
12620 * The chain of bound functions is resolved in Section 15.3.4.5.2,
12621 * with arguments "piling up" until the [[Construct]] internal
12622 * method is called on the final, actual Function object. Note
12623 * that the "prototype" property is looked up *only* from the
12624 * final object, *before* calling the constructor.
12625 *
12626 * Currently we follow the bound function chain here to get the
12627 * "prototype" property value from the final, non-bound function.
12628 * However, we let duk_handle_call() handle the argument "piling"
12629 * when the constructor is called. The bound function chain is
12630 * thus now processed twice.
12631 *
12632 * When constructing new Array instances, an unnecessary object is
12633 * created and discarded now: the standard [[Construct]] creates an
12634 * object, and calls the Array constructor. The Array constructor
12635 * returns an Array instance, which is used as the result value for
12636 * the "new" operation; the object created before the Array constructor
12637 * call is discarded.
12638 *
12639 * This would be easy to fix, e.g. by knowing that the Array constructor
12640 * will always create a replacement object and skip creating the fallback
12641 * object in that case.
12642 *
12643 * Note: functions called via "new" need to know they are called as a
12644 * constructor. For instance, built-in constructors behave differently
12645 * depending on how they are called.
12646 */
12647
12648 /* XXX: merge this with duk_js_call.c, as this function implements
12649 * core semantics (or perhaps merge the two files altogether).
12650 */
12651
12652 duk_hthread *thr = (duk_hthread *) ctx;
12654 duk_hobject *cons;
12655 duk_hobject *fallback;
12656 duk_idx_t idx_cons;
12657 duk_small_uint_t call_flags;
12658
12660
12661 /* [... constructor arg1 ... argN] */
12662
12663 idx_cons = duk_require_normalize_index(ctx, -nargs - 1);
12664
12665 DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld",
12666 (long) duk_get_top(ctx), (long) nargs, (long) idx_cons));
12667
12668 /* XXX: code duplication */
12669
12670 /*
12671 * Figure out the final, non-bound constructor, to get "prototype"
12672 * property.
12673 */
12674
12675 duk_dup(ctx, idx_cons);
12676 for (;;) {
12677 duk_tval *tv;
12678 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
12679 DUK_ASSERT(tv != NULL);
12680
12681 if (DUK_TVAL_IS_OBJECT(tv)) {
12682 cons = DUK_TVAL_GET_OBJECT(tv);
12683 DUK_ASSERT(cons != NULL);
12685 /* Checking callability of the immediate target
12686 * is important, same for constructability.
12687 * Checking it for functions down the bound
12688 * function chain is not strictly necessary
12689 * because .bind() should normally reject them.
12690 * But it's good to check anyway because it's
12691 * technically possible to edit the bound function
12692 * chain via internal keys.
12693 */
12694 goto not_constructable;
12695 }
12696 if (!DUK_HOBJECT_HAS_BOUND(cons)) {
12697 break;
12698 }
12699 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
12700 /* Lightfuncs cannot be bound. */
12701 break;
12702 } else {
12703 /* Anything else is not constructable. */
12704 goto not_constructable;
12705 }
12706 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [... cons target] */
12707 duk_remove(ctx, -2); /* -> [... target] */
12708 }
12709 DUK_ASSERT(duk_is_callable(ctx, -1));
12710 DUK_ASSERT(duk_is_lightfunc(ctx, -1) ||
12711 (duk_get_hobject(ctx, -1) != NULL && !DUK_HOBJECT_HAS_BOUND(duk_get_hobject(ctx, -1))));
12712
12713 /* [... constructor arg1 ... argN final_cons] */
12714
12715 /*
12716 * Create "fallback" object to be used as the object instance,
12717 * unless the constructor returns a replacement value.
12718 * Its internal prototype needs to be set based on "prototype"
12719 * property of the constructor.
12720 */
12721
12722 duk_push_object(ctx); /* class Object, extensible */
12723
12724 /* [... constructor arg1 ... argN final_cons fallback] */
12725
12727 proto = duk_get_hobject(ctx, -1);
12728 if (!proto) {
12729 DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
12730 "-> leave standard Object prototype as fallback prototype"));
12731 } else {
12732 DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
12733 "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
12734 fallback = duk_get_hobject(ctx, -2);
12735 DUK_ASSERT(fallback != NULL);
12737 }
12738 duk_pop(ctx);
12739
12740 /* [... constructor arg1 ... argN final_cons fallback] */
12741
12742 /*
12743 * Manipulate callstack for the call.
12744 */
12745
12746 duk_dup_top(ctx);
12747 duk_insert(ctx, idx_cons + 1); /* use fallback as 'this' value */
12748 duk_insert(ctx, idx_cons); /* also stash it before constructor,
12749 * in case we need it (as the fallback value)
12750 */
12751 duk_pop(ctx); /* pop final_cons */
12752
12753
12754 /* [... fallback constructor fallback(this) arg1 ... argN];
12755 * Note: idx_cons points to first 'fallback', not 'constructor'.
12756 */
12757
12758 DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, idx_cons+2 (fallback/this) -> %!T, "
12759 "nargs=%ld, top=%ld",
12760 (duk_tval *) duk_get_tval(ctx, idx_cons + 1),
12761 (duk_tval *) duk_get_tval(ctx, idx_cons + 2),
12762 (long) nargs,
12763 (long) duk_get_top(ctx)));
12764
12765 /*
12766 * Call the constructor function (called in "constructor mode").
12767 */
12768
12769 call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL; /* not protected, respect reclimit, is a constructor call */
12770
12771 duk_handle_call_unprotected(thr, /* thread */
12772 nargs, /* num_stack_args */
12773 call_flags); /* call_flags */
12774
12775 /* [... fallback retval] */
12776
12777 DUK_DDD(DUK_DDDPRINT("constructor call finished, fallback=%!iT, retval=%!iT",
12778 (duk_tval *) duk_get_tval(ctx, -2),
12779 (duk_tval *) duk_get_tval(ctx, -1)));
12780
12781 /*
12782 * Determine whether to use the constructor return value as the created
12783 * object instance or not.
12784 */
12785
12786 if (duk_is_object(ctx, -1)) {
12787 duk_remove(ctx, -2);
12788 } else {
12789 duk_pop(ctx);
12790 }
12791
12792 /*
12793 * Augment created errors upon creation (not when they are thrown or
12794 * rethrown). __FILE__ and __LINE__ are not desirable here; the call
12795 * stack reflects the caller which is correct.
12796 */
12797
12798#ifdef DUK_USE_AUGMENT_ERROR_CREATE
12800 duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
12801#endif
12802
12803 /* [... retval] */
12805 return;
12806
12807 not_constructable:
12809}
12810
12812 duk_uint_t nargs;
12813
12814 nargs = duk_to_uint(ctx, -1);
12815 duk_pop(ctx);
12816
12817 duk_new(ctx, nargs);
12818 return 1;
12819}
12820
12823
12825
12826 /* For now, just use duk_safe_call() to wrap duk_new(). We can't
12827 * simply use a protected duk_handle_call() because there's post
12828 * processing which might throw. It should be possible to ensure
12829 * the post processing never throws (except in internal errors and
12830 * out of memory etc which are always allowed) and then remove this
12831 * wrapper.
12832 */
12833
12834 duk_push_uint(ctx, nargs);
12835 rc = duk_safe_call(ctx, duk__pnew_helper, nargs + 2 /*nargs*/, 1 /*nrets*/);
12836 return rc;
12837}
12838
12840 duk_hthread *thr = (duk_hthread *) ctx;
12841 duk_activation *act;
12842
12844 DUK_ASSERT(thr != NULL);
12846
12848 DUK_ASSERT(act != NULL); /* because callstack_top > 0 */
12849 return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
12850}
12851
12853 duk_hthread *thr = (duk_hthread *) ctx;
12854 duk_activation *act;
12855
12856 /* For user code this could just return 1 (strict) always
12857 * because all Duktape/C functions are considered strict,
12858 * and strict is also the default when nothing is running.
12859 * However, Duktape may call this function internally when
12860 * the current activation is an Ecmascript function, so
12861 * this cannot be replaced by a 'return 1' without fixing
12862 * the internal call sites.
12863 */
12866 DUK_ASSERT(thr != NULL);
12868
12870 if (act == NULL) {
12871 /* Strict by default. */
12872 return 1;
12873 }
12874 return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
12875}
12876
12877/*
12878 * Duktape/C function magic
12879 */
12880
12882 duk_hthread *thr = (duk_hthread *) ctx;
12883 duk_activation *act;
12884 duk_hobject *func;
12885
12887 DUK_ASSERT(thr != NULL);
12889
12891 if (act) {
12892 func = DUK_ACT_GET_FUNC(act);
12893 if (!func) {
12894 duk_tval *tv = &act->tv_func;
12895 duk_small_uint_t lf_flags;
12896 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
12897 return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
12898 }
12899 DUK_ASSERT(func != NULL);
12900
12903 return (duk_int_t) nf->magic;
12904 }
12905 }
12906 return 0;
12907}
12908
12910 duk_hthread *thr = (duk_hthread *) ctx;
12911 duk_tval *tv;
12912 duk_hobject *h;
12913
12915
12916 tv = duk_require_tval(ctx, index);
12917 if (DUK_TVAL_IS_OBJECT(tv)) {
12919 DUK_ASSERT(h != NULL);
12921 goto type_error;
12922 }
12923 return (duk_int_t) ((duk_hnativefunction *) h)->magic;
12924 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
12926 return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
12927 }
12928
12929 /* fall through */
12930 type_error:
12932 return 0;
12933}
12934
12937
12939
12941 DUK_ASSERT(nf != NULL);
12942 nf->magic = (duk_int16_t) magic;
12943}
12944#line 1 "duk_api_codec.c"
12945/*
12946 * Encoding and decoding basic formats: hex, base64.
12947 *
12948 * These are in-place operations which may allow an optimized implementation.
12949 *
12950 * Base-64: https://tools.ietf.org/html/rfc4648#section-4
12951 */
12953/* include removed: duk_internal.h */
12954
12955/* Shared handling for encode/decode argument. Fast path handling for
12956 * buffer and string values because they're the most common. In particular,
12957 * avoid creating a temporary string or buffer when possible.
12958 */
12959DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
12960 DUK_ASSERT(duk_is_valid_index(ctx, index)); /* checked by caller */
12961 if (duk_is_buffer(ctx, index)) {
12962 return (const duk_uint8_t *) duk_get_buffer(ctx, index, out_len);
12963 } else {
12964 return (const duk_uint8_t *) duk_to_lstring(ctx, index, out_len);
12965 }
12966}
12967
12968#if defined(DUK_USE_BASE64_FASTPATH)
12969DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
12970 duk_uint_t t;
12971 duk_size_t n_full, n_full3, n_final;
12972 const duk_uint8_t *src_end_fast;
12973
12974 n_full = srclen / 3; /* full 3-byte -> 4-char conversions */
12975 n_full3 = n_full * 3;
12976 n_final = srclen - n_full3;
12977 DUK_ASSERT_DISABLE(n_final >= 0);
12978 DUK_ASSERT(n_final <= 2);
12979
12980 src_end_fast = src + n_full3;
12981 while (DUK_UNLIKELY(src != src_end_fast)) {
12982 t = (duk_uint_t) (*src++);
12983 t = (t << 8) + (duk_uint_t) (*src++);
12984 t = (t << 8) + (duk_uint_t) (*src++);
12985
12986 *dst++ = duk_base64_enctab[t >> 18];
12987 *dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
12988 *dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
12989 *dst++ = duk_base64_enctab[t & 0x3f];
12990
12991#if 0 /* Tested: not faster on x64 */
12992 /* aaaaaabb bbbbcccc ccdddddd */
12993 dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
12994 dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];
12995 dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];
12996 dst[3] = duk_base64_enctab[src[2] & 0x3f];
12997 src += 3; dst += 4;
12998#endif
12999 }
13000
13001 switch (n_final) {
13002 /* case 0: nop */
13003 case 1: {
13004 /* XX== */
13005 t = (duk_uint_t) (*src++);
13006 *dst++ = duk_base64_enctab[t >> 2]; /* XXXXXX-- */
13007 *dst++ = duk_base64_enctab[(t << 4) & 0x3f]; /* ------XX */
13008 *dst++ = DUK_ASC_EQUALS;
13009 *dst++ = DUK_ASC_EQUALS;
13010 break;
13011 }
13012 case 2: {
13013 /* XXX= */
13014 t = (duk_uint_t) (*src++);
13015 t = (t << 8) + (duk_uint_t) (*src++);
13016 *dst++ = duk_base64_enctab[t >> 10]; /* XXXXXX-- -------- */
13017 *dst++ = duk_base64_enctab[(t >> 4) & 0x3f]; /* ------XX XXXX---- */
13018 *dst++ = duk_base64_enctab[(t << 2) & 0x3f]; /* -------- ----XXXX */
13019 *dst++ = DUK_ASC_EQUALS;
13020 break;
13021 }
13022 }
13023}
13024#else /* DUK_USE_BASE64_FASTPATH */
13025DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
13026 duk_small_uint_t i, snip;
13027 duk_uint_t t;
13028 duk_uint_fast8_t x, y;
13029 const duk_uint8_t *src_end;
13030
13031 src_end = src + srclen;
13032
13033 while (src < src_end) {
13034 /* read 3 bytes into 't', padded by zero */
13035 snip = 4;
13036 t = 0;
13037 for (i = 0; i < 3; i++) {
13038 t = t << 8;
13039 if (src >= src_end) {
13040 snip--;
13041 } else {
13042 t += (duk_uint_t) (*src++);
13043 }
13044 }
13045
13046 /*
13047 * Missing bytes snip base64 example
13048 * 0 4 XXXX
13049 * 1 3 XXX=
13050 * 2 2 XX==
13051 */
13052
13053 DUK_ASSERT(snip >= 2 && snip <= 4);
13054
13055 for (i = 0; i < 4; i++) {
13056 x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
13057 t = t << 6;
13058
13059 /* A straightforward 64-byte lookup would be faster
13060 * and cleaner, but this is shorter.
13061 */
13062 if (i >= snip) {
13063 y = '=';
13064 } else if (x <= 25) {
13065 y = x + 'A';
13066 } else if (x <= 51) {
13067 y = x - 26 + 'a';
13068 } else if (x <= 61) {
13069 y = x - 52 + '0';
13070 } else if (x == 62) {
13071 y = '+';
13072 } else {
13073 y = '/';
13074 }
13075
13076 *dst++ = (duk_uint8_t) y;
13077 }
13078 }
13079}
13080#endif /* DUK_USE_BASE64_FASTPATH */
13081
13082#if defined(DUK_USE_BASE64_FASTPATH)
13083DUK_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) {
13084 duk_int_t x;
13085 duk_int_t t;
13086 duk_small_uint_t n_equal;
13087 duk_small_uint_t n_chars;
13088 const duk_uint8_t *src_end;
13089 const duk_uint8_t *src_end_safe;
13090
13091 src_end = src + srclen;
13092 src_end_safe = src_end - 4; /* if 'src < src_end_safe', safe to read 4 bytes */
13093
13094 /* Innermost fast path processes 4 valid base-64 characters at a time
13095 * but bails out on whitespace, padding chars ('=') and invalid chars.
13096 * Once the slow path segment has been processed, we return to the
13097 * inner fast path again. This handles e.g. base64 with newlines
13098 * reasonably well because the majority of a line is in the fast path.
13099 */
13100 for (;;) {
13101 /* Fast path, handle units with just actual encoding characters. */
13102
13103 while (src <= src_end_safe) {
13104 /* The lookup byte is intentionally sign extended to (at least)
13105 * 32 bits and then ORed. This ensures that is at least 1 byte
13106 * is negative, the highest bit of 't' will be set at the end
13107 * and we don't need to check every byte.
13108 */
13109 DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p",
13110 (const void *) src, (const void *) src_end_safe, (const void *) src_end));
13111
13112 t = (duk_int_t) duk_base64_dectab[*src++];
13113 t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13114 t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13115 t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13116
13117 if (DUK_UNLIKELY(t < 0)) {
13118 DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit"));
13119 src -= 4;
13120 break;
13121 }
13122
13123 DUK_ASSERT(t <= 0xffffffL);
13124 DUK_ASSERT((t >> 24) == 0);
13125 *dst++ = (duk_uint8_t) (t >> 16);
13126 *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13127 *dst++ = (duk_uint8_t) (t & 0xff);
13128 }
13129
13130 /* Handle one slow path unit (or finish if we're done). */
13131
13132 n_equal = 0;
13133 n_chars = 0;
13134 t = 0;
13135 for (;;) {
13136 DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld",
13137 (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));
13138
13139 if (DUK_UNLIKELY(src >= src_end)) {
13140 goto done; /* two level break */
13141 }
13142
13143 x = duk_base64_dectab[*src++];
13144 if (DUK_UNLIKELY(x < 0)) {
13145 if (x == -2) {
13146 continue; /* allowed ascii whitespace */
13147 } else if (x == -3) {
13148 n_equal++;
13149 t <<= 6;
13150 } else {
13151 DUK_ASSERT(x == -1);
13152 goto error;
13153 }
13154 } else {
13155 DUK_ASSERT(x >= 0 && x <= 63);
13156 if (n_equal > 0) {
13157 /* Don't allow actual chars after equal sign. */
13158 goto error;
13159 }
13160 t = (t << 6) + x;
13161 }
13162
13163 if (DUK_UNLIKELY(n_chars == 3)) {
13164 /* Emit 3 bytes and backtrack if there was padding. There's
13165 * always space for the whole 3 bytes so no check needed.
13166 */
13167 DUK_ASSERT(t <= 0xffffffL);
13168 DUK_ASSERT((t >> 24) == 0);
13169 *dst++ = (duk_uint8_t) (t >> 16);
13170 *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13171 *dst++ = (duk_uint8_t) (t & 0xff);
13172
13173 if (DUK_UNLIKELY(n_equal > 0)) {
13174 DUK_ASSERT(n_equal <= 4);
13175
13176 /* There may be whitespace between the equal signs. */
13177 if (n_equal == 1) {
13178 /* XXX= */
13179 dst -= 1;
13180 } else if (n_equal == 2) {
13181 /* XX== */
13182 dst -= 2;
13183 } else {
13184 goto error; /* invalid padding */
13185 }
13186
13187 /* Continue parsing after padding, allows concatenated,
13188 * padded base64.
13189 */
13190 }
13191 break; /* back to fast loop */
13192 } else {
13193 n_chars++;
13194 }
13195 }
13196 }
13197 done:
13198 DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
13199 (const void *) src, (const void *) src_end, (long) n_chars));
13200
13201 DUK_ASSERT(src == src_end);
13202
13203 if (n_chars != 0) {
13204 /* Here we'd have the option of decoding unpadded base64
13205 * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
13206 * accepted.
13207 */
13208 goto error;
13209 }
13210
13211 *out_dst_final = dst;
13212 return 1;
13213
13214 error:
13215 return 0;
13216}
13217#else /* DUK_USE_BASE64_FASTPATH */
13218DUK_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) {
13219 duk_uint_t t;
13220 duk_uint_fast8_t x, y;
13221 duk_small_uint_t group_idx;
13222 duk_small_uint_t n_equal;
13223 const duk_uint8_t *src_end;
13224
13225 src_end = src + srclen;
13226 t = 0;
13227 group_idx = 0;
13228 n_equal = 0;
13229
13230 while (src < src_end) {
13231 x = *src++;
13232
13233 if (x >= 'A' && x <= 'Z') {
13234 y = x - 'A' + 0;
13235 } else if (x >= 'a' && x <= 'z') {
13236 y = x - 'a' + 26;
13237 } else if (x >= '0' && x <= '9') {
13238 y = x - '0' + 52;
13239 } else if (x == '+') {
13240 y = 62;
13241 } else if (x == '/') {
13242 y = 63;
13243 } else if (x == '=') {
13244 /* We don't check the zero padding bytes here right now
13245 * (that they're actually zero). This seems to be common
13246 * behavior for base-64 decoders.
13247 */
13248
13249 n_equal++;
13250 t <<= 6; /* shift in zeroes */
13251 goto skip_add;
13252 } else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
13253 /* allow basic ASCII whitespace */
13254 continue;
13255 } else {
13256 goto error;
13257 }
13258
13259 if (n_equal > 0) {
13260 /* Don't allow mixed padding and actual chars. */
13261 goto error;
13262 }
13263 t = (t << 6) + y;
13264 skip_add:
13265
13266 if (group_idx == 3) {
13267 /* output 3 bytes from 't' */
13268 *dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
13269 *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13270 *dst++ = (duk_uint8_t) (t & 0xff);
13271
13272 if (DUK_UNLIKELY(n_equal > 0)) {
13273 /* Backtrack. */
13274 DUK_ASSERT(n_equal <= 4);
13275 if (n_equal == 1) {
13276 dst -= 1;
13277 } else if (n_equal == 2) {
13278 dst -= 2;
13279 } else {
13280 goto error; /* invalid padding */
13281 }
13282
13283 /* Here we can choose either to end parsing and ignore
13284 * whatever follows, or to continue parsing in case
13285 * multiple (possibly padded) base64 strings have been
13286 * concatenated. Currently, keep on parsing.
13287 */
13288 n_equal = 0;
13289 }
13290
13291 t = 0;
13292 group_idx = 0;
13293 } else {
13294 group_idx++;
13295 }
13296 }
13298 if (group_idx != 0) {
13299 /* Here we'd have the option of decoding unpadded base64
13300 * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
13301 * accepted.
13302 */
13303 goto error;
13304 }
13305
13306 *out_dst_final = dst;
13307 return 1;
13308
13309 error:
13310 return 0;
13311}
13312#endif /* DUK_USE_BASE64_FASTPATH */
13313
13315 duk_hthread *thr = (duk_hthread *) ctx;
13316 const duk_uint8_t *src;
13317 duk_size_t srclen;
13318 duk_size_t dstlen;
13319 duk_uint8_t *dst;
13320 const char *ret;
13321
13323
13324 /* XXX: optimize for string inputs: no need to coerce to a buffer
13325 * which makes a copy of the input.
13326 */
13327
13329 src = duk__prep_codec_arg(ctx, index, &srclen);
13330 /* Note: for srclen=0, src may be NULL */
13331
13332 /* Computation must not wrap; this limit works for 32-bit size_t:
13333 * >>> srclen = 3221225469
13334 * >>> '%x' % ((srclen + 2) / 3 * 4)
13335 * 'fffffffc'
13336 */
13337 if (srclen > 3221225469UL) {
13338 goto type_error;
13339 }
13340 dstlen = (srclen + 2) / 3 * 4;
13341 dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen);
13342
13343 duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
13344
13345 ret = duk_to_string(ctx, -1);
13346 duk_replace(ctx, index);
13347 return ret;
13348
13349 type_error:
13351 return NULL; /* never here */
13352}
13353
13355 duk_hthread *thr = (duk_hthread *) ctx;
13356 const duk_uint8_t *src;
13357 duk_size_t srclen;
13358 duk_size_t dstlen;
13359 duk_uint8_t *dst;
13360 duk_uint8_t *dst_final;
13361 duk_bool_t retval;
13362
13364
13365 /* XXX: optimize for buffer inputs: no need to coerce to a string
13366 * which causes an unnecessary interning.
13367 */
13368
13370 src = duk__prep_codec_arg(ctx, index, &srclen);
13371
13372 /* Computation must not wrap, only srclen + 3 is at risk of
13373 * wrapping because after that the number gets smaller.
13374 * This limit works for 32-bit size_t:
13375 * 0x100000000 - 3 - 1 = 4294967292
13376 */
13377 if (srclen > 4294967292UL) {
13378 goto type_error;
13379 }
13380 dstlen = (srclen + 3) / 4 * 3; /* upper limit, assuming no whitespace etc */
13381 dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
13382 /* Note: for dstlen=0, dst may be NULL */
13383
13384 retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);
13385 if (!retval) {
13386 goto type_error;
13387 }
13388
13389 /* XXX: convert to fixed buffer? */
13390 (void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst));
13391 duk_replace(ctx, index);
13392 return;
13393
13394 type_error:
13396}
13397
13399 const duk_uint8_t *inp;
13400 duk_size_t len;
13401 duk_size_t i;
13402 duk_uint8_t *buf;
13403 const char *ret;
13404#if defined(DUK_USE_HEX_FASTPATH)
13405 duk_size_t len_safe;
13406 duk_uint16_t *p16;
13407#endif
13408
13410
13412 inp = duk__prep_codec_arg(ctx, index, &len);
13413 DUK_ASSERT(inp != NULL || len == 0);
13414
13415 /* Fixed buffer, no zeroing because we'll fill all the data. */
13416 buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len * 2, DUK_BUF_FLAG_NOZERO /*flags*/);
13417 DUK_ASSERT(buf != NULL);
13418
13419#if defined(DUK_USE_HEX_FASTPATH)
13420 DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0); /* pointer is aligned, guaranteed for fixed buffer */
13421 p16 = (duk_uint16_t *) (void *) buf;
13422 len_safe = len & ~0x03U;
13423 for (i = 0; i < len_safe; i += 4) {
13424 p16[0] = duk_hex_enctab[inp[i]];
13425 p16[1] = duk_hex_enctab[inp[i + 1]];
13426 p16[2] = duk_hex_enctab[inp[i + 2]];
13427 p16[3] = duk_hex_enctab[inp[i + 3]];
13428 p16 += 4;
13429 }
13430 for (; i < len; i++) {
13431 *p16++ = duk_hex_enctab[inp[i]];
13432 }
13433#else /* DUK_USE_HEX_FASTPATH */
13434 for (i = 0; i < len; i++) {
13436 t = (duk_small_uint_t) inp[i];
13437 buf[i*2 + 0] = duk_lc_digits[t >> 4];
13438 buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
13439 }
13440#endif /* DUK_USE_HEX_FASTPATH */
13441
13442 /* XXX: Using a string return value forces a string intern which is
13443 * not always necessary. As a rough performance measure, hex encode
13444 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
13445 * without string coercion. Change to returning a buffer and let the
13446 * caller coerce to string if necessary?
13447 */
13448
13449 ret = duk_to_string(ctx, -1);
13450 duk_replace(ctx, index);
13451 return ret;
13452}
13453
13455 duk_hthread *thr = (duk_hthread *) ctx;
13456 const duk_uint8_t *inp;
13457 duk_size_t len;
13458 duk_size_t i;
13459 duk_int_t t;
13460 duk_uint8_t *buf;
13461#if defined(DUK_USE_HEX_FASTPATH)
13462 duk_int_t chk;
13463 duk_uint8_t *p;
13464 duk_size_t len_safe;
13465#endif
13466
13468
13470 inp = duk__prep_codec_arg(ctx, index, &len);
13471 DUK_ASSERT(inp != NULL || len == 0);
13472
13473 if (len & 0x01) {
13474 goto type_error;
13475 }
13476
13477 /* Fixed buffer, no zeroing because we'll fill all the data. */
13478 buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len / 2, DUK_BUF_FLAG_NOZERO /*flags*/);
13479 DUK_ASSERT(buf != NULL);
13480
13481#if defined(DUK_USE_HEX_FASTPATH)
13482 p = buf;
13483 len_safe = len & ~0x07U;
13484 for (i = 0; i < len_safe; i += 8) {
13485 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
13486 ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13487 chk = t;
13488 p[0] = (duk_uint8_t) t;
13489 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
13490 ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
13491 chk |= t;
13492 p[1] = (duk_uint8_t) t;
13493 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
13494 ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
13495 chk |= t;
13496 p[2] = (duk_uint8_t) t;
13497 t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
13498 ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
13499 chk |= t;
13500 p[3] = (duk_uint8_t) t;
13501 p += 4;
13502
13503 /* Check if any lookup above had a negative result. */
13504 if (DUK_UNLIKELY(chk < 0)) {
13505 goto type_error;
13506 }
13507 }
13508 for (; i < len; i += 2) {
13509 t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
13510 ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13511 if (DUK_UNLIKELY(t < 0)) {
13512 goto type_error;
13513 }
13514 *p++ = (duk_uint8_t) t;
13515 }
13516#else /* DUK_USE_HEX_FASTPATH */
13517 for (i = 0; i < len; i += 2) {
13518 /* For invalid characters the value -1 gets extended to
13519 * at least 16 bits. If either nybble is invalid, the
13520 * resulting 't' will be < 0.
13522 t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
13523 ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13524 if (DUK_UNLIKELY(t < 0)) {
13525 goto type_error;
13526 }
13527 buf[i >> 1] = (duk_uint8_t) t;
13528 }
13529#endif /* DUK_USE_HEX_FASTPATH */
13530
13531 duk_replace(ctx, index);
13532 return;
13533
13534 type_error:
13536}
13537
13539#ifdef DUK_USE_ASSERTIONS
13540 duk_idx_t top_at_entry;
13541#endif
13542 const char *ret;
13543
13545#ifdef DUK_USE_ASSERTIONS
13546 top_at_entry = duk_get_top(ctx);
13547#endif
13548
13551 index /*idx_value*/,
13552 DUK_INVALID_INDEX /*idx_replacer*/,
13553 DUK_INVALID_INDEX /*idx_space*/,
13554 0 /*flags*/);
13555 DUK_ASSERT(duk_is_string(ctx, -1));
13556 duk_replace(ctx, index);
13557 ret = duk_get_string(ctx, index);
13558
13559 DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
13560
13561 return ret;
13562}
13563
13565#ifdef DUK_USE_ASSERTIONS
13566 duk_idx_t top_at_entry;
13567#endif
13568
13570#ifdef DUK_USE_ASSERTIONS
13571 top_at_entry = duk_get_top(ctx);
13572#endif
13576 index /*idx_value*/,
13577 DUK_INVALID_INDEX /*idx_reviver*/,
13578 0 /*flags*/);
13579 duk_replace(ctx, index);
13580
13581 DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
13582}
13583#line 1 "duk_api_compile.c"
13584/*
13585 * Compilation and evaluation
13586 */
13587
13588/* include removed: duk_internal.h */
13589
13591struct duk__compile_raw_args {
13592 duk_size_t src_length; /* should be first on 64-bit platforms */
13593 const duk_uint8_t *src_buffer;
13595};
13596
13597/* Eval is just a wrapper now. */
13598DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
13599 duk_uint_t comp_flags;
13600 duk_int_t rc;
13601
13603
13604 /* Note: strictness is *not* inherited from the current Duktape/C.
13605 * This would be confusing because the current strictness state
13606 * depends on whether we're running inside a Duktape/C activation
13607 * (= strict mode) or outside of any activation (= non-strict mode).
13608 * See tests/api/test-eval-strictness.c for more discussion.
13609 */
13610
13611 /* [ ... source? filename? ] (depends on flags) */
13612
13613 comp_flags = flags;
13614 comp_flags |= DUK_COMPILE_EVAL;
13615 rc = duk_compile_raw(ctx, src_buffer, src_length, comp_flags); /* may be safe, or non-safe depending on flags */
13616
13617 /* [ ... closure/error ] */
13618
13619 if (rc != DUK_EXEC_SUCCESS) {
13620 rc = DUK_EXEC_ERROR;
13621 goto got_rc;
13622 }
13623
13624 duk_push_global_object(ctx); /* explicit 'this' binding, see GH-164 */
13625
13626 if (flags & DUK_COMPILE_SAFE) {
13627 rc = duk_pcall_method(ctx, 0);
13628 } else {
13629 duk_call_method(ctx, 0);
13630 rc = DUK_EXEC_SUCCESS;
13631 }
13632
13633 /* [ ... result/error ] */
13634
13635 got_rc:
13636 if (flags & DUK_COMPILE_NORESULT) {
13637 duk_pop(ctx);
13638 }
13639
13640 return rc;
13641}
13642
13643/* Helper which can be called both directly and with duk_safe_call(). */
13645 duk_hthread *thr = (duk_hthread *) ctx;
13646 duk__compile_raw_args *comp_args;
13647 duk_uint_t flags;
13648 duk_small_uint_t comp_flags;
13649 duk_hcompiledfunction *h_templ;
13650
13652
13653 /* Note: strictness is not inherited from the current Duktape/C
13654 * context. Otherwise it would not be possible to compile
13655 * non-strict code inside a Duktape/C activation (which is
13656 * always strict now). See tests/api/test-eval-strictness.c
13657 * for discussion.
13658 */
13659
13660 /* [ ... source? filename? &comp_args ] (depends on flags) */
13661
13662 comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1);
13663 flags = comp_args->flags;
13664 duk_pop(ctx);
13665
13666 /* [ ... source? filename? ] */
13667
13668 if (flags & DUK_COMPILE_NOFILENAME) {
13669 /* Automatic filename: 'eval' or 'input'. */
13671 }
13672
13673 /* [ ... source? filename ] */
13674
13675 if (!comp_args->src_buffer) {
13676 duk_hstring *h_sourcecode;
13677
13678 h_sourcecode = duk_get_hstring(ctx, -2);
13679 if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */
13680 (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */
13681 /* XXX: when this error is caused by a nonexistent
13682 * file given to duk_peval_file() or similar, the
13683 * error message is not the best possible.
13684 */
13686 }
13687 DUK_ASSERT(h_sourcecode != NULL);
13688 comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
13689 comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
13690 }
13691 DUK_ASSERT(comp_args->src_buffer != NULL);
13692
13693 /* XXX: unnecessary translation of flags */
13694 comp_flags = 0;
13695 if (flags & DUK_COMPILE_EVAL) {
13696 comp_flags |= DUK_JS_COMPILE_FLAG_EVAL;
13697 }
13698 if (flags & DUK_COMPILE_FUNCTION) {
13699 comp_flags |= DUK_JS_COMPILE_FLAG_EVAL |
13701 }
13702 if (flags & DUK_COMPILE_STRICT) {
13703 comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
13704 }
13705
13706 /* [ ... source? filename ] */
13707
13708 duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags);
13709
13710 /* [ ... source? func_template ] */
13711
13712 if (flags & DUK_COMPILE_NOSOURCE) {
13713 ;
13714 } else {
13715 duk_remove(ctx, -2);
13716 }
13718 /* [ ... func_template ] */
13719
13720 h_templ = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
13721 DUK_ASSERT(h_templ != NULL);
13723 h_templ,
13726 1 /*add_auto_proto*/);
13727 duk_remove(ctx, -2); /* -> [ ... closure ] */
13728
13729 /* [ ... closure ] */
13730
13731 return 1;
13732}
13733
13734DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
13735 duk__compile_raw_args comp_args_alloc;
13736 duk__compile_raw_args *comp_args = &comp_args_alloc;
13737
13739
13740 if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
13741 /* String length is computed here to avoid multiple evaluation
13742 * of a macro argument in the calling side.
13743 */
13744 src_length = DUK_STRLEN(src_buffer);
13745 }
13746
13747 comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
13748 comp_args->src_length = src_length;
13749 comp_args->flags = flags;
13750 duk_push_pointer(ctx, (void *) comp_args);
13751
13752 /* [ ... source? filename? &comp_args ] (depends on flags) */
13753
13754 if (flags & DUK_COMPILE_SAFE) {
13755 duk_int_t rc;
13756 duk_int_t nargs;
13757 duk_int_t nrets = 1;
13758
13759 /* Arguments can be: [ source? filename? &comp_args] so that
13760 * nargs is 1 to 3. Call site encodes the correct nargs count
13761 * directly into flags.
13762 */
13763 nargs = flags & 0x07;
13764 DUK_ASSERT(nargs == (1 +
13765 ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
13766 ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1)));
13767 rc = duk_safe_call(ctx, duk__do_compile, nargs, nrets);
13769 /* [ ... closure ] */
13770 return rc;
13771 }
13772
13773 (void) duk__do_compile(ctx);
13774
13775 /* [ ... closure ] */
13776 return DUK_EXEC_SUCCESS;
13777}
13778#line 1 "duk_api_debug.c"
13779/*
13780 * Debugging related API calls
13781 */
13782
13783/* include removed: duk_internal.h */
13784
13786 duk_idx_t idx;
13787 duk_idx_t top;
13788
13790
13791 /* We don't duk_require_stack() here now, but rely on the caller having
13792 * enough space.
13793 */
13794
13795 top = duk_get_top(ctx);
13796 duk_push_array(ctx);
13797 for (idx = 0; idx < top; idx++) {
13798 duk_dup(ctx, idx);
13799 duk_put_prop_index(ctx, -2, idx);
13800 }
13801
13802 /* XXX: conversion errors should not propagate outwards.
13803 * Perhaps values need to be coerced individually?
13804 */
13806 duk_get_top_index(ctx), /*idx_value*/
13807 DUK_INVALID_INDEX, /*idx_replacer*/
13808 DUK_INVALID_INDEX, /*idx_space*/
13812
13813 duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1));
13814 duk_replace(ctx, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
13815 duk_pop(ctx);
13816 DUK_ASSERT(duk_is_string(ctx, -1));
13817}
13818
13819#if defined(DUK_USE_DEBUGGER_SUPPORT)
13820
13823 duk_debug_write_function write_cb,
13825 duk_debug_read_flush_function read_flush_cb,
13826 duk_debug_write_flush_function write_flush_cb,
13827 duk_debug_request_function request_cb,
13828 duk_debug_detached_function detached_cb,
13829 void *udata) {
13830 duk_hthread *thr = (duk_hthread *) ctx;
13831 duk_heap *heap;
13832 const char *str;
13833 duk_size_t len;
13834
13835 /* XXX: should there be an error or an automatic detach if
13836 * already attached?
13837 */
13838
13839 DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
13840
13842 DUK_ASSERT(read_cb != NULL);
13843 DUK_ASSERT(write_cb != NULL);
13844 /* Other callbacks are optional. */
13845
13846 heap = thr->heap;
13847 heap->dbg_read_cb = read_cb;
13848 heap->dbg_write_cb = write_cb;
13849 heap->dbg_peek_cb = peek_cb;
13850 heap->dbg_read_flush_cb = read_flush_cb;
13851 heap->dbg_write_flush_cb = write_flush_cb;
13852 heap->dbg_request_cb = request_cb;
13853 heap->dbg_detached_cb = detached_cb;
13854 heap->dbg_udata = udata;
13855 heap->dbg_have_next_byte = 0;
13856
13857 /* Start in paused state. */
13858 heap->dbg_processing = 0;
13859 heap->dbg_paused = 1;
13860 heap->dbg_state_dirty = 1;
13861 heap->dbg_force_restart = 0;
13862 heap->dbg_step_type = 0;
13863 heap->dbg_step_thread = NULL;
13864 heap->dbg_step_csindex = 0;
13865 heap->dbg_step_startline = 0;
13866 heap->dbg_exec_counter = 0;
13867 heap->dbg_last_counter = 0;
13868 heap->dbg_last_time = 0.0;
13869
13870 /* Send version identification and flush right afterwards. Note that
13871 * we must write raw, unframed bytes here.
13872 */
13873 duk_push_sprintf(ctx, "%ld %ld %s %s\n",
13875 (long) DUK_VERSION,
13876 (const char *) DUK_GIT_DESCRIBE,
13877 (const char *) DUK_USE_TARGET_INFO);
13878 str = duk_get_lstring(ctx, -1, &len);
13879 DUK_ASSERT(str != NULL);
13880 duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
13881 duk_debug_write_flush(thr);
13882 duk_pop(ctx);
13883}
13884
13886 duk_hthread *thr;
13887
13888 DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
13889
13891 thr = (duk_hthread *) ctx;
13892 DUK_ASSERT(thr != NULL);
13893 DUK_ASSERT(thr->heap != NULL);
13894
13895 /* Can be called multiple times with no harm. */
13896 duk_debug_do_detach(thr->heap);
13897}
13898
13900 duk_hthread *thr;
13901 duk_bool_t processed_messages;
13902
13904 thr = (duk_hthread *) ctx;
13905 DUK_ASSERT(thr != NULL);
13906 DUK_ASSERT(thr->heap != NULL);
13907
13908 if (!DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13909 return;
13910 }
13911 if (thr->callstack_top > 0 || thr->heap->dbg_processing) {
13912 /* Calling duk_debugger_cooperate() while Duktape is being
13913 * called into is not supported. This is not a 100% check
13914 * but prevents any damage in most cases.
13915 */
13916 return;
13917 }
13918
13919 processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
13920 DUK_UNREF(processed_messages);
13921}
13922
13924 duk_hthread *thr;
13925 duk_idx_t top;
13926 duk_idx_t idx;
13927 duk_bool_t ret = 0;
13928
13930 thr = (duk_hthread *) ctx;
13931 DUK_ASSERT(thr != NULL);
13932 DUK_ASSERT(thr->heap != NULL);
13933
13934 DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
13935
13936 top = duk_get_top(ctx);
13937 if (top < nvalues) {
13938 DUK_ERROR_API(thr, "not enough stack values for notify");
13939 return ret; /* unreachable */
13940 }
13941 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13942 duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
13943 for (idx = top - nvalues; idx < top; idx++) {
13944 duk_tval *tv = DUK_GET_TVAL_POSIDX(ctx, idx);
13945 duk_debug_write_tval(thr, tv);
13946 }
13947 duk_debug_write_eom(thr);
13948
13949 /* Return non-zero (true) if we have a good reason to believe
13950 * the notify was delivered; if we're still attached at least
13951 * a transport error was not indicated by the transport write
13952 * callback. This is not a 100% guarantee of course.
13953 */
13954 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13955 ret = 1;
13956 }
13957 }
13958 duk_pop_n(ctx, nvalues);
13959 return ret;
13960}
13961
13963 duk_hthread *thr;
13964
13966 thr = (duk_hthread *) ctx;
13967 DUK_ASSERT(thr != NULL);
13968 DUK_ASSERT(thr->heap != NULL);
13969
13970 DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
13971
13972 /* Treat like a debugger statement: ignore when not attached. */
13973 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13974 DUK_HEAP_SET_PAUSED(thr->heap);
13975
13976 /* Pause on the next opcode executed. This is always safe to do even
13977 * inside the debugger message loop: the interrupt counter will be reset
13978 * to its proper value when the message loop exits.
13979 */
13980 thr->interrupt_init = 1;
13981 thr->interrupt_counter = 0;
13982 }
13983}
13984
13985#else /* DUK_USE_DEBUGGER_SUPPORT */
13986
13989 duk_debug_write_function write_cb,
13992 duk_debug_write_flush_function write_flush_cb,
13993 duk_debug_request_function request_cb,
13994 duk_debug_detached_function detached_cb,
13995 void *udata) {
13997 DUK_UNREF(read_cb);
13998 DUK_UNREF(write_cb);
13999 DUK_UNREF(peek_cb);
14000 DUK_UNREF(read_flush_cb);
14001 DUK_UNREF(write_flush_cb);
14002 DUK_UNREF(request_cb);
14003 DUK_UNREF(detached_cb);
14004 DUK_UNREF(udata);
14005 DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
14006}
14007
14010 DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
14011}
14012
14014 /* nop */
14016 DUK_UNREF(ctx);
14017}
14023
14024 top = duk_get_top(ctx);
14025 if (top < nvalues) {
14026 DUK_ERROR_API((duk_hthread *) ctx, "not enough stack values for notify");
14027 return 0; /* unreachable */
14028 }
14029
14030 /* No debugger support, just pop values. */
14031 duk_pop_n(ctx, nvalues);
14032 return 0;
14034
14036 /* Treat like debugger statement: nop */
14038 DUK_UNREF(ctx);
14039}
14040
14041#endif /* DUK_USE_DEBUGGER_SUPPORT */
14042#line 1 "duk_api_heap.c"
14043/*
14044 * Heap creation and destruction
14045 */
14046
14047/* include removed: duk_internal.h */
14048
14051 duk_realloc_function realloc_func,
14052 duk_free_function free_func,
14053 void *heap_udata,
14054 duk_fatal_function fatal_handler) {
14055 duk_heap *heap = NULL;
14056 duk_context *ctx;
14057
14058 /* Assume that either all memory funcs are NULL or non-NULL, mixed
14059 * cases will now be unsafe.
14060 */
14061
14062 /* XXX: just assert non-NULL values here and make caller arguments
14063 * do the defaulting to the default implementations (smaller code)?
14064 */
14065
14066 if (!alloc_func) {
14067 DUK_ASSERT(realloc_func == NULL);
14068 DUK_ASSERT(free_func == NULL);
14069#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
14070 alloc_func = duk_default_alloc_function;
14071 realloc_func = duk_default_realloc_function;
14072 free_func = duk_default_free_function;
14073#else
14074 DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
14075 return NULL;
14076#endif
14077 } else {
14078 DUK_ASSERT(realloc_func != NULL);
14079 DUK_ASSERT(free_func != NULL);
14080 }
14081
14082 if (!fatal_handler) {
14083 fatal_handler = duk_default_fatal_handler;
14085
14086 DUK_ASSERT(alloc_func != NULL);
14087 DUK_ASSERT(realloc_func != NULL);
14088 DUK_ASSERT(free_func != NULL);
14089 DUK_ASSERT(fatal_handler != NULL);
14090
14091 heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
14092 if (!heap) {
14093 return NULL;
14094 }
14095 ctx = (duk_context *) heap->heap_thread;
14096 DUK_ASSERT(ctx != NULL);
14097 DUK_ASSERT(((duk_hthread *) ctx)->heap != NULL);
14098 return ctx;
14099}
14100
14102 duk_hthread *thr = (duk_hthread *) ctx;
14103 duk_heap *heap;
14104
14105 if (!ctx) {
14106 return;
14107 }
14108 heap = thr->heap;
14109 DUK_ASSERT(heap != NULL);
14110
14111 duk_heap_free(heap);
14112}
14113
14114/* XXX: better place for this */
14116 duk_hthread *thr = (duk_hthread *) ctx;
14117 duk_hobject *h_glob;
14118 duk_hobject *h_prev_glob;
14119 duk_hobject *h_env;
14120 duk_hobject *h_prev_env;
14121
14122 DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(ctx, -1)));
14123
14124 h_glob = duk_require_hobject(ctx, -1);
14125 DUK_ASSERT(h_glob != NULL);
14126
14127 /*
14128 * Replace global object.
14129 */
14130
14131 h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
14132 DUK_UNREF(h_prev_glob);
14133 thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
14134 DUK_HOBJECT_INCREF(thr, h_glob);
14135 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob); /* side effects, in theory (referenced by global env) */
14136
14137 /*
14138 * Replace lexical environment for global scope
14139 *
14140 * Create a new object environment for the global lexical scope.
14141 * We can't just reset the _Target property of the current one,
14142 * because the lexical scope is shared by other threads with the
14143 * same (initial) built-ins.
14144 */
14145
14146 (void) duk_push_object_helper(ctx,
14149 -1); /* no prototype, updated below */
14150
14151 duk_dup(ctx, -2);
14152 duk_dup(ctx, -3);
14153
14154 /* [ ... new_glob new_env new_glob new_glob ] */
14155
14158
14159 /* [ ... new_glob new_env ] */
14160
14161 h_env = duk_get_hobject(ctx, -1);
14162 DUK_ASSERT(h_env != NULL);
14163
14164 h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
14165 thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_env;
14166 DUK_HOBJECT_INCREF(thr, h_env);
14167 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env); /* side effects */
14168 DUK_UNREF(h_env); /* without refcounts */
14169 DUK_UNREF(h_prev_env);
14170
14171 /* [ ... new_glob new_env ] */
14172
14173 duk_pop_2(ctx);
14174
14175 /* [ ... ] */
14176}
14177#line 1 "duk_api_logging.c"
14178/*
14179 * Logging
14180 *
14181 * Current logging primitive is a sprintf-style log which is convenient
14182 * for most C code. Another useful primitive would be to log N arguments
14183 * from value stack (like the Ecmascript binding does).
14184 */
14185
14186/* include removed: duk_internal.h */
14187
14188DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, va_list ap) {
14189 /* stridx_logfunc[] must be static to allow initializer with old compilers like BCC */
14190 static const duk_uint16_t stridx_logfunc[6] = {
14193 };
14194
14196
14197 if (level < 0) {
14198 level = 0;
14199 } else if (level > (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1) {
14200 level = (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1;
14201 }
14202
14205 duk_get_prop_stridx(ctx, -1, stridx_logfunc[level]);
14206 duk_dup(ctx, -2);
14207
14208 /* [ ... Logger clog logfunc clog ] */
14209
14210 duk_push_vsprintf(ctx, fmt, ap);
14211
14212 /* [ ... Logger clog logfunc clog(=this) msg ] */
14213
14214 duk_call_method(ctx, 1 /*nargs*/);
14215
14216 /* [ ... Logger clog res ] */
14217
14218 duk_pop_3(ctx);
14219}
14221DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...) {
14222 va_list ap;
14223
14225
14226 va_start(ap, fmt);
14227 duk_log_va(ctx, level, fmt, ap);
14228 va_end(ap);
14229}
14230#line 1 "duk_api_memory.c"
14231/*
14232 * Memory calls.
14233 */
14234
14235/* include removed: duk_internal.h */
14238 duk_hthread *thr = (duk_hthread *) ctx;
14239
14241
14242 return DUK_ALLOC_RAW(thr->heap, size);
14243}
14245DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) {
14246 duk_hthread *thr = (duk_hthread *) ctx;
14247
14249
14250 DUK_FREE_RAW(thr->heap, ptr);
14251}
14253DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) {
14254 duk_hthread *thr = (duk_hthread *) ctx;
14255
14257
14258 return DUK_REALLOC_RAW(thr->heap, ptr, size);
14259}
14261DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) {
14262 duk_hthread *thr = (duk_hthread *) ctx;
14263
14265
14266 return DUK_ALLOC(thr->heap, size);
14267}
14268
14269DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) {
14270 duk_hthread *thr = (duk_hthread *) ctx;
14271
14273
14274 DUK_FREE(thr->heap, ptr);
14275}
14276
14277DUK_EXTERNAL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) {
14278 duk_hthread *thr = (duk_hthread *) ctx;
14279
14281
14282 /*
14283 * Note: since this is an exposed API call, there should be
14284 * no way a mark-and-sweep could have a side effect on the
14285 * memory allocation behind 'ptr'; the pointer should never
14286 * be something that Duktape wants to change.
14287 *
14288 * Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
14289 * have the storage location here anyway).
14290 */
14291
14292 return DUK_REALLOC(thr->heap, ptr, size);
14293}
14296 duk_hthread *thr = (duk_hthread *) ctx;
14297 duk_heap *heap;
14298
14300 DUK_ASSERT(out_funcs != NULL);
14301 DUK_ASSERT(thr != NULL);
14302 DUK_ASSERT(thr->heap != NULL);
14303
14304 heap = thr->heap;
14305 out_funcs->alloc_func = heap->alloc_func;
14306 out_funcs->realloc_func = heap->realloc_func;
14307 out_funcs->free_func = heap->free_func;
14308 out_funcs->udata = heap->heap_udata;
14309}
14310
14311DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags) {
14312#ifdef DUK_USE_MARK_AND_SWEEP
14313 duk_hthread *thr = (duk_hthread *) ctx;
14314 duk_heap *heap;
14315
14316 DUK_UNREF(flags);
14317
14318 /* NULL accepted */
14319 if (!ctx) {
14320 return;
14321 }
14323 heap = thr->heap;
14324 DUK_ASSERT(heap != NULL);
14325
14326 DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
14327 duk_heap_mark_and_sweep(heap, 0);
14328#else
14329 DUK_D(DUK_DPRINT("mark-and-sweep requested by application but mark-and-sweep not enabled, ignoring"));
14330 DUK_UNREF(ctx);
14331 DUK_UNREF(flags);
14332#endif
14333}
14334#line 1 "duk_api_object.c"
14335/*
14336 * Object handling: property access and other support functions.
14337 */
14338
14339/* include removed: duk_internal.h */
14340
14341/*
14342 * Property handling
14343 *
14344 * The API exposes only the most common property handling functions.
14345 * The caller can invoke Ecmascript built-ins for full control (e.g.
14346 * defineProperty, getOwnPropertyDescriptor).
14347 */
14348
14350 duk_hthread *thr = (duk_hthread *) ctx;
14351 duk_tval *tv_obj;
14352 duk_tval *tv_key;
14353 duk_bool_t rc;
14354
14356
14357 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14358 * resize is not necessary for a property get right now.
14359 */
14360
14361 tv_obj = duk_require_tval(ctx, obj_index);
14362 tv_key = duk_require_tval(ctx, -1);
14363
14364 rc = duk_hobject_getprop(thr, tv_obj, tv_key);
14365 DUK_ASSERT(rc == 0 || rc == 1);
14366 /* a value is left on stack regardless of rc */
14367
14368 duk_remove(ctx, -2); /* remove key */
14369 return rc; /* 1 if property found, 0 otherwise */
14370}
14371
14374 DUK_ASSERT(key != NULL);
14375
14376 obj_index = duk_require_normalize_index(ctx, obj_index);
14377 duk_push_string(ctx, key);
14378 return duk_get_prop(ctx, obj_index);
14379}
14380
14383
14384 obj_index = duk_require_normalize_index(ctx, obj_index);
14385 duk_push_uarridx(ctx, arr_index);
14386 return duk_get_prop(ctx, obj_index);
14387}
14388
14390 duk_hthread *thr = (duk_hthread *) ctx;
14391
14393 DUK_ASSERT_DISABLE(stridx >= 0);
14395 DUK_UNREF(thr);
14396
14397 obj_index = duk_require_normalize_index(ctx, obj_index);
14398 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14399 return duk_get_prop(ctx, obj_index);
14400}
14401
14403 duk_bool_t rc;
14404
14406 DUK_ASSERT_DISABLE(stridx >= 0);
14408
14409 rc = duk_get_prop_stridx(ctx, obj_index, stridx);
14410 if (out_has_prop) {
14411 *out_has_prop = rc;
14412 }
14413 rc = duk_to_boolean(ctx, -1);
14414 DUK_ASSERT(rc == 0 || rc == 1);
14415 duk_pop(ctx);
14416 return rc;
14417}
14418
14420 duk_hthread *thr = (duk_hthread *) ctx;
14421 duk_tval *tv_obj;
14422 duk_tval *tv_key;
14423 duk_tval *tv_val;
14424 duk_small_int_t throw_flag;
14425 duk_bool_t rc;
14426
14427 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14428 * resize is not necessary for a property put right now (putprop protects
14429 * against it internally).
14430 */
14431
14432 /* Key and value indices are either (-2, -1) or (-1, -2). Given idx_key,
14433 * idx_val is always (idx_key ^ 0x01).
14434 */
14435 DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
14436 (idx_key == -1 && (idx_key ^ 1) == -2));
14437 tv_obj = duk_require_tval(ctx, obj_idx);
14438 tv_key = duk_require_tval(ctx, idx_key);
14439 tv_val = duk_require_tval(ctx, idx_key ^ 1);
14440 throw_flag = duk_is_strict_call(ctx);
14441
14442 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
14443 DUK_ASSERT(rc == 0 || rc == 1);
14444
14445 duk_pop_2(ctx); /* remove key and value */
14446 return rc; /* 1 if property found, 0 otherwise */
14447}
14448
14451 return duk__put_prop_shared(ctx, obj_idx, -2);
14452}
14453
14454DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
14456 DUK_ASSERT(key != NULL);
14457
14458 /* Careful here and with other duk_put_prop_xxx() helpers: the
14459 * target object and the property value may be in the same value
14460 * stack slot (unusual, but still conceptually clear).
14461 */
14462 obj_idx = duk_normalize_index(ctx, obj_idx);
14463 (void) duk_push_string(ctx, key);
14464 return duk__put_prop_shared(ctx, obj_idx, -1);
14465}
14466
14469
14470 obj_idx = duk_require_normalize_index(ctx, obj_idx);
14471 duk_push_uarridx(ctx, arr_idx);
14472 return duk__put_prop_shared(ctx, obj_idx, -1);
14473}
14474
14476 duk_hthread *thr = (duk_hthread *) ctx;
14477
14479 DUK_ASSERT_DISABLE(stridx >= 0);
14481 DUK_UNREF(thr);
14482
14483 obj_idx = duk_require_normalize_index(ctx, obj_idx);
14484 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14485 return duk__put_prop_shared(ctx, obj_idx, -1);
14486}
14487
14489 duk_hthread *thr = (duk_hthread *) ctx;
14490 duk_tval *tv_obj;
14491 duk_tval *tv_key;
14492 duk_small_int_t throw_flag;
14493 duk_bool_t rc;
14494
14496
14497 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14498 * resize is not necessary for a property delete right now.
14499 */
14500
14501 tv_obj = duk_require_tval(ctx, obj_index);
14502 tv_key = duk_require_tval(ctx, -1);
14503 throw_flag = duk_is_strict_call(ctx);
14505 rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
14506 DUK_ASSERT(rc == 0 || rc == 1);
14507
14508 duk_pop(ctx); /* remove key */
14509 return rc;
14510}
14511
14514 DUK_ASSERT(key != NULL);
14515
14516 obj_index = duk_require_normalize_index(ctx, obj_index);
14517 duk_push_string(ctx, key);
14518 return duk_del_prop(ctx, obj_index);
14519}
14520
14523
14524 obj_index = duk_require_normalize_index(ctx, obj_index);
14525 duk_push_uarridx(ctx, arr_index);
14526 return duk_del_prop(ctx, obj_index);
14527}
14528
14530 duk_hthread *thr = (duk_hthread *) ctx;
14531
14533 DUK_ASSERT_DISABLE(stridx >= 0);
14535 DUK_UNREF(thr);
14536
14537 obj_index = duk_require_normalize_index(ctx, obj_index);
14538 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14539 return duk_del_prop(ctx, obj_index);
14540}
14541
14543 duk_hthread *thr = (duk_hthread *) ctx;
14544 duk_tval *tv_obj;
14545 duk_tval *tv_key;
14546 duk_bool_t rc;
14549
14550 /* Note: copying tv_obj and tv_key to locals to shield against a valstack
14551 * resize is not necessary for a property existence check right now.
14552 */
14553
14554 tv_obj = duk_require_tval(ctx, obj_index);
14555 tv_key = duk_require_tval(ctx, -1);
14557 rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
14558 DUK_ASSERT(rc == 0 || rc == 1);
14559
14560 duk_pop(ctx); /* remove key */
14561 return rc; /* 1 if property found, 0 otherwise */
14562}
14563
14566 DUK_ASSERT(key != NULL);
14567
14568 obj_index = duk_require_normalize_index(ctx, obj_index);
14569 duk_push_string(ctx, key);
14570 return duk_has_prop(ctx, obj_index);
14571}
14572
14575
14576 obj_index = duk_require_normalize_index(ctx, obj_index);
14577 duk_push_uarridx(ctx, arr_index);
14578 return duk_has_prop(ctx, obj_index);
14579}
14580
14582 duk_hthread *thr = (duk_hthread *) ctx;
14583
14585 DUK_ASSERT_DISABLE(stridx >= 0);
14587 DUK_UNREF(thr);
14588
14589 obj_index = duk_require_normalize_index(ctx, obj_index);
14590 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14591 return duk_has_prop(ctx, obj_index);
14592}
14593
14594/* Define own property without inheritance looks and such. This differs from
14595 * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
14596 * not invoked by this method. The caller must be careful to invoke any such
14597 * behaviors if necessary.
14598 */
14599DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags) {
14600 duk_hthread *thr = (duk_hthread *) ctx;
14601 duk_hobject *obj;
14602 duk_hstring *key;
14603
14605
14606 obj = duk_require_hobject(ctx, obj_index);
14607 DUK_ASSERT(obj != NULL);
14608 key = duk_to_hstring(ctx, -2);
14609 DUK_ASSERT(key != NULL);
14610 DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
14611
14612 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14614 duk_pop(ctx); /* pop key */
14615}
14616
14617DUK_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) {
14618 duk_hthread *thr = (duk_hthread *) ctx;
14619 duk_hobject *obj;
14620
14622
14623 obj = duk_require_hobject(ctx, obj_index);
14624 DUK_ASSERT(obj != NULL);
14625
14626 duk_hobject_define_property_internal_arridx(thr, obj, arr_index, desc_flags);
14627 /* value popped by call */
14628}
14629
14631 duk_hthread *thr = (duk_hthread *) ctx;
14633 duk_hstring *key;
14634
14636 DUK_ASSERT_DISABLE(stridx >= 0);
14638
14639 obj = duk_require_hobject(ctx, obj_index);
14640 DUK_ASSERT(obj != NULL);
14641 key = DUK_HTHREAD_GET_STRING(thr, stridx);
14642 DUK_ASSERT(key != NULL);
14643 DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
14644
14645 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14646 /* value popped by call */
14647}
14648
14650 duk_hthread *thr = (duk_hthread *) ctx;
14651 duk_hobject *obj;
14652 duk_hstring *key;
14653
14655 DUK_ASSERT_DISABLE(stridx >= 0);
14657 DUK_ASSERT_DISABLE(builtin_idx >= 0);
14659
14660 obj = duk_require_hobject(ctx, obj_index);
14661 DUK_ASSERT(obj != NULL);
14662 key = DUK_HTHREAD_GET_STRING(thr, stridx);
14663 DUK_ASSERT(key != NULL);
14664
14665 duk_push_hobject(ctx, thr->builtins[builtin_idx]);
14666 duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14667 /* value popped by call */
14668}
14669
14670/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
14671 * setter/getter into an object property. This is needed by the 'arguments'
14672 * object creation code, function instance creation code, and Function.prototype.bind().
14673 */
14674
14676 duk_hthread *thr = (duk_hthread *) ctx;
14677 duk_hobject *obj = duk_require_hobject(ctx, obj_index);
14679 duk_hobject_define_accessor_internal(thr, obj, DUK_HTHREAD_GET_STRING(thr, stridx), thrower, thrower, desc_flags);
14680}
14681
14682/* Object.defineProperty() equivalent C binding. */
14683DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags) {
14684 duk_hthread *thr = (duk_hthread *) ctx;
14685 duk_idx_t idx_base;
14686 duk_hobject *obj;
14687 duk_hstring *key;
14688 duk_idx_t idx_value;
14689 duk_hobject *get;
14690 duk_hobject *set;
14691 duk_uint_t is_data_desc;
14692 duk_uint_t is_acc_desc;
14693
14695
14696 obj = duk_require_hobject(ctx, obj_index);
14697
14698 is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
14699 is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
14700 if (is_data_desc && is_acc_desc) {
14701 /* "Have" flags must not be conflicting so that they would
14702 * apply to both a plain property and an accessor at the same
14703 * time.
14704 */
14705 goto fail_invalid_desc;
14706 }
14707
14708 idx_base = duk_get_top_index(ctx);
14709 if (flags & DUK_DEFPROP_HAVE_SETTER) {
14713 set = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
14714 if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
14715 goto fail_not_callable;
14716 }
14717 idx_base--;
14718 } else {
14719 set = NULL;
14720 }
14721 if (flags & DUK_DEFPROP_HAVE_GETTER) {
14725 get = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
14726 if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
14727 goto fail_not_callable;
14728 }
14729 idx_base--;
14730 } else {
14731 get = NULL;
14732 }
14733 if (flags & DUK_DEFPROP_HAVE_VALUE) {
14734 idx_value = idx_base;
14735 idx_base--;
14736 } else {
14737 idx_value = (duk_idx_t) -1;
14738 }
14739 key = duk_require_hstring(ctx, idx_base);
14740
14741 duk_require_valid_index(ctx, idx_base);
14742
14744 flags /*defprop_flags*/,
14745 obj,
14746 key,
14747 idx_value,
14748 get,
14749 set);
14750
14751 /* Clean up stack */
14752
14753 duk_set_top(ctx, idx_base);
14754
14755 /* [ ... obj ... ] */
14756
14757 return;
14759 fail_invalid_desc:
14761 return;
14762
14763 fail_not_callable:
14765 return;
14766}
14767
14768/*
14769 * Object related
14770 *
14771 * Note: seal() and freeze() are accessible through Ecmascript bindings,
14772 * and are not exposed through the API.
14774
14775DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) {
14776 duk_hthread *thr = (duk_hthread *) ctx;
14777 duk_hobject *obj;
14778
14780
14781 obj = duk_get_hobject(ctx, obj_index);
14782 if (obj) {
14783 /* Note: this may fail, caller should protect the call if necessary */
14784 duk_hobject_compact_props(thr, obj);
14785 }
14786}
14787
14788/* XXX: the duk_hobject_enum.c stack APIs should be reworked */
14789
14790DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) {
14792
14793 duk_dup(ctx, obj_index);
14795 duk_hobject_enumerator_create(ctx, enum_flags); /* [target] -> [enum] */
14796}
14797
14798DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) {
14800
14801 duk_require_hobject(ctx, enum_index);
14802 duk_dup(ctx, enum_index);
14803 return duk_hobject_enumerator_next(ctx, get_value);
14804}
14805
14806/*
14807 * Helpers for writing multiple properties
14809
14811 const duk_function_list_entry *ent = funcs;
14812
14814
14815 obj_index = duk_require_normalize_index(ctx, obj_index);
14816 if (ent != NULL) {
14817 while (ent->key != NULL) {
14818 duk_push_c_function(ctx, ent->value, ent->nargs);
14819 duk_put_prop_string(ctx, obj_index, ent->key);
14820 ent++;
14821 }
14822 }
14823}
14824
14825DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers) {
14826 const duk_number_list_entry *ent = numbers;
14829
14830 obj_index = duk_require_normalize_index(ctx, obj_index);
14831 if (ent != NULL) {
14832 while (ent->key != NULL) {
14833 duk_push_number(ctx, ent->value);
14834 duk_put_prop_string(ctx, obj_index, ent->key);
14835 ent++;
14836 }
14837 }
14838}
14839
14840/*
14841 * Shortcut for accessing global object properties
14843
14845 duk_hthread *thr = (duk_hthread *) ctx;
14846 duk_bool_t ret;
14847
14850
14851 /* XXX: direct implementation */
14852
14854 ret = duk_get_prop_string(ctx, -1, key);
14855 duk_remove(ctx, -2);
14856 return ret;
14857}
14858
14860 duk_hthread *thr = (duk_hthread *) ctx;
14861 duk_bool_t ret;
14865
14866 /* XXX: direct implementation */
14867
14869 duk_insert(ctx, -2);
14870 ret = duk_put_prop_string(ctx, -2, key); /* [ ... global val ] -> [ ... global ] */
14871 duk_pop(ctx);
14872 return ret;
14873}
14874
14875/*
14876 * Object prototype
14877 */
14878
14880 duk_hthread *thr = (duk_hthread *) ctx;
14881 duk_hobject *obj;
14883
14885 DUK_UNREF(thr);
14886
14887 obj = duk_require_hobject(ctx, index);
14888 DUK_ASSERT(obj != NULL);
14889
14890 /* XXX: shared helper for duk_push_hobject_or_undefined()? */
14892 if (proto) {
14893 duk_push_hobject(ctx, proto);
14894 } else {
14895 duk_push_undefined(ctx);
14896 }
14897}
14898
14900 duk_hthread *thr = (duk_hthread *) ctx;
14901 duk_hobject *obj;
14903
14905
14906 obj = duk_require_hobject(ctx, index);
14907 DUK_ASSERT(obj != NULL);
14910 proto = duk_get_hobject(ctx, -1);
14911 /* proto can also be NULL here (allowed explicitly) */
14912
14913#if defined(DUK_USE_ROM_OBJECTS)
14915 DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
14916 return;
14918#endif
14919
14921
14922 duk_pop(ctx);
14924
14925/*
14926 * Object finalizer
14927 */
14928
14929/* XXX: these could be implemented as macros calling an internal function
14930 * directly.
14931 * XXX: same issue as with Duktape.fin: there's no way to delete the property
14932 * now (just set it to undefined).
14933 */
14936
14938}
14939
14942
14944}
14945#line 1 "duk_api_stack.c"
14946/*
14947 * API calls related to general value stack manipulation: resizing the value
14948 * stack, pushing and popping values, type checking and reading values,
14949 * coercing values, etc.
14950 *
14951 * Also contains internal functions (such as duk_get_tval()), defined
14952 * in duk_api_internal.h, with semantics similar to the public API.
14953 */
14955/* XXX: repetition of stack pre-checks -> helper or macro or inline */
14956/* XXX: shared api error strings, and perhaps even throw code for rare cases? */
14957
14958/* include removed: duk_internal.h */
14959
14960/*
14961 * Forward declarations
14962 */
14963
14965
14966/*
14967 * Global state for working around missing variadic macros
14968 */
14970#ifndef DUK_USE_VARIADIC_MACROS
14973#endif
14974
14975/*
14976 * Misc helpers
14977 */
14979/* Check that there's room to push one value. */
14980#if defined(DUK_USE_VALSTACK_UNSAFE)
14981/* Faster but value stack overruns are memory unsafe. */
14982#define DUK__CHECK_SPACE() do { \
14983 DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
14984 } while (0)
14985#else
14986#define DUK__CHECK_SPACE() do { \
14987 if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
14988 DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \
14989 } \
14990 } while (0)
14991#endif
14992
14994
14996 duk_hthread *thr;
14997 duk_tval *tv;
14999 duk_double_t d;
15000
15001 thr = (duk_hthread *) ctx;
15002
15003 tv = duk_get_tval(ctx, index);
15004 if (tv == NULL) {
15005 goto error_notnumber;
15006 }
15007
15008 /*
15009 * Special cases like NaN and +/- Infinity are handled explicitly
15010 * because a plain C coercion from double to int handles these cases
15011 * in undesirable ways. For instance, NaN may coerce to INT_MIN
15012 * (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
15013 *
15014 * This double-to-int coercion differs from ToInteger() because it
15015 * has a finite range (ToInteger() allows e.g. +/- Infinity). It
15016 * also differs from ToInt32() because the INT_MIN/INT_MAX clamping
15017 * depends on the size of the int type on the platform. In particular,
15018 * on platforms with a 64-bit int type, the full range is allowed.
15019 */
15020
15021#if defined(DUK_USE_FASTINT)
15022 if (DUK_TVAL_IS_FASTINT(tv)) {
15023 duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
15024#if (DUK_INT_MAX <= 0x7fffffffL)
15025 /* Clamping only necessary for 32-bit ints. */
15026 if (t < DUK_INT_MIN) {
15027 t = DUK_INT_MIN;
15028 } else if (t > DUK_INT_MAX) {
15029 t = DUK_INT_MAX;
15030 }
15031#endif
15032 return (duk_int_t) t;
15033 }
15034#endif
15035
15036 if (DUK_TVAL_IS_NUMBER(tv)) {
15037 d = DUK_TVAL_GET_NUMBER(tv);
15039 if (c == DUK_FP_NAN) {
15040 return 0;
15041 } else if (d < (duk_double_t) DUK_INT_MIN) {
15042 /* covers -Infinity */
15043 return DUK_INT_MIN;
15044 } else if (d > (duk_double_t) DUK_INT_MAX) {
15045 /* covers +Infinity */
15046 return DUK_INT_MAX;
15047 } else {
15048 /* coerce towards zero */
15049 return (duk_int_t) d;
15050 }
15051 }
15052
15053 error_notnumber:
15054
15055 if (require) {
15057 /* not reachable */
15058 }
15059 return 0;
15060}
15061
15063 duk_hthread *thr;
15064 duk_tval *tv;
15066 duk_double_t d;
15067
15068 /* Same as above but for unsigned int range. */
15069
15070 thr = (duk_hthread *) ctx;
15071
15072 tv = duk_get_tval(ctx, index);
15073 if (tv == NULL) {
15074 goto error_notnumber;
15075 }
15076
15077#if defined(DUK_USE_FASTINT)
15078 if (DUK_TVAL_IS_FASTINT(tv)) {
15079 duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
15080 if (t < 0) {
15081 t = 0;
15082 }
15083#if (DUK_UINT_MAX <= 0xffffffffUL)
15084 /* Clamping only necessary for 32-bit ints. */
15085 else if (t > DUK_UINT_MAX) {
15086 t = DUK_UINT_MAX;
15087 }
15088#endif
15089 return (duk_uint_t) t;
15090 }
15091#endif
15092
15093 if (DUK_TVAL_IS_NUMBER(tv)) {
15094 d = DUK_TVAL_GET_NUMBER(tv);
15096 if (c == DUK_FP_NAN) {
15097 return 0;
15098 } else if (d < 0.0) {
15099 /* covers -Infinity */
15100 return (duk_uint_t) 0;
15101 } else if (d > (duk_double_t) DUK_UINT_MAX) {
15102 /* covers +Infinity */
15103 return (duk_uint_t) DUK_UINT_MAX;
15104 } else {
15105 /* coerce towards zero */
15106 return (duk_uint_t) d;
15107 }
15108 }
15109
15110 error_notnumber:
15112 if (require) {
15114 /* not reachable */
15115 }
15116 return 0;
15117}
15118
15119/*
15120 * Stack index validation/normalization and getting a stack duk_tval ptr.
15121 *
15122 * These are called by many API entrypoints so the implementations must be
15123 * fast and "inlined".
15124 *
15125 * There's some repetition because of this; keep the functions in sync.
15126 */
15127
15129 duk_hthread *thr = (duk_hthread *) ctx;
15130 duk_uidx_t vs_size;
15131 duk_uidx_t uindex;
15132
15135
15136 /* Care must be taken to avoid pointer wrapping in the index
15137 * validation. For instance, on a 32-bit platform with 8-byte
15138 * duk_tval the index 0x20000000UL would wrap the memory space
15139 * once.
15140 */
15141
15142 /* Assume value stack sizes (in elements) fits into duk_idx_t. */
15144 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15145 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15146
15147 if (index < 0) {
15148 uindex = vs_size + (duk_uidx_t) index;
15149 } else {
15150 /* since index non-negative */
15152 uindex = (duk_uidx_t) index;
15153 }
15154
15155 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15156 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15157
15158 if (DUK_LIKELY(uindex < vs_size)) {
15159 return (duk_idx_t) uindex;
15160 }
15161 return DUK_INVALID_INDEX;
15162}
15163
15165 duk_hthread *thr = (duk_hthread *) ctx;
15166 duk_uidx_t vs_size;
15167 duk_uidx_t uindex;
15168
15171
15173 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15174 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15175
15176 if (index < 0) {
15177 uindex = vs_size + (duk_uidx_t) index;
15178 } else {
15180 uindex = (duk_uidx_t) index;
15181 }
15182
15183 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15184 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15185
15186 if (DUK_LIKELY(uindex < vs_size)) {
15187 return (duk_idx_t) uindex;
15188 }
15190 return 0; /* unreachable */
15191}
15192
15194 duk_hthread *thr = (duk_hthread *) ctx;
15195 duk_uidx_t vs_size;
15196 duk_uidx_t uindex;
15197
15200
15202 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15203 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15205 if (index < 0) {
15206 uindex = vs_size + (duk_uidx_t) index;
15207 } else {
15209 uindex = (duk_uidx_t) index;
15210 }
15211
15212 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15213 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15214
15215 if (DUK_LIKELY(uindex < vs_size)) {
15216 return thr->valstack_bottom + uindex;
15217 }
15218 return NULL;
15219}
15220
15222 duk_hthread *thr = (duk_hthread *) ctx;
15223 duk_uidx_t vs_size;
15224 duk_uidx_t uindex;
15225
15228
15230 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15231 DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
15232
15233 /* Use unsigned arithmetic to optimize comparison. */
15234 if (index < 0) {
15235 uindex = vs_size + (duk_uidx_t) index;
15236 } else {
15238 uindex = (duk_uidx_t) index;
15239 }
15240
15241 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15242 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15244 if (DUK_LIKELY(uindex < vs_size)) {
15245 return thr->valstack_bottom + uindex;
15246 }
15248 return NULL;
15249}
15250
15251/* Non-critical. */
15255
15256 return (duk_normalize_index(ctx, index) >= 0);
15257}
15258
15259/* Non-critical. */
15261 duk_hthread *thr = (duk_hthread *) ctx;
15262
15265
15266 if (duk_normalize_index(ctx, index) < 0) {
15268 return; /* unreachable */
15269 }
15270}
15272/*
15273 * Value stack top handling
15274 */
15275
15277 duk_hthread *thr = (duk_hthread *) ctx;
15278
15280
15281 return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
15282}
15283
15284/* Set stack top within currently allocated range, but don't reallocate.
15285 * This is performance critical especially for call handling, so whenever
15286 * changing, profile and look at generated code.
15287 */
15289 duk_hthread *thr = (duk_hthread *) ctx;
15290 duk_uidx_t vs_size;
15291 duk_uidx_t vs_limit;
15292 duk_uidx_t uindex;
15293 duk_tval *tv;
15294
15297
15300 vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15301 vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
15302
15303 if (index < 0) {
15304 /* Negative indices are always within allocated stack but
15305 * must not go below zero index.
15306 */
15307 uindex = vs_size + (duk_uidx_t) index;
15308 } else {
15309 /* Positive index can be higher than valstack top but must
15310 * not go above allocated stack (equality is OK).
15311 */
15312 uindex = (duk_uidx_t) index;
15313 }
15314
15315 /* DUK_INVALID_INDEX won't be accepted as a valid index. */
15316 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15317 DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
15318
15319#if defined(DUK_USE_VALSTACK_UNSAFE)
15320 DUK_ASSERT(uindex <= vs_limit);
15321 DUK_UNREF(vs_limit);
15322#else
15323 if (DUK_UNLIKELY(uindex > vs_limit)) {
15325 return; /* unreachable */
15326 }
15327#endif
15328 DUK_ASSERT(uindex <= vs_limit);
15329
15330 /* Handle change in value stack top. Respect value stack
15331 * initialization policy: 'undefined' above top. Note that
15332 * DECREF may cause a side effect that reallocates valstack,
15333 * so must relookup after DECREF.
15334 */
15335
15336 if (uindex >= vs_size) {
15337 /* Stack size increases or stays the same. */
15338#if defined(DUK_USE_ASSERTIONS)
15339 duk_uidx_t count;
15340
15341 count = uindex - vs_size;
15342 while (count != 0) {
15343 count--;
15344 tv = thr->valstack_top + count;
15346 }
15347#endif
15348 thr->valstack_top = thr->valstack_bottom + uindex;
15349 } else {
15350 /* Stack size decreases. */
15351#if defined(DUK_USE_REFERENCE_COUNTING)
15352 duk_uidx_t count;
15353
15354 count = vs_size - uindex;
15355 DUK_ASSERT(count > 0);
15356 while (count > 0) {
15357 count--;
15358 tv = --thr->valstack_top; /* tv -> value just before prev top value; must relookup */
15359 DUK_ASSERT(tv >= thr->valstack_bottom);
15360 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
15361 }
15362#else /* DUK_USE_REFERENCE_COUNTING */
15363 duk_uidx_t count;
15364 duk_tval *tv_end;
15365
15366 count = vs_size - uindex;
15367 tv = thr->valstack_top;
15368 tv_end = tv - count;
15369 DUK_ASSERT(tv > tv_end);
15370 do {
15371 tv--;
15373 } while (tv != tv_end);
15374 thr->valstack_top = tv_end;
15375#endif /* DUK_USE_REFERENCE_COUNTING */
15376 }
15377}
15378
15380 duk_hthread *thr = (duk_hthread *) ctx;
15381 duk_idx_t ret;
15382
15384
15385 ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
15386 if (DUK_UNLIKELY(ret < 0)) {
15387 /* Return invalid index; if caller uses this without checking
15388 * in another API call, the index won't map to a valid stack
15389 * entry.
15390 */
15391 return DUK_INVALID_INDEX;
15392 }
15393 return ret;
15394}
15395
15397 duk_hthread *thr = (duk_hthread *) ctx;
15398 duk_idx_t ret;
15399
15401
15402 ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
15403 if (DUK_UNLIKELY(ret < 0)) {
15404 DUK_ERROR_API_INDEX(thr, -1);
15405 return 0; /* unreachable */
15406 }
15407 return ret;
15408}
15409
15410/*
15411 * Value stack resizing.
15412 *
15413 * This resizing happens above the current "top": the value stack can be
15414 * grown or shrunk, but the "top" is not affected. The value stack cannot
15415 * be resized to a size below the current "top".
15416 *
15417 * The low level reallocation primitive must carefully recompute all value
15418 * stack pointers, and must also work if ALL pointers are NULL. The resize
15419 * is quite tricky because the valstack realloc may cause a mark-and-sweep,
15420 * which may run finalizers. Running finalizers may resize the valstack
15421 * recursively (the same value stack we're working on). So, after realloc
15422 * returns, we know that the valstack "top" should still be the same (there
15423 * should not be live values above the "top"), but its underlying size and
15424 * pointer may have changed.
15425 */
15426
15427/* XXX: perhaps refactor this to allow caller to specify some parameters, or
15428 * at least a 'compact' flag which skips any spare or round-up .. useful for
15429 * emergency gc.
15430 */
15431
15433 duk_hthread *thr = (duk_hthread *) ctx;
15434 duk_ptrdiff_t old_bottom_offset;
15435 duk_ptrdiff_t old_top_offset;
15436 duk_ptrdiff_t old_end_offset_post;
15437#ifdef DUK_USE_DEBUG
15438 duk_ptrdiff_t old_end_offset_pre;
15439 duk_tval *old_valstack_pre;
15440 duk_tval *old_valstack_post;
15441#endif
15442 duk_tval *new_valstack;
15443 duk_size_t new_alloc_size;
15444 duk_tval *p;
15445
15447 DUK_ASSERT(thr != NULL);
15448 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15450 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15451 DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size); /* can't resize below 'top' */
15452 DUK_ASSERT(new_size <= thr->valstack_max); /* valstack limit caller has check, prevents wrapping */
15453 DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval)); /* specific assert for wrapping */
15454
15455 /* get pointer offsets for tweaking below */
15456 old_bottom_offset = (((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack));
15457 old_top_offset = (((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack));
15458#ifdef DUK_USE_DEBUG
15459 old_end_offset_pre = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* not very useful, used for debugging */
15460 old_valstack_pre = thr->valstack;
15461#endif
15462
15463 /* Allocate a new valstack.
15464 *
15465 * Note: cannot use a plain DUK_REALLOC() because a mark-and-sweep may
15466 * invalidate the original thr->valstack base pointer inside the realloc
15467 * process. See doc/memory-management.rst.
15468 */
15469
15470 new_alloc_size = sizeof(duk_tval) * new_size;
15471 new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
15472 if (!new_valstack) {
15473 /* Because new_size != 0, if condition doesn't need to be
15474 * (new_valstack != NULL || new_size == 0).
15475 */
15476 DUK_ASSERT(new_size != 0);
15477 DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
15478 (unsigned long) new_size, (unsigned long) new_alloc_size));
15479 return 0;
15480 }
15481
15482 /* Note: the realloc may have triggered a mark-and-sweep which may
15483 * have resized our valstack internally. However, the mark-and-sweep
15484 * MUST NOT leave the stack bottom/top in a different state. Particular
15485 * assumptions and facts:
15486 *
15487 * - The thr->valstack pointer may be different after realloc,
15488 * and the offset between thr->valstack_end <-> thr->valstack
15489 * may have changed.
15490 * - The offset between thr->valstack_bottom <-> thr->valstack
15491 * and thr->valstack_top <-> thr->valstack MUST NOT have changed,
15492 * because mark-and-sweep must adhere to a strict stack policy.
15493 * In other words, logical bottom and top MUST NOT have changed.
15494 * - All values above the top are unreachable but are initialized
15495 * to UNDEFINED, up to the post-realloc valstack_end.
15496 * - 'old_end_offset' must be computed after realloc to be correct.
15497 */
15498
15499 DUK_ASSERT((((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack)) == old_bottom_offset);
15500 DUK_ASSERT((((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack)) == old_top_offset);
15501
15502 /* success, fixup pointers */
15503 old_end_offset_post = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* must be computed after realloc */
15504#ifdef DUK_USE_DEBUG
15505 old_valstack_post = thr->valstack;
15506#endif
15507 thr->valstack = new_valstack;
15508 thr->valstack_end = new_valstack + new_size;
15509#if !defined(DUK_USE_PREFER_SIZE)
15510 thr->valstack_size = new_size;
15511#endif
15512 thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_bottom_offset);
15513 thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_top_offset);
15514
15515 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15517 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15518
15519 /* useful for debugging */
15520#ifdef DUK_USE_DEBUG
15521 if (old_end_offset_pre != old_end_offset_post) {
15522 DUK_D(DUK_DPRINT("valstack was resized during valstack_resize(), probably by mark-and-sweep; "
15523 "end offset changed: %lu -> %lu",
15524 (unsigned long) old_end_offset_pre,
15525 (unsigned long) old_end_offset_post));
15526 }
15527 if (old_valstack_pre != old_valstack_post) {
15528 DUK_D(DUK_DPRINT("valstack pointer changed during valstack_resize(), probably by mark-and-sweep: %p -> %p",
15529 (void *) old_valstack_pre,
15530 (void *) old_valstack_post));
15531 }
15532#endif
15533
15534 DUK_DD(DUK_DDPRINT("resized valstack to %lu elements (%lu bytes), bottom=%ld, top=%ld, "
15535 "new pointers: start=%p end=%p bottom=%p top=%p",
15536 (unsigned long) new_size, (unsigned long) new_alloc_size,
15537 (long) (thr->valstack_bottom - thr->valstack),
15538 (long) (thr->valstack_top - thr->valstack),
15539 (void *) thr->valstack, (void *) thr->valstack_end,
15540 (void *) thr->valstack_bottom, (void *) thr->valstack_top));
15541
15542 /* Init newly allocated slots (only). */
15543 p = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + old_end_offset_post);
15544 while (p < thr->valstack_end) {
15545 /* Never executed if new size is smaller. */
15547 p++;
15548 }
15549
15550 /* Assert for value stack initialization policy. */
15551#if defined(DUK_USE_ASSERTIONS)
15552 p = thr->valstack_top;
15553 while (p < thr->valstack_end) {
15555 p++;
15556 }
15557#endif
15558
15559 return 1;
15560}
15561
15564 duk_size_t min_new_size,
15565 duk_small_uint_t flags) {
15566 duk_hthread *thr = (duk_hthread *) ctx;
15567 duk_size_t old_size;
15568 duk_size_t new_size;
15569 duk_bool_t is_shrink = 0;
15570 duk_small_uint_t shrink_flag = (flags & DUK_VSRESIZE_FLAG_SHRINK);
15571 duk_small_uint_t compact_flag = (flags & DUK_VSRESIZE_FLAG_COMPACT);
15572 duk_small_uint_t throw_flag = (flags & DUK_VSRESIZE_FLAG_THROW);
15573
15574 DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, "
15575 "curr_bottom=%ld, shrink=%d, compact=%d, throw=%d",
15576 (unsigned long) min_new_size,
15577 (long) (thr->valstack_end - thr->valstack),
15578 (long) (thr->valstack_top - thr->valstack),
15579 (long) (thr->valstack_bottom - thr->valstack),
15580 (int) shrink_flag, (int) compact_flag, (int) throw_flag));
15581
15583 DUK_ASSERT(thr != NULL);
15584 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15586 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15587
15588#if defined(DUK_USE_PREFER_SIZE)
15589 old_size = (duk_size_t) (thr->valstack_end - thr->valstack);
15590#else
15591 DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
15592 old_size = thr->valstack_size;
15593#endif
15594
15595 if (min_new_size <= old_size) {
15596 is_shrink = 1;
15597 if (!shrink_flag ||
15598 old_size - min_new_size < DUK_VALSTACK_SHRINK_THRESHOLD) {
15599 DUK_DDD(DUK_DDDPRINT("no need to grow or shrink valstack"));
15600 return 1;
15601 }
15602 }
15603
15604 new_size = min_new_size;
15605 if (!compact_flag) {
15606 if (is_shrink) {
15607 /* shrink case; leave some spare */
15608 new_size += DUK_VALSTACK_SHRINK_SPARE;
15609 }
15610
15611 /* round up roughly to next 'grow step' */
15612 new_size = (new_size / DUK_VALSTACK_GROW_STEP + 1) * DUK_VALSTACK_GROW_STEP;
15613 }
15614
15615 DUK_DD(DUK_DDPRINT("want to %s valstack: %lu -> %lu elements (min_new_size %lu)",
15616 (const char *) (new_size > old_size ? "grow" : "shrink"),
15617 (unsigned long) old_size, (unsigned long) new_size,
15618 (unsigned long) min_new_size));
15619
15620 if (new_size > thr->valstack_max) {
15621 /* Note: may be triggered even if minimal new_size would not reach the limit,
15622 * plan limit accordingly (taking DUK_VALSTACK_GROW_STEP into account).
15623 */
15624 if (throw_flag) {
15626 } else {
15627 return 0;
15628 }
15629 }
15630
15631 /*
15632 * When resizing the valstack, a mark-and-sweep may be triggered for
15633 * the allocation of the new valstack. If the mark-and-sweep needs
15634 * to use our thread for something, it may cause *the same valstack*
15635 * to be resized recursively. This happens e.g. when mark-and-sweep
15636 * finalizers are called. This is taken into account carefully in
15637 * duk__resize_valstack().
15638 *
15639 * 'new_size' is known to be <= valstack_max, which ensures that
15640 * size_t and pointer arithmetic won't wrap in duk__resize_valstack().
15641 */
15642
15643 if (!duk__resize_valstack(ctx, new_size)) {
15644 if (is_shrink) {
15645 DUK_DD(DUK_DDPRINT("valstack resize failed, but is a shrink, ignore"));
15646 return 1;
15647 }
15648
15649 DUK_DD(DUK_DDPRINT("valstack resize failed"));
15650
15651 if (throw_flag) {
15653 } else {
15654 return 0;
15655 }
15656 }
15657
15658 DUK_DDD(DUK_DDDPRINT("valstack resize successful"));
15659 return 1;
15660}
15661
15663 duk_hthread *thr = (duk_hthread *) ctx;
15664 duk_size_t min_new_size;
15665
15668
15669 if (DUK_UNLIKELY(extra < 0)) {
15670 /* Clamping to zero makes the API more robust to calling code
15671 * calculation errors.
15672 */
15673 extra = 0;
15674 }
15675
15676 min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
15677 return duk_valstack_resize_raw(ctx,
15678 min_new_size, /* min_new_size */
15679 0 /* no shrink */ | /* flags */
15680 0 /* no compact */ |
15681 0 /* no throw */);
15682}
15683
15685 duk_hthread *thr = (duk_hthread *) ctx;
15686 duk_size_t min_new_size;
15687
15690
15691 if (DUK_UNLIKELY(extra < 0)) {
15692 /* Clamping to zero makes the API more robust to calling code
15693 * calculation errors.
15694 */
15695 extra = 0;
15696 }
15697
15698 min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
15699 (void) duk_valstack_resize_raw(ctx,
15700 min_new_size, /* min_new_size */
15701 0 /* no shrink */ | /* flags */
15702 0 /* no compact */ |
15704}
15705
15707 duk_size_t min_new_size;
15708
15710
15711 if (DUK_UNLIKELY(top < 0)) {
15712 /* Clamping to zero makes the API more robust to calling code
15713 * calculation errors.
15714 */
15715 top = 0;
15716 }
15717
15718 min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
15719 return duk_valstack_resize_raw(ctx,
15720 min_new_size, /* min_new_size */
15721 0 /* no shrink */ | /* flags */
15722 0 /* no compact */ |
15723 0 /* no throw */);
15724}
15725
15727 duk_size_t min_new_size;
15728
15730
15731 if (DUK_UNLIKELY(top < 0)) {
15732 /* Clamping to zero makes the API more robust to calling code
15733 * calculation errors.
15734 */
15735 top = 0;
15736 }
15737
15738 min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
15739 (void) duk_valstack_resize_raw(ctx,
15740 min_new_size, /* min_new_size */
15741 0 /* no shrink */ | /* flags */
15742 0 /* no compact */ |
15744}
15745
15746/*
15747 * Basic stack manipulation: swap, dup, insert, replace, etc
15748 */
15749
15750DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
15752 duk_tval *tv2;
15753 duk_tval tv_tmp;
15754
15756
15757 tv1 = duk_require_tval(ctx, index1);
15758 DUK_ASSERT(tv1 != NULL);
15759 tv2 = duk_require_tval(ctx, index2);
15760 DUK_ASSERT(tv2 != NULL);
15761
15762 /* If tv1==tv2 this is a NOP, no check is needed */
15763 DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
15764 DUK_TVAL_SET_TVAL(tv1, tv2);
15765 DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
15766}
15767
15770
15771 duk_swap(ctx, index, -1);
15772}
15773
15775 duk_hthread *thr;
15776 duk_tval *tv_from;
15777 duk_tval *tv_to;
15778
15780 thr = (duk_hthread *) ctx;
15782
15783 tv_from = duk_require_tval(ctx, from_index);
15784 tv_to = thr->valstack_top++;
15785 DUK_ASSERT(tv_from != NULL);
15786 DUK_ASSERT(tv_to != NULL);
15787 DUK_TVAL_SET_TVAL(tv_to, tv_from);
15788 DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
15789}
15790
15792 duk_hthread *thr;
15793 duk_tval *tv_from;
15794 duk_tval *tv_to;
15797 thr = (duk_hthread *) ctx;
15799
15800 if (thr->valstack_top - thr->valstack_bottom <= 0) {
15801 DUK_ERROR_API_INDEX(thr, -1);
15802 return; /* unreachable */
15803 }
15804 tv_from = thr->valstack_top - 1;
15805 tv_to = thr->valstack_top++;
15806 DUK_ASSERT(tv_from != NULL);
15807 DUK_ASSERT(tv_to != NULL);
15808 DUK_TVAL_SET_TVAL(tv_to, tv_from);
15809 DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
15810}
15811
15812DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index) {
15813 duk_tval *p;
15814 duk_tval *q;
15815 duk_tval tv_tmp;
15816 duk_size_t nbytes;
15817
15819
15820 p = duk_require_tval(ctx, to_index);
15821 DUK_ASSERT(p != NULL);
15822 q = duk_require_tval(ctx, -1);
15823 DUK_ASSERT(q != NULL);
15824
15825 DUK_ASSERT(q >= p);
15826
15827 /* nbytes
15828 * <--------->
15829 * [ ... | p | x | x | q ]
15830 * => [ ... | q | p | x | x ]
15831 */
15832
15833 nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
15834
15835 DUK_DDD(DUK_DDDPRINT("duk_insert: to_index=%ld, p=%p, q=%p, nbytes=%lu",
15836 (long) to_index, (void *) p, (void *) q, (unsigned long) nbytes));
15837
15838 /* No net refcount changes. */
15839
15840 if (nbytes > 0) {
15841 DUK_TVAL_SET_TVAL(&tv_tmp, q);
15842 DUK_ASSERT(nbytes > 0);
15843 DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);
15844 DUK_TVAL_SET_TVAL(p, &tv_tmp);
15845 } else {
15846 /* nop: insert top to top */
15847 DUK_ASSERT(nbytes == 0);
15848 DUK_ASSERT(p == q);
15849 }
15850}
15851
15852DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index) {
15853 duk_hthread *thr = (duk_hthread *) ctx;
15854 duk_tval *tv1;
15855 duk_tval *tv2;
15856 duk_tval tv_tmp;
15857
15859
15860 tv1 = duk_require_tval(ctx, -1);
15861 DUK_ASSERT(tv1 != NULL);
15862 tv2 = duk_require_tval(ctx, to_index);
15863 DUK_ASSERT(tv2 != NULL);
15864
15865 /* For tv1 == tv2, both pointing to stack top, the end result
15866 * is same as duk_pop(ctx).
15867 */
15868 DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
15869 DUK_TVAL_SET_TVAL(tv2, tv1);
15871 thr->valstack_top--;
15872 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
15873}
15874
15875DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index) {
15876 duk_hthread *thr = (duk_hthread *) ctx;
15877 duk_tval *tv1;
15878 duk_tval *tv2;
15879
15881 DUK_UNREF(thr); /* w/o refcounting */
15882
15883 tv1 = duk_require_tval(ctx, from_index);
15884 DUK_ASSERT(tv1 != NULL);
15885 tv2 = duk_require_tval(ctx, to_index);
15886 DUK_ASSERT(tv2 != NULL);
15887
15888 /* For tv1 == tv2, this is a no-op (no explicit check needed). */
15889 DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1); /* side effects */
15890}
15891
15893 duk_hthread *thr = (duk_hthread *) ctx;
15894 duk_tval *p;
15895 duk_tval *q;
15896#ifdef DUK_USE_REFERENCE_COUNTING
15897 duk_tval tv_tmp;
15898#endif
15899 duk_size_t nbytes;
15900
15902
15903 p = duk_require_tval(ctx, index);
15904 DUK_ASSERT(p != NULL);
15905 q = duk_require_tval(ctx, -1);
15906 DUK_ASSERT(q != NULL);
15907
15908 DUK_ASSERT(q >= p);
15909
15910 /* nbytes zero size case
15911 * <--------->
15912 * [ ... | p | x | x | q ] [ ... | p==q ]
15913 * => [ ... | x | x | q ] [ ... ]
15914 */
15915
15916#ifdef DUK_USE_REFERENCE_COUNTING
15917 /* use a temp: decref only when valstack reachable values are correct */
15918 DUK_TVAL_SET_TVAL(&tv_tmp, p);
15919#endif
15920
15921 nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
15922 DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes); /* zero size not an issue: pointers are valid */
15923
15925 thr->valstack_top--;
15926
15927#ifdef DUK_USE_REFERENCE_COUNTING
15928 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
15929#endif
15930}
15931
15932/*
15933 * Stack slice primitives
15934 */
15935
15936DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy) {
15937 duk_hthread *to_thr = (duk_hthread *) to_ctx;
15938 duk_hthread *from_thr = (duk_hthread *) from_ctx;
15939 void *src;
15940 duk_size_t nbytes;
15941 duk_tval *p;
15942 duk_tval *q;
15943
15944 /* XXX: several pointer comparison issues here */
15945
15946 DUK_ASSERT_CTX_VALID(to_ctx);
15947 DUK_ASSERT_CTX_VALID(from_ctx);
15948 DUK_ASSERT(to_ctx != NULL);
15949 DUK_ASSERT(from_ctx != NULL);
15950
15951 if (to_ctx == from_ctx) {
15953 return;
15954 }
15955 if ((count < 0) ||
15956 (count > (duk_idx_t) to_thr->valstack_max)) {
15957 /* Maximum value check ensures 'nbytes' won't wrap below. */
15959 return;
15960 }
15961
15962 nbytes = sizeof(duk_tval) * count;
15963 if (nbytes == 0) {
15964 return;
15965 }
15966 DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
15967 if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) {
15969 }
15970 src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
15971 if (src < (void *) from_thr->valstack_bottom) {
15973 }
15974
15975 /* copy values (no overlap even if to_ctx == from_ctx; that's not
15976 * allowed now anyway)
15977 */
15978 DUK_ASSERT(nbytes > 0);
15979 DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
15980
15981 p = to_thr->valstack_top;
15982 to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
15983
15984 if (is_copy) {
15985 /* Incref copies, keep originals. */
15986 q = to_thr->valstack_top;
15987 while (p < q) {
15988 DUK_TVAL_INCREF(to_thr, p); /* no side effects */
15989 p++;
15990 }
15991 } else {
15992 /* No net refcount change. */
15993 p = from_thr->valstack_top;
15994 q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
15995 from_thr->valstack_top = q;
15996
15997 while (p > q) {
15998 p--;
16000 /* XXX: fast primitive to set a bunch of values to UNDEFINED */
16001 }
16002 }
16003}
16004
16005/*
16006 * Get/require
16007 */
16008
16010 duk_hthread *thr = (duk_hthread *) ctx;
16011 duk_tval *tv;
16012
16014
16015 tv = duk_get_tval(ctx, index);
16016 if (tv && DUK_TVAL_IS_UNDEFINED(tv)) {
16017 return;
16018 }
16020 return; /* not reachable */
16021}
16022
16024 duk_hthread *thr = (duk_hthread *) ctx;
16025 duk_tval *tv;
16026
16028
16029 tv = duk_get_tval(ctx, index);
16030 if (tv && DUK_TVAL_IS_NULL(tv)) {
16031 return;
16032 }
16034 return; /* not reachable */
16036
16038 duk_bool_t ret = 0; /* default: false */
16039 duk_tval *tv;
16040
16042
16043 tv = duk_get_tval(ctx, index);
16044 if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
16045 ret = DUK_TVAL_GET_BOOLEAN(tv);
16046 }
16047
16048 DUK_ASSERT(ret == 0 || ret == 1);
16049 return ret;
16050}
16053 duk_hthread *thr = (duk_hthread *) ctx;
16054 duk_tval *tv;
16055
16057
16058 tv = duk_get_tval(ctx, index);
16059 if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
16061 DUK_ASSERT(ret == 0 || ret == 1);
16062 return ret;
16063 }
16065 return 0; /* not reachable */
16066}
16067
16069 duk_double_union ret;
16070 duk_tval *tv;
16071
16073
16074 ret.d = DUK_DOUBLE_NAN; /* default: NaN */
16075 tv = duk_get_tval(ctx, index);
16076 if (tv && DUK_TVAL_IS_NUMBER(tv)) {
16077 ret.d = DUK_TVAL_GET_NUMBER(tv);
16078 }
16079
16080 /*
16081 * Number should already be in NaN-normalized form, but let's
16082 * normalize anyway.
16083 */
16084
16086 return ret.d;
16087}
16088
16090 duk_hthread *thr = (duk_hthread *) ctx;
16091 duk_tval *tv;
16092
16094
16096 if (tv && DUK_TVAL_IS_NUMBER(tv)) {
16097 duk_double_union ret;
16098 ret.d = DUK_TVAL_GET_NUMBER(tv);
16099
16100 /*
16101 * Number should already be in NaN-normalized form,
16102 * but let's normalize anyway.
16103 */
16104
16106 return ret.d;
16109 return DUK_DOUBLE_NAN; /* not reachable */
16110}
16111
16113 /* Custom coercion for API */
16115 return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
16116}
16117
16119 /* Custom coercion for API */
16121 return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
16122}
16123
16125 /* Custom coercion for API */
16127 return (duk_int_t) duk__api_coerce_d2i(ctx, index, 1 /*require*/);
16128}
16129
16131 /* Custom coercion for API */
16133 return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 1 /*require*/);
16134}
16135
16137 const char *ret;
16138 duk_tval *tv;
16139
16141
16142 /* default: NULL, length 0 */
16143 ret = NULL;
16144 if (out_len) {
16145 *out_len = 0;
16146 }
16148 tv = duk_get_tval(ctx, index);
16149 if (tv && DUK_TVAL_IS_STRING(tv)) {
16150 /* Here we rely on duk_hstring instances always being zero
16151 * terminated even if the actual string is not.
16152 */
16154 DUK_ASSERT(h != NULL);
16155 ret = (const char *) DUK_HSTRING_GET_DATA(h);
16156 if (out_len) {
16157 *out_len = DUK_HSTRING_GET_BYTELEN(h);
16158 }
16159 }
16160
16161 return ret;
16162}
16163
16165 duk_hthread *thr = (duk_hthread *) ctx;
16166 const char *ret;
16167
16169
16170 /* Note: this check relies on the fact that even a zero-size string
16171 * has a non-NULL pointer.
16172 */
16173 ret = duk_get_lstring(ctx, index, out_len);
16174 if (ret) {
16175 return ret;
16178 return NULL; /* not reachable */
16179}
16180
16183
16184 return duk_get_lstring(ctx, index, NULL);
16185}
16186
16189
16191}
16192
16194 duk_tval *tv;
16195
16197
16198 tv = duk_get_tval(ctx, index);
16199 if (tv && DUK_TVAL_IS_POINTER(tv)) {
16200 void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
16201 return (void *) p;
16202 }
16203
16204 return NULL;
16205}
16206
16208 duk_hthread *thr = (duk_hthread *) ctx;
16209 duk_tval *tv;
16210
16212
16213 /* Note: here we must be wary of the fact that a pointer may be
16214 * valid and be a NULL.
16215 */
16216 tv = duk_get_tval(ctx, index);
16217 if (tv && DUK_TVAL_IS_POINTER(tv)) {
16218 void *p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
16219 return (void *) p;
16220 }
16222 return NULL; /* not reachable */
16223}
16224
16225#if 0 /*unused*/
16226DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) {
16227 duk_tval *tv;
16228
16230
16231 tv = duk_get_tval(ctx, index);
16232 if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
16234 DUK_ASSERT(h != NULL);
16235 return (void *) h;
16236 }
16237
16238 return NULL;
16239}
16240#endif
16241
16243 duk_hthread *thr = (duk_hthread *) ctx;
16244 duk_tval *tv;
16245
16247 DUK_UNREF(thr);
16248
16249 if (out_size != NULL) {
16250 *out_size = 0;
16251 }
16253 tv = duk_get_tval(ctx, index);
16254 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
16257 if (out_size) {
16258 *out_size = DUK_HBUFFER_GET_SIZE(h);
16259 }
16260 return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
16261 }
16262
16263 if (throw_flag) {
16265 }
16266 return NULL;
16267}
16268
16270 return duk__get_buffer_helper(ctx, index, out_size, 0 /*throw_flag*/);
16271}
16272
16274 return duk__get_buffer_helper(ctx, index, out_size, 1 /*throw_flag*/);
16275}
16276
16278 duk_hthread *thr = (duk_hthread *) ctx;
16279 duk_tval *tv;
16280
16282 DUK_UNREF(thr);
16283
16284 if (out_size != NULL) {
16285 *out_size = 0;
16286 }
16287
16288 tv = duk_get_tval(ctx, index);
16289 if (tv == NULL) {
16290 goto fail;
16291 }
16292
16293 if (DUK_TVAL_IS_BUFFER(tv)) {
16295 DUK_ASSERT(h != NULL);
16296 if (out_size) {
16297 *out_size = DUK_HBUFFER_GET_SIZE(h);
16298 }
16299 return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
16300 } else if (DUK_TVAL_IS_OBJECT(tv)) {
16302 DUK_ASSERT(h != NULL);
16304 /* XXX: this is probably a useful shared helper: for a
16305 * duk_hbufferobject, get a validated buffer pointer/length.
16306 */
16307 duk_hbufferobject *h_bufobj = (duk_hbufferobject *) h;
16309
16310 if (h_bufobj->buf != NULL &&
16312 duk_uint8_t *p;
16313
16314 p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
16315 if (out_size != NULL) {
16316 *out_size = (duk_size_t) h_bufobj->length;
16317 }
16318 return (void *) (p + h_bufobj->offset);
16319 }
16320 /* if slice not fully valid, treat as error */
16321 }
16322 }
16323
16324 fail:
16325 if (throw_flag) {
16328 return NULL;
16329}
16330
16332 return duk__get_buffer_data_helper(ctx, index, out_size, 0 /*throw_flag*/);
16333}
16334
16336 return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/);
16337}
16338
16339/* Raw helper for getting a value from the stack, checking its tag.
16340 * The tag cannot be a number because numbers don't have an internal
16341 * tag in the packed representation.
16342 */
16346
16348
16349 tv = duk_get_tval(ctx, index);
16350 if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) {
16351 duk_heaphdr *ret;
16352 ret = DUK_TVAL_GET_HEAPHDR(tv);
16353 DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
16354 return ret;
16355 }
16357 return (duk_heaphdr *) NULL;
16358}
16359
16370 return (duk_hstring *) h;
16371}
16372
16383 return (duk_hobject *) h;
16384}
16385
16388}
16389
16391 duk_heaphdr *h;
16393 if (h == NULL) {
16395 }
16396 return (duk_hbuffer *) h;
16397}
16398
16401 if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) {
16402 h = NULL;
16403 }
16404 return (duk_hthread *) h;
16405}
16406
16415
16423
16432
16458 if (!tv) {
16459 return NULL;
16460 }
16461 if (!DUK_TVAL_IS_OBJECT(tv)) {
16462 return NULL;
16463 }
16464 h = DUK_TVAL_GET_OBJECT(tv);
16465 DUK_ASSERT(h != NULL);
16466
16468 return NULL;
16469 }
16471 f = (duk_hnativefunction *) h;
16477 duk_hthread *thr = (duk_hthread *) ctx;
16479
16481
16482 ret = duk_get_c_function(ctx, index);
16483 if (!ret) {
16485 }
16486 return ret;
16487}
16488
16492 }
16493}
16494
16497
16498 return (duk_context *) duk_get_hthread(ctx, index);
16499}
16500
16503
16504 return (duk_context *) duk_require_hthread(ctx, index);
16505}
16508 duk_tval *tv;
16509 void *ret;
16510
16512
16513 tv = duk_get_tval(ctx, index);
16514 if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
16515 ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
16516 DUK_ASSERT(ret != NULL);
16517 return ret;
16518 }
16519
16520 return (void *) NULL;
16521}
16522
16524 duk_hthread *thr = (duk_hthread *) ctx;
16525 duk_tval *tv;
16526 void *ret;
16527
16529
16530 tv = duk_require_tval(ctx, index);
16531 DUK_ASSERT(tv != NULL);
16533 ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
16534 DUK_ASSERT(ret != NULL);
16535 return ret;
16536 }
16537
16539 return (void *) NULL; /* not reachable */
16540}
16541
16542#if 0
16543/* This would be pointless: we'd return NULL for both lightfuncs and
16544 * unexpected types.
16545 */
16546DUK_INTERNAL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) {
16547}
16548#endif
16549
16550/* Useful for internal call sites where we either expect an object (function)
16551 * or a lightfunc. Accepts an object (returned as is) or a lightfunc (coerced
16552 * to an object). Return value is NULL if value is neither an object nor a
16553 * lightfunc.
16554 */
16556 duk_tval *tv;
16557
16559
16560 tv = duk_require_tval(ctx, index);
16561 DUK_ASSERT(tv != NULL);
16562 if (DUK_TVAL_IS_OBJECT(tv)) {
16563 return DUK_TVAL_GET_OBJECT(tv);
16564 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16565 duk_to_object(ctx, index);
16566 return duk_require_hobject(ctx, index);
16567 }
16568
16569 return NULL;
16570}
16571
16572/* Useful for internal call sites where we either expect an object (function)
16573 * or a lightfunc. Returns NULL for a lightfunc.
16574 */
16576 duk_hthread *thr = (duk_hthread *) ctx;
16577 duk_tval *tv;
16578
16580
16581 tv = duk_require_tval(ctx, index);
16582 DUK_ASSERT(tv != NULL);
16583 if (DUK_TVAL_IS_OBJECT(tv)) {
16584 return DUK_TVAL_GET_OBJECT(tv);
16585 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16586 return NULL;
16587 }
16589 return NULL; /* not reachable */
16590}
16591
16592/* Useful for internal call sites where we either expect an object (function)
16593 * or a lightfunc. Accepts an object (returned as is) or a lightfunc (coerced
16594 * to an object). Return value is never NULL.
16595 */
16597 duk_hthread *thr = (duk_hthread *) ctx;
16598 duk_tval *tv;
16599
16601
16602 tv = duk_require_tval(ctx, index);
16603 if (DUK_TVAL_IS_OBJECT(tv)) {
16604 return DUK_TVAL_GET_OBJECT(tv);
16605 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16606 duk_to_object(ctx, index);
16607 return duk_require_hobject(ctx, index);
16608 }
16610 return NULL; /* not reachable */
16611}
16612
16614 duk_hobject *h;
16615
16617 DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
16618 DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
16619
16621 if (h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum) {
16622 h = NULL;
16623 }
16624 return h;
16625}
16626
16628 duk_hthread *thr;
16629 duk_hobject *h;
16632 DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
16633 DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
16634 thr = (duk_hthread *) ctx;
16635
16637 if (!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum)) {
16638 duk_hstring *h_class;
16640 DUK_UNREF(h_class);
16641
16643 }
16644 return h;
16645}
16646
16648 duk_tval *tv;
16649
16651
16652 tv = duk_get_tval(ctx, index);
16653 if (!tv) {
16654 return 0;
16655 }
16656
16657 switch (DUK_TVAL_GET_TAG(tv)) {
16658 case DUK_TAG_UNDEFINED:
16659 case DUK_TAG_NULL:
16660 case DUK_TAG_BOOLEAN:
16661 case DUK_TAG_POINTER:
16662 return 0;
16663 case DUK_TAG_STRING: {
16665 DUK_ASSERT(h != NULL);
16667 }
16668 case DUK_TAG_OBJECT: {
16670 DUK_ASSERT(h != NULL);
16671 return (duk_size_t) duk_hobject_get_length((duk_hthread *) ctx, h);
16672 }
16673 case DUK_TAG_BUFFER: {
16675 DUK_ASSERT(h != NULL);
16676 return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
16677 }
16678 case DUK_TAG_LIGHTFUNC: {
16680 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
16681 return (duk_size_t) DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
16682 }
16683#if defined(DUK_USE_FASTINT)
16684 case DUK_TAG_FASTINT:
16685#endif
16686 default:
16687 /* number */
16690 return 0;
16691 }
16692
16694}
16695
16697 duk_hthread *thr = (duk_hthread *) ctx;
16698 duk_hobject *h;
16699
16701
16702 h = duk_get_hobject(ctx, index);
16703 if (!h) {
16704 return;
16705 }
16706
16707 duk_hobject_set_length(thr, h, (duk_uint32_t) length); /* XXX: typing */
16708}
16709
16710/*
16711 * Conversions and coercions
16712 *
16713 * The conversion/coercions are in-place operations on the value stack.
16714 * Some operations are implemented here directly, while others call a
16715 * helper in duk_js_ops.c after validating arguments.
16716 */
16717
16718/* E5 Section 8.12.8 */
16719
16721 if (duk_get_prop_stridx(ctx, index, func_stridx)) {
16722 /* [ ... func ] */
16723 if (duk_is_callable(ctx, -1)) {
16724 duk_dup(ctx, index); /* -> [ ... func this ] */
16725 duk_call_method(ctx, 0); /* -> [ ... retval ] */
16726 if (duk_is_primitive(ctx, -1)) {
16727 duk_replace(ctx, index);
16728 return 1;
16729 }
16730 /* [ ... retval ]; popped below */
16731 }
16732 }
16733 duk_pop(ctx); /* [ ... func/retval ] -> [ ... ] */
16734 return 0;
16735}
16736
16738 duk_hthread *thr = (duk_hthread *) ctx;
16739 duk_hobject *obj;
16740 /* inline initializer for coercers[] is not allowed by old compilers like BCC */
16741 duk_small_int_t coercers[2];
16742
16744 DUK_ASSERT(thr != NULL);
16745
16746 coercers[0] = DUK_STRIDX_VALUE_OF;
16747 coercers[1] = DUK_STRIDX_TO_STRING;
16748
16751
16752 if (hint == DUK_HINT_NONE) {
16754 hint = DUK_HINT_STRING;
16755 } else {
16756 hint = DUK_HINT_NUMBER;
16757 }
16758 }
16760 if (hint == DUK_HINT_STRING) {
16761 coercers[0] = DUK_STRIDX_TO_STRING;
16762 coercers[1] = DUK_STRIDX_VALUE_OF;
16763 }
16764
16765 if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[0])) {
16766 return;
16767 }
16768
16769 if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[1])) {
16770 return;
16772
16774}
16775
16777 duk_hthread *thr = (duk_hthread *) ctx;
16778 duk_tval *tv;
16779
16781 DUK_UNREF(thr);
16782
16783 tv = duk_require_tval(ctx, index);
16785 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
16786}
16787
16789 duk_hthread *thr = (duk_hthread *) ctx;
16790 duk_tval *tv;
16791
16793 DUK_UNREF(thr);
16794
16795 tv = duk_require_tval(ctx, index);
16796 DUK_ASSERT(tv != NULL);
16797 DUK_TVAL_SET_NULL_UPDREF(thr, tv); /* side effects */
16798}
16800/* E5 Section 9.1 */
16803 DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
16804
16806
16809 /* everything except object stay as is */
16810 return;
16811 }
16812 duk_to_defaultvalue(ctx, index, hint);
16813}
16814
16815/* E5 Section 9.2 */
16817 duk_hthread *thr = (duk_hthread *) ctx;
16818 duk_tval *tv;
16819 duk_bool_t val;
16820
16822 DUK_UNREF(thr);
16823
16825
16826 tv = duk_require_tval(ctx, index);
16827 DUK_ASSERT(tv != NULL);
16828
16829 val = duk_js_toboolean(tv);
16830 DUK_ASSERT(val == 0 || val == 1);
16831
16832 /* Note: no need to re-lookup tv, conversion is side effect free */
16833 DUK_ASSERT(tv != NULL);
16834 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val); /* side effects */
16835 return val;
16836}
16837
16839 duk_hthread *thr = (duk_hthread *) ctx;
16840 duk_tval *tv;
16841 duk_double_t d;
16842
16844
16846 DUK_ASSERT(tv != NULL);
16847 /* XXX: fastint? */
16848 d = duk_js_tonumber(thr, tv);
16849
16850 /* Note: need to re-lookup because ToNumber() may have side effects */
16851 tv = duk_require_tval(ctx, index);
16852 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
16853 return d;
16854}
16855
16856/* XXX: combine all the integer conversions: they share everything
16857 * but the helper function for coercion.
16858 */
16859
16861
16863 duk_hthread *thr = (duk_hthread *) ctx;
16865 duk_double_t d;
16866
16868
16869 tv = duk_require_tval(ctx, index);
16870 DUK_ASSERT(tv != NULL);
16871 d = coerce_func(thr, tv);
16872
16873 /* XXX: fastint? */
16874
16875 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16876 tv = duk_require_tval(ctx, index);
16877 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
16878 return d;
16879}
16880
16882 /* Value coercion (in stack): ToInteger(), E5 Section 9.4
16883 * API return value coercion: custom
16884 */
16887 return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
16888}
16889
16891 /* Value coercion (in stack): ToInteger(), E5 Section 9.4
16892 * API return value coercion: custom
16893 */
16896 return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
16897}
16898
16900 duk_hthread *thr = (duk_hthread *) ctx;
16901 duk_tval *tv;
16902 duk_int32_t ret;
16903
16905
16906 tv = duk_require_tval(ctx, index);
16907 DUK_ASSERT(tv != NULL);
16908 ret = duk_js_toint32(thr, tv);
16909
16910 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16911 tv = duk_require_tval(ctx, index);
16912 DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv, ret); /* side effects */
16913 return ret;
16914}
16915
16917 duk_hthread *thr = (duk_hthread *) ctx;
16918 duk_tval *tv;
16919 duk_uint32_t ret;
16920
16922
16923 tv = duk_require_tval(ctx, index);
16924 DUK_ASSERT(tv != NULL);
16925 ret = duk_js_touint32(thr, tv);
16926
16927 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16928 tv = duk_require_tval(ctx, index);
16929 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret); /* side effects */
16930 return ret;
16931}
16932
16934 duk_hthread *thr = (duk_hthread *) ctx;
16936 duk_uint16_t ret;
16937
16939
16940 tv = duk_require_tval(ctx, index);
16941 DUK_ASSERT(tv != NULL);
16942 ret = duk_js_touint16(thr, tv);
16943
16944 /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16945 tv = duk_require_tval(ctx, index);
16946 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret); /* side effects */
16947 return ret;
16948}
16949
16950#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16951/* Special coercion for Uint8ClampedArray. */
16953 duk_double_t d;
16954 duk_double_t t;
16955 duk_uint8_t ret;
16956
16957 /* XXX: Simplify this algorithm, should be possible to come up with
16958 * a shorter and faster algorithm by inspecting IEEE representation
16959 * directly.
16960 */
16961
16962 d = duk_to_number(ctx, index);
16963 if (d <= 0.0) {
16964 return 0;
16965 } else if (d >= 255) {
16966 return 255;
16967 } else if (DUK_ISNAN(d)) {
16968 /* Avoid NaN-to-integer coercion as it is compiler specific. */
16969 return 0;
16971
16972 t = d - DUK_FLOOR(d);
16973 if (t == 0.5) {
16974 /* Exact halfway, round to even. */
16975 ret = (duk_uint8_t) d;
16976 ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
16977 * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
16978 */
16979 } else {
16980 /* Not halfway, round to nearest. */
16981 ret = (duk_uint8_t) (d + 0.5);
16982 }
16983 return ret;
16985#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
16986
16987DUK_EXTERNAL const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
16989
16990 (void) duk_to_string(ctx, index);
16991 return duk_require_lstring(ctx, index, out_len);
16992}
16993
16996
16997 duk_to_string(ctx, -1);
16998 return 1;
16999}
17000
17003
17005
17006 /* We intentionally ignore the duk_safe_call() return value and only
17007 * check the output type. This way we don't also need to check that
17008 * the returned value is indeed a string in the success case.
17009 */
17010
17011 duk_dup(ctx, index);
17012 (void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/);
17013 if (!duk_is_string(ctx, -1)) {
17014 /* Error: try coercing error to string once. */
17015 (void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/);
17016 if (!duk_is_string(ctx, -1)) {
17017 /* Double error */
17018 duk_pop(ctx);
17020 } else {
17021 ;
17022 }
17023 } else {
17024 ;
17025 }
17027 DUK_ASSERT(duk_get_string(ctx, -1) != NULL);
17028
17029 duk_replace(ctx, index);
17030 return duk_get_lstring(ctx, index, out_len);
17031}
17032
17033#if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
17034DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index) {
17035 (void) duk_safe_to_string(ctx, index);
17038 return duk_get_hstring(ctx, index);
17039}
17040#endif
17041
17042/* Coerce top into Object.prototype.toString() output. */
17044 duk_hthread *thr;
17045 duk_uint_t typemask;
17046 duk_hstring *h_strclass;
17047
17049 thr = (duk_hthread *) ctx;
17050 DUK_UNREF(thr);
17051
17052 typemask = duk_get_type_mask(ctx, -1);
17053 if (typemask & DUK_TYPE_MASK_UNDEFINED) {
17054 h_strclass = DUK_HTHREAD_STRING_UC_UNDEFINED(thr);
17055 } else if (typemask & DUK_TYPE_MASK_NULL) {
17057 } else {
17058 duk_hobject *h_obj;
17059
17060 duk_to_object(ctx, -1);
17061 h_obj = duk_get_hobject(ctx, -1);
17062 DUK_ASSERT(h_obj != NULL);
17063
17064 h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h_obj);
17065 }
17066 DUK_ASSERT(h_strclass != NULL);
17067
17068 duk_pop(ctx);
17069 duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
17070}
17071
17072#if !defined(DUK_USE_PARANOID_ERRORS)
17074 duk_hthread *thr;
17075 duk_hstring *h_strclass;
17076
17078 DUK_ASSERT(h != NULL);
17079 thr = (duk_hthread *) ctx;
17080 DUK_UNREF(thr);
17081
17082 h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h);
17083 DUK_ASSERT(h_strclass != NULL);
17084 duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
17085}
17086#endif /* !DUK_USE_PARANOID_ERRORS */
17087
17088/* XXX: other variants like uint, u32 etc */
17090 duk_hthread *thr = (duk_hthread *) ctx;
17091 duk_tval *tv;
17092 duk_tval tv_tmp;
17093 duk_double_t d, dmin, dmax;
17094 duk_int_t res;
17095 duk_bool_t clamped = 0;
17096
17098
17099 tv = duk_require_tval(ctx, index);
17100 DUK_ASSERT(tv != NULL);
17101 d = duk_js_tointeger(thr, tv); /* E5 Section 9.4, ToInteger() */
17102
17103 dmin = (duk_double_t) minval;
17104 dmax = (duk_double_t) maxval;
17105
17106 if (d < dmin) {
17107 clamped = 1;
17108 res = minval;
17109 d = dmin;
17110 } else if (d > dmax) {
17111 clamped = 1;
17112 res = maxval;
17113 d = dmax;
17114 } else {
17115 res = (duk_int_t) d;
17116 }
17117 DUK_UNREF(d); /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
17118 /* 'd' and 'res' agree here */
17119
17120 /* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
17121 tv = duk_get_tval(ctx, index);
17122 DUK_ASSERT(tv != NULL); /* not popped by side effect */
17123 DUK_TVAL_SET_TVAL(&tv_tmp, tv);
17124#if defined(DUK_USE_FASTINT)
17125#if (DUK_INT_MAX <= 0x7fffffffL)
17126 DUK_TVAL_SET_FASTINT_I32(tv, res);
17127#else
17128 /* Clamping needed if duk_int_t is 64 bits. */
17129 if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
17130 DUK_TVAL_SET_FASTINT(tv, res);
17131 } else {
17132 DUK_TVAL_SET_NUMBER(tv, d);
17133 }
17134#endif
17135#else
17136 DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */
17137#endif
17138 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
17139
17140 if (out_clamped) {
17141 *out_clamped = clamped;
17142 } else {
17143 /* coerced value is updated to value stack even when RangeError thrown */
17144 if (clamped) {
17146 }
17147 }
17148
17149 return res;
17150}
17151
17154 return duk_to_int_clamped_raw(ctx, index, minval, maxval, &dummy);
17155}
17156
17158 return duk_to_int_clamped_raw(ctx, index, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */
17159}
17160
17162 duk_hthread *thr = (duk_hthread *) ctx;
17163 duk_tval *tv;
17164
17166 DUK_UNREF(thr);
17167
17169
17170 tv = duk_require_tval(ctx, index);
17171 DUK_ASSERT(tv != NULL);
17172
17173 switch (DUK_TVAL_GET_TAG(tv)) {
17174 case DUK_TAG_UNDEFINED: {
17176 break;
17177 }
17178 case DUK_TAG_NULL: {
17180 break;
17181 }
17182 case DUK_TAG_BOOLEAN: {
17183 if (DUK_TVAL_GET_BOOLEAN(tv)) {
17185 } else {
17187 }
17188 break;
17189 }
17190 case DUK_TAG_STRING: {
17191 /* nop */
17192 goto skip_replace;
17193 }
17194 case DUK_TAG_OBJECT: {
17196 return duk_to_string(ctx, index); /* Note: recursive call */
17197 }
17198 case DUK_TAG_BUFFER: {
17200
17201 /* Note: this allows creation of internal strings. */
17202
17203 DUK_ASSERT(h != NULL);
17204 duk_push_lstring(ctx,
17205 (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
17207 break;
17208 }
17209 case DUK_TAG_POINTER: {
17210 void *ptr = DUK_TVAL_GET_POINTER(tv);
17211 if (ptr != NULL) {
17212 duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) ptr);
17213 } else {
17214 /* Represent a null pointer as 'null' to be consistent with
17215 * the JX format variant. Native '%p' format for a NULL
17216 * pointer may be e.g. '(nil)'.
17217 */
17219 }
17220 break;
17221 }
17222 case DUK_TAG_LIGHTFUNC: {
17223 /* Should match Function.prototype.toString() */
17225 break;
17226 }
17227#if defined(DUK_USE_FASTINT)
17228 case DUK_TAG_FASTINT:
17229#endif
17230 default: {
17231 /* number */
17234 duk_push_tval(ctx, tv);
17236 10 /*radix*/,
17237 0 /*precision:shortest*/,
17238 0 /*force_exponential*/);
17239 break;
17240 }
17242
17243 duk_replace(ctx, index);
17244
17245 skip_replace:
17246 return duk_require_string(ctx, index);
17247}
17248
17250 duk_hstring *ret;
17252 duk_to_string(ctx, index);
17253 ret = duk_get_hstring(ctx, index);
17254 DUK_ASSERT(ret != NULL);
17255 return ret;
17256}
17257
17259 duk_hthread *thr = (duk_hthread *) ctx;
17260 duk_hbuffer *h_buf;
17261 const duk_uint8_t *src_data;
17262 duk_size_t src_size;
17263 duk_uint8_t *dst_data;
17264
17266 DUK_UNREF(thr);
17267
17269
17270 h_buf = duk_get_hbuffer(ctx, index);
17271 if (h_buf != NULL) {
17272 /* Buffer is kept as is, with the fixed/dynamic nature of the
17273 * buffer only changed if requested. An external buffer
17274 * is converted into a non-external dynamic buffer in a
17275 * duk_to_dynamic_buffer() call.
17276 */
17277 duk_uint_t tmp;
17278 duk_uint8_t *tmp_ptr;
17279
17280 tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
17281 src_data = (const duk_uint8_t *) tmp_ptr;
17282 src_size = DUK_HBUFFER_GET_SIZE(h_buf);
17283
17285 if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
17286 mode == DUK_BUF_MODE_DONTCARE) {
17287 /* Note: src_data may be NULL if input is a zero-size
17288 * dynamic buffer.
17289 */
17290 dst_data = tmp_ptr;
17291 goto skip_copy;
17292 }
17293 } else {
17294 /* Non-buffer value is first ToString() coerced, then converted
17295 * to a buffer (fixed buffer is used unless a dynamic buffer is
17296 * explicitly requested).
17297 */
17298
17299 src_data = (const duk_uint8_t *) duk_to_lstring(ctx, index, &src_size);
17300 }
17301
17302 dst_data = (duk_uint8_t *) duk_push_buffer(ctx, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
17303 if (DUK_LIKELY(src_size > 0)) {
17304 /* When src_size == 0, src_data may be NULL (if source
17305 * buffer is dynamic), and dst_data may be NULL (if
17306 * target buffer is dynamic). Avoid zero-size memcpy()
17307 * with an invalid pointer.
17308 */
17309 DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);
17310 }
17311 duk_replace(ctx, index);
17312 skip_copy:
17313
17314 if (out_size) {
17315 *out_size = src_size;
17316 }
17317 return dst_data;
17318}
17319
17321 duk_tval *tv;
17322 void *res;
17323
17325
17327
17328 tv = duk_require_tval(ctx, index);
17329 DUK_ASSERT(tv != NULL);
17330
17331 switch (DUK_TVAL_GET_TAG(tv)) {
17332 case DUK_TAG_UNDEFINED:
17333 case DUK_TAG_NULL:
17334 case DUK_TAG_BOOLEAN:
17335 res = NULL;
17336 break;
17337 case DUK_TAG_POINTER:
17338 res = DUK_TVAL_GET_POINTER(tv);
17339 break;
17340 case DUK_TAG_STRING:
17341 case DUK_TAG_OBJECT:
17342 case DUK_TAG_BUFFER:
17343 /* Heap allocated: return heap pointer which is NOT useful
17344 * for the caller, except for debugging.
17345 */
17346 res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
17347 break;
17348 case DUK_TAG_LIGHTFUNC:
17349 /* Function pointers do not always cast correctly to void *
17350 * (depends on memory and segmentation model for instance),
17351 * so they coerce to NULL.
17352 */
17353 res = NULL;
17354 break;
17355#if defined(DUK_USE_FASTINT)
17356 case DUK_TAG_FASTINT:
17357#endif
17358 default:
17359 /* number */
17362 res = NULL;
17363 break;
17364 }
17365
17366 duk_push_pointer(ctx, res);
17367 duk_replace(ctx, index);
17368 return res;
17369}
17370
17372 duk_hthread *thr = (duk_hthread *) ctx;
17373 duk_tval *tv;
17374 duk_uint_t flags = 0; /* shared flags for a subset of types */
17376
17378
17380
17381 tv = duk_require_tval(ctx, index);
17382 DUK_ASSERT(tv != NULL);
17383
17384 switch (DUK_TVAL_GET_TAG(tv)) {
17385 case DUK_TAG_UNDEFINED:
17386 case DUK_TAG_NULL: {
17388 break;
17389 }
17390 case DUK_TAG_BOOLEAN: {
17394 goto create_object;
17395 }
17396 case DUK_TAG_STRING: {
17401 goto create_object;
17402 }
17403 case DUK_TAG_OBJECT: {
17404 /* nop */
17405 break;
17406 }
17407 case DUK_TAG_BUFFER: {
17408 /* A plain buffer coerces to a Duktape.Buffer because it's the
17409 * object counterpart of the plain buffer value. But it might
17410 * still make more sense to produce an ArrayBuffer here?
17411 */
17412
17413 duk_hbufferobject *h_bufobj;
17414 duk_hbuffer *h_val;
17415
17416 h_val = DUK_TVAL_GET_BUFFER(tv);
17417 DUK_ASSERT(h_val != NULL);
17418
17419 h_bufobj = duk_push_bufferobject_raw(ctx,
17424 DUK_ASSERT(h_bufobj != NULL);
17427
17428 h_bufobj->buf = h_val;
17429 DUK_HBUFFER_INCREF(thr, h_val);
17430 DUK_ASSERT(h_bufobj->offset == 0);
17431 h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
17432 DUK_ASSERT(h_bufobj->shift == 0);
17434
17436 goto replace_value;
17437 }
17438 case DUK_TAG_POINTER: {
17442 goto create_object;
17443 }
17444 case DUK_TAG_LIGHTFUNC: {
17445 /* Lightfunc coerces to a Function instance with concrete
17446 * properties. Since 'length' is virtual for Duktape/C
17447 * functions, don't need to define that.
17448 *
17449 * The result is made extensible to mimic what happens to
17450 * strings:
17451 * > Object.isExtensible(Object('foo'))
17452 * true
17453 */
17454 duk_small_uint_t lf_flags;
17455 duk_idx_t nargs;
17456 duk_small_uint_t lf_len;
17457 duk_c_function func;
17459
17460 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
17461
17462 nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
17463 if (nargs == DUK_LFUNC_NARGS_VARARGS) {
17464 nargs = (duk_idx_t) DUK_VARARGS;
17465 }
17472 /* DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC: omitted here intentionally */
17474 (void) duk__push_c_function_raw(ctx, func, nargs, flags);
17475
17476 lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
17477 if ((duk_idx_t) lf_len != nargs) {
17478 /* Explicit length is only needed if it differs from 'nargs'. */
17479 duk_push_int(ctx, (duk_int_t) lf_len);
17481 }
17482 duk_push_lightfunc_name(ctx, tv);
17484
17485 nf = duk_get_hnativefunction(ctx, -1);
17486 DUK_ASSERT(nf != NULL);
17487 nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
17488
17489 /* Enable DUKFUNC exotic behavior once properties are set up. */
17491 goto replace_value;
17492 }
17493#if defined(DUK_USE_FASTINT)
17494 case DUK_TAG_FASTINT:
17495#endif
17496 default: {
17502 goto create_object;
17503 }
17504 }
17505 return;
17506
17507 create_object:
17508 (void) duk_push_object_helper(ctx, flags, proto);
17509
17510 /* Note: Boolean prototype's internal value property is not writable,
17511 * but duk_xdef_prop_stridx() disregards the write protection. Boolean
17512 * instances are immutable.
17513 *
17514 * String and buffer special behaviors are already enabled which is not
17515 * ideal, but a write to the internal value is not affected by them.
17516 */
17517 duk_dup(ctx, index);
17519
17520 replace_value:
17522}
17523
17524/*
17525 * Type checking
17526 */
17527
17529 duk_tval *tv;
17530
17531 tv = duk_get_tval(ctx, index);
17532 if (!tv) {
17533 return 0;
17534 }
17535 return (DUK_TVAL_GET_TAG(tv) == tag);
17536}
17537
17539 duk_hobject *obj;
17540
17542
17543 obj = duk_get_hobject(ctx, index);
17544 if (obj) {
17545 return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
17546 }
17547 return 0;
17548}
17549
17551 duk_tval *tv;
17552
17554
17555 tv = duk_get_tval(ctx, index);
17556 if (!tv) {
17557 return DUK_TYPE_NONE;
17558 }
17559 switch (DUK_TVAL_GET_TAG(tv)) {
17560 case DUK_TAG_UNDEFINED:
17561 return DUK_TYPE_UNDEFINED;
17562 case DUK_TAG_NULL:
17563 return DUK_TYPE_NULL;
17564 case DUK_TAG_BOOLEAN:
17565 return DUK_TYPE_BOOLEAN;
17566 case DUK_TAG_STRING:
17567 return DUK_TYPE_STRING;
17568 case DUK_TAG_OBJECT:
17569 return DUK_TYPE_OBJECT;
17570 case DUK_TAG_BUFFER:
17571 return DUK_TYPE_BUFFER;
17572 case DUK_TAG_POINTER:
17573 return DUK_TYPE_POINTER;
17574 case DUK_TAG_LIGHTFUNC:
17575 return DUK_TYPE_LIGHTFUNC;
17576#if defined(DUK_USE_FASTINT)
17577 case DUK_TAG_FASTINT:
17578#endif
17579 default:
17580 /* Note: number has no explicit tag (in 8-byte representation) */
17583 return DUK_TYPE_NUMBER;
17584 }
17586}
17587
17588#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
17589DUK_LOCAL const char *duk__type_names[] = {
17590 "none",
17591 "undefined",
17592 "null",
17593 "boolean",
17594 "number",
17595 "string",
17596 "object",
17597 "buffer",
17598 "pointer",
17599 "lightfunc"
17600};
17601
17602DUK_INTERNAL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index) {
17603 duk_int_t type_tag;
17604
17605 type_tag = duk_get_type(ctx, index);
17606 DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
17607 DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
17608
17609 return duk__type_names[type_tag];
17610}
17611#endif
17612
17615
17616 return (duk_get_type(ctx, index) == type) ? 1 : 0;
17617}
17618
17620 duk_tval *tv;
17621
17623
17624 tv = duk_get_tval(ctx, index);
17625 if (!tv) {
17626 return DUK_TYPE_MASK_NONE;
17627 }
17628 switch (DUK_TVAL_GET_TAG(tv)) {
17629 case DUK_TAG_UNDEFINED:
17631 case DUK_TAG_NULL:
17632 return DUK_TYPE_MASK_NULL;
17633 case DUK_TAG_BOOLEAN:
17634 return DUK_TYPE_MASK_BOOLEAN;
17635 case DUK_TAG_STRING:
17636 return DUK_TYPE_MASK_STRING;
17637 case DUK_TAG_OBJECT:
17638 return DUK_TYPE_MASK_OBJECT;
17639 case DUK_TAG_BUFFER:
17641 case DUK_TAG_POINTER:
17642 return DUK_TYPE_MASK_POINTER;
17643 case DUK_TAG_LIGHTFUNC:
17645#if defined(DUK_USE_FASTINT)
17646 case DUK_TAG_FASTINT:
17647#endif
17648 default:
17649 /* Note: number has no explicit tag (in 8-byte representation) */
17652 return DUK_TYPE_MASK_NUMBER;
17653 }
17659
17661
17662 if (duk_get_type_mask(ctx, index) & mask) {
17663 return 1;
17664 }
17683 duk_tval *tv;
17685
17687
17688 tv = duk_get_tval(ctx, index);
17689 if (!tv) {
17690 return 0;
17691 }
17692 tag = DUK_TVAL_GET_TAG(tv);
17693 return (tag == DUK_TAG_UNDEFINED) || (tag == DUK_TAG_NULL);
17694}
17695
17698 return duk__tag_check(ctx, index, DUK_TAG_BOOLEAN);
17699}
17700
17702 duk_tval *tv;
17705
17706 /*
17707 * Number is special because it doesn't have a specific
17708 * tag in the 8-byte representation.
17709 */
17710
17711 /* XXX: shorter version for 12-byte representation? */
17712
17713 tv = duk_get_tval(ctx, index);
17714 if (!tv) {
17715 return 0;
17716 }
17717 return DUK_TVAL_IS_NUMBER(tv);
17718}
17719
17721 /* XXX: This will now return false for non-numbers, even though they would
17722 * coerce to NaN (as a general rule). In particular, duk_get_number()
17723 * returns a NaN for non-numbers, so should this function also return
17724 * true for non-numbers?
17725 */
17727 duk_tval *tv;
17728
17730
17732 if (!tv || !DUK_TVAL_IS_NUMBER(tv)) {
17733 return 0;
17734 }
17735 return DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
17740 return duk__tag_check(ctx, index, DUK_TAG_STRING);
17745 return duk__tag_check(ctx, index, DUK_TAG_OBJECT);
17757
17761}
17762
17764 duk_hobject *obj;
17765
17767
17768 obj = duk_get_hobject(ctx, index);
17769 if (obj) {
17771 }
17772 return 0;
17773}
17780 tv = duk_get_tval(ctx, index);
17781 if (tv && DUK_TVAL_IS_LIGHTFUNC(tv)) {
17782 return 1;
17783 }
17785 index,
17794 index,
17801 index,
17815 index,
17817}
17818
17820 duk_tval *tv;
17821
17823
17824 tv = duk_get_tval(ctx, index);
17825 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17827 DUK_ASSERT(h != NULL);
17828 return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
17829 }
17830 return 0;
17831}
17832
17834 duk_tval *tv;
17835
17837
17838 tv = duk_get_tval(ctx, index);
17839 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17841 DUK_ASSERT(h != NULL);
17842 return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
17843 }
17844 return 0;
17845}
17846
17848 duk_tval *tv;
17849
17851
17852 tv = duk_get_tval(ctx, index);
17853 if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17855 DUK_ASSERT(h != NULL);
17856 return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
17857 }
17858 return 0;
17859}
17860
17862 duk_hthread *thr = (duk_hthread *) ctx;
17863 duk_hobject *h;
17864 duk_uint_t sanity;
17865
17867
17868 h = duk_get_hobject(ctx, index);
17869
17871 do {
17872 if (!h) {
17873 return DUK_ERR_NONE;
17874 }
17875 if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
17876 return DUK_ERR_EVAL_ERROR;
17877 }
17879 return DUK_ERR_RANGE_ERROR;
17880 }
17883 }
17885 return DUK_ERR_SYNTAX_ERROR;
17886 }
17887 if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
17888 return DUK_ERR_TYPE_ERROR;
17889 }
17891 return DUK_ERR_URI_ERROR;
17892 }
17893 if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
17894 return DUK_ERR_ERROR;
17895 }
17896
17897 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
17898 } while (--sanity > 0);
17899
17900 return DUK_ERR_NONE;
17901}
17902
17904 * Pushers
17905 */
17906
17908 duk_hthread *thr;
17909 duk_tval *tv_slot;
17910
17912 DUK_ASSERT(tv != NULL);
17913 thr = (duk_hthread *) ctx;
17915 tv_slot = thr->valstack_top++;
17916 DUK_TVAL_SET_TVAL(tv_slot, tv);
17917 DUK_TVAL_INCREF(thr, tv); /* no side effects */
17918}
17919
17921 duk_hthread *thr;
17922
17924 thr = (duk_hthread *) ctx;
17926
17927 /* Because value stack init policy is 'undefined above top',
17928 * we don't need to write, just assert.
17929 */
17930 thr->valstack_top++;
17932}
17933
17935 duk_hthread *thr;
17936 duk_tval *tv_slot;
17937
17939 thr = (duk_hthread *) ctx;
17941 tv_slot = thr->valstack_top++;
17942 DUK_TVAL_SET_NULL(tv_slot);
17943}
17944
17946 duk_hthread *thr;
17947 duk_tval *tv_slot;
17949
17951 thr = (duk_hthread *) ctx;
17953 b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */
17954 tv_slot = thr->valstack_top++;
17955 DUK_TVAL_SET_BOOLEAN(tv_slot, b);
17956}
17957
17959 duk_hthread *thr;
17960 duk_tval *tv_slot;
17961
17963 thr = (duk_hthread *) ctx;
17965 tv_slot = thr->valstack_top++;
17967}
17968
17970 duk_hthread *thr;
17971 duk_tval *tv_slot;
17972
17974 thr = (duk_hthread *) ctx;
17976 tv_slot = thr->valstack_top++;
17979
17980/* normalize NaN which may not match our canonical internal NaN */
17982 duk_hthread *thr;
17983 duk_tval *tv_slot;
17985
17987 thr = (duk_hthread *) ctx;
17989 du.d = val;
17991 tv_slot = thr->valstack_top++;
17992 DUK_TVAL_SET_NUMBER(tv_slot, du.d);
17993}
17994
17996#if defined(DUK_USE_FASTINT)
17997 duk_hthread *thr;
17998 duk_tval *tv_slot;
17999
18001 thr = (duk_hthread *) ctx;
18003 tv_slot = thr->valstack_top++;
18004#if DUK_INT_MAX <= 0x7fffffffL
18005 DUK_TVAL_SET_FASTINT_I32(tv_slot, (duk_int32_t) val);
18006#else
18007 if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
18008 DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
18009 } else {
18010 duk_double_t = (duk_double_t) val;
18012 }
18013#endif
18014#else /* DUK_USE_FASTINT */
18015 duk_hthread *thr;
18016 duk_tval *tv_slot;
18017 duk_double_t d;
18018
18020 thr = (duk_hthread *) ctx;
18022 d = (duk_double_t) val;
18023 tv_slot = thr->valstack_top++;
18024 DUK_TVAL_SET_NUMBER(tv_slot, d);
18025#endif /* DUK_USE_FASTINT */
18026}
18027
18029#if defined(DUK_USE_FASTINT)
18030 duk_hthread *thr;
18031 duk_tval *tv_slot;
18032
18034 thr = (duk_hthread *) ctx;
18036 tv_slot = thr->valstack_top++;
18037#if DUK_UINT_MAX <= 0xffffffffUL
18038 DUK_TVAL_SET_FASTINT_U32(tv_slot, (duk_uint32_t) val);
18039#else
18040 if (val <= DUK_FASTINT_MAX) { /* val is unsigned so >= 0 */
18041 /* XXX: take advantage of val being unsigned, no need to mask */
18042 DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
18043 } else {
18044 duk_double_t = (duk_double_t) val;
18046 }
18047#endif
18048#else /* DUK_USE_FASTINT */
18049 duk_hthread *thr;
18050 duk_tval *tv_slot;
18051 duk_double_t d;
18052
18054 thr = (duk_hthread *) ctx;
18056 d = (duk_double_t) val;
18057 tv_slot = thr->valstack_top++;
18058 DUK_TVAL_SET_NUMBER(tv_slot, d);
18059#endif /* DUK_USE_FASTINT */
18060}
18061
18063 duk_hthread *thr;
18064 duk_tval *tv_slot;
18066
18068 thr = (duk_hthread *) ctx;
18072 tv_slot = thr->valstack_top++;
18073 DUK_TVAL_SET_NUMBER(tv_slot, du.d);
18074}
18075
18076DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len) {
18077 duk_hthread *thr = (duk_hthread *) ctx;
18078 duk_hstring *h;
18079 duk_tval *tv_slot;
18080
18082
18083 /* check stack before interning (avoid hanging temp) */
18084 if (thr->valstack_top >= thr->valstack_end) {
18086 }
18087
18088 /* NULL with zero length represents an empty string; NULL with higher
18089 * length is also now trated like an empty string although it is
18090 * a bit dubious. This is unlike duk_push_string() which pushes a
18091 * 'null' if the input string is a NULL.
18092 */
18093 if (!str) {
18094 len = 0;
18096
18097 /* Check for maximum string length */
18098 if (len > DUK_HSTRING_MAX_BYTELEN) {
18100 }
18101
18102 h = duk_heap_string_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
18103 DUK_ASSERT(h != NULL);
18104
18105 tv_slot = thr->valstack_top++;
18106 DUK_TVAL_SET_STRING(tv_slot, h);
18107 DUK_HSTRING_INCREF(thr, h); /* no side effects */
18108
18109 return (const char *) DUK_HSTRING_GET_DATA(h);
18110}
18112DUK_EXTERNAL const char *duk_push_string(duk_context *ctx, const char *str) {
18114
18115 if (str) {
18116 return duk_push_lstring(ctx, str, DUK_STRLEN(str));
18117 } else {
18118 duk_push_null(ctx);
18119 return NULL;
18120 }
18121}
18122
18123#ifdef DUK_USE_FILE_IO
18124/* This is a bit clunky because it is ANSI C portable. Should perhaps
18125 * relocate to another file because this is potentially platform
18126 * dependent.
18127 */
18128DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
18129 duk_hthread *thr = (duk_hthread *) ctx;
18130 duk_file *f = NULL;
18131 char *buf;
18132 long sz; /* ANSI C typing */
18133
18135
18136 if (!path) {
18137 goto fail;
18138 }
18139 f = DUK_FOPEN(path, "rb");
18140 if (!f) {
18141 goto fail;
18142 }
18143 if (DUK_FSEEK(f, 0, SEEK_END) < 0) {
18144 goto fail;
18145 }
18146 sz = DUK_FTELL(f);
18147 if (sz < 0) {
18148 goto fail;
18149 }
18150 if (DUK_FSEEK(f, 0, SEEK_SET) < 0) {
18151 goto fail;
18152 }
18153 buf = (char *) duk_push_fixed_buffer(ctx, (duk_size_t) sz);
18154 DUK_ASSERT(buf != NULL);
18155 if ((duk_size_t) DUK_FREAD(buf, 1, (size_t) sz, f) != (duk_size_t) sz) {
18156 goto fail;
18157 }
18158 (void) DUK_FCLOSE(f); /* ignore fclose() error */
18159 f = NULL;
18160 return duk_to_string(ctx, -1);
18161
18162 fail:
18163 if (f) {
18164 DUK_FCLOSE(f);
18165 }
18166
18167 if (flags != 0) {
18168 DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE); /* only flag now */
18169 duk_push_undefined(ctx);
18170 } else {
18171 /* XXX: string not shared because it is conditional */
18172 DUK_ERROR_TYPE(thr, "read file error");
18173 }
18174 return NULL;
18175}
18176#else
18177DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
18178 duk_hthread *thr = (duk_hthread *) ctx;
18180 DUK_UNREF(path);
18181
18182 if (flags != 0) {
18183 DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE); /* only flag now */
18184 duk_push_undefined(ctx);
18185 } else {
18186 /* XXX: string not shared because it is conditional */
18187 DUK_ERROR_UNSUPPORTED(thr, "file I/O disabled");
18188 }
18189 return NULL;
18190}
18191#endif /* DUK_USE_FILE_IO */
18192
18193DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val) {
18194 duk_hthread *thr;
18195 duk_tval *tv_slot;
18196
18198 thr = (duk_hthread *) ctx;
18200 tv_slot = thr->valstack_top++;
18201 DUK_TVAL_SET_POINTER(tv_slot, val);
18202}
18203
18204DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t check_object_coercible) {
18205 duk_hthread *thr;
18206 duk_tval *tv_slot;
18207
18209 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
18210 thr = (duk_hthread *) ctx;
18213
18214 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* because of valstack init policy */
18215 tv_slot = thr->valstack_top++;
18216
18217 if (DUK_UNLIKELY(thr->callstack_top == 0)) {
18218 if (check_object_coercible) {
18219 goto type_error;
18220 }
18221 /* 'undefined' already on stack top */
18222 } else {
18223 duk_tval *tv;
18224
18225 /* 'this' binding is just before current activation's bottom */
18227 tv = thr->valstack_bottom - 1;
18228 if (check_object_coercible &&
18230 /* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
18231 goto type_error;
18233
18234 DUK_TVAL_SET_TVAL(tv_slot, tv);
18235 DUK_TVAL_INCREF(thr, tv);
18236 }
18237 return;
18239 type_error:
18241}
18242
18245
18246 duk__push_this_helper(ctx, 0 /*check_object_coercible*/);
18247}
18248
18251
18252 duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18253}
18254
18256 duk_hobject *h;
18257
18259
18260 duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18261 duk_to_object(ctx, -1);
18262 h = duk_get_hobject(ctx, -1);
18263 DUK_ASSERT(h != NULL);
18264 return h;
18265}
18266
18268 duk_hstring *h;
18269
18271
18272 duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18273 duk_to_string(ctx, -1);
18274 h = duk_get_hstring(ctx, -1);
18276 return h;
18277}
18278
18280 duk_hthread *thr;
18281
18282 DUK_ASSERT(ctx != NULL);
18283 thr = (duk_hthread *) ctx;
18284
18285 DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */
18286 DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */
18287 DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */
18288
18289 return thr->valstack_bottom - 1;
18290}
18291
18293 duk_hthread *thr = (duk_hthread *) ctx;
18294 duk_activation *act;
18295
18297 DUK_ASSERT(thr != NULL);
18300
18302 if (act) {
18303 duk_push_tval(ctx, &act->tv_func);
18304 } else {
18306 }
18307}
18308
18310 duk_hthread *thr = (duk_hthread *) ctx;
18311
18313 DUK_ASSERT(thr != NULL);
18314
18315 if (thr->heap->curr_thread) {
18317 } else {
18318 duk_push_undefined(ctx);
18319 }
18320}
18321
18326}
18327
18328/* XXX: size optimize */
18332 DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
18333 duk_pop(ctx);
18335 duk_dup_top(ctx);
18336 duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C); /* [ ... parent stash stash ] -> [ ... parent stash ] */
18337 }
18338 duk_remove(ctx, -2);
18339}
18342 duk_hthread *thr = (duk_hthread *) ctx;
18343 duk_heap *heap;
18345 heap = thr->heap;
18346 DUK_ASSERT(heap->heap_object != NULL);
18347 duk_push_hobject(ctx, heap->heap_object);
18348 duk__push_stash(ctx);
18349}
18350
18354 duk__push_stash(ctx);
18355}
18356
18358 duk_hthread *thr = (duk_hthread *) ctx;
18360 if (!target_ctx) {
18362 return; /* not reached */
18363 }
18364 duk_push_hobject(ctx, (duk_hobject *) target_ctx);
18365 duk__push_stash(ctx);
18366}
18367
18368/* XXX: duk_ssize_t would be useful here */
18369DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
18370 duk_int_t len;
18371
18373 DUK_UNREF(ctx);
18374
18375 /* NUL terminator handling doesn't matter here */
18376 len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
18377 if (len < (duk_int_t) sz) {
18378 /* Return value of 'sz' or more indicates output was (potentially)
18379 * truncated.
18380 */
18381 return (duk_int_t) len;
18382 }
18383 return -1;
18384}
18385
18386DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
18387 duk_hthread *thr = (duk_hthread *) ctx;
18388 duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
18390 duk_bool_t pushed_buf = 0;
18391 void *buf;
18392 duk_int_t len; /* XXX: duk_ssize_t */
18393 const char *res;
18394
18396
18397 /* special handling of fmt==NULL */
18398 if (!fmt) {
18399 duk_hstring *h_str;
18401 h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr); /* rely on interning, must be this string */
18402 return (const char *) DUK_HSTRING_GET_DATA(h_str);
18403 }
18404
18405 /* initial estimate based on format string */
18406 sz = DUK_STRLEN(fmt) + 16; /* format plus something to avoid just missing */
18409 }
18410 DUK_ASSERT(sz > 0);
18411
18412 /* Try to make do with a stack buffer to avoid allocating a temporary buffer.
18413 * This works 99% of the time which is quite nice.
18414 */
18415 for (;;) {
18416 va_list ap_copy; /* copied so that 'ap' can be reused */
18417
18418 if (sz <= sizeof(stack_buf)) {
18419 buf = stack_buf;
18420 } else if (!pushed_buf) {
18421 pushed_buf = 1;
18422 buf = duk_push_dynamic_buffer(ctx, sz);
18423 } else {
18424 buf = duk_resize_buffer(ctx, -1, sz);
18425 }
18426 DUK_ASSERT(buf != NULL);
18427
18428 DUK_VA_COPY(ap_copy, ap);
18429 len = duk__try_push_vsprintf(ctx, buf, sz, fmt, ap_copy);
18430 va_end(ap_copy);
18431 if (len >= 0) {
18432 break;
18433 }
18434
18435 /* failed, resize and try again */
18436 sz = sz * 2;
18439 }
18440 }
18441
18442 /* Cannot use duk_to_string() on the buffer because it is usually
18443 * larger than 'len'. Also, 'buf' is usually a stack buffer.
18444 */
18445 res = duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len); /* [ buf? res ] */
18446 if (pushed_buf) {
18447 duk_remove(ctx, -2);
18448 }
18449 return res;
18450}
18451
18452DUK_EXTERNAL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) {
18453 va_list ap;
18454 const char *ret;
18455
18457
18458 /* allow fmt==NULL */
18459 va_start(ap, fmt);
18460 ret = duk_push_vsprintf(ctx, fmt, ap);
18461 va_end(ap);
18462
18463 return ret;
18464}
18465
18466DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
18467 duk_hthread *thr = (duk_hthread *) ctx;
18468 duk_tval *tv_slot;
18469 duk_hobject *h;
18470 duk_idx_t ret;
18471
18473 DUK_ASSERT(prototype_bidx == -1 ||
18474 (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
18475
18476 /* check stack first */
18477 if (thr->valstack_top >= thr->valstack_end) {
18479 }
18480
18481 h = duk_hobject_alloc(thr->heap, hobject_flags_and_class);
18482 if (!h) {
18484 }
18485
18486 DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
18487
18488 tv_slot = thr->valstack_top;
18490 DUK_HOBJECT_INCREF(thr, h); /* no side effects */
18491 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18492 thr->valstack_top++;
18493
18494 /* object is now reachable */
18495
18496 if (prototype_bidx >= 0) {
18497 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[prototype_bidx]);
18498 } else {
18499 DUK_ASSERT(prototype_bidx == -1);
18501 }
18502
18503 return ret;
18505
18507 duk_hthread *thr = (duk_hthread *) ctx;
18508 duk_idx_t ret;
18509 duk_hobject *h;
18510
18512
18513 ret = duk_push_object_helper(ctx, hobject_flags_and_class, -1);
18514 h = duk_get_hobject(ctx, -1);
18515 DUK_ASSERT(h != NULL);
18518 return ret;
18519}
18520
18523
18524 return duk_push_object_helper(ctx,
18528}
18529
18531 duk_hthread *thr = (duk_hthread *) ctx;
18532 duk_hobject *obj;
18533 duk_idx_t ret;
18534
18536
18537 ret = duk_push_object_helper(ctx,
18542
18543 obj = duk_require_hobject(ctx, ret);
18544
18545 /*
18546 * An array must have a 'length' property (E5 Section 15.4.5.2).
18547 * The special array behavior flag must only be enabled once the
18548 * length property has been added.
18549 *
18550 * The internal property must be a number (and preferably a
18551 * fastint if fastint support is enabled).
18552 */
18553
18554 duk_push_int(ctx, 0);
18555#if defined(DUK_USE_FASTINT)
18556 DUK_ASSERT(DUK_TVAL_IS_FASTINT(duk_require_tval(ctx, -1)));
18557#endif
18558
18560 obj,
18564
18565 return ret;
18566}
18567
18569 duk_hthread *thr = (duk_hthread *) ctx;
18570 duk_hthread *obj;
18571 duk_idx_t ret;
18572 duk_tval *tv_slot;
18573
18575
18576 /* check stack first */
18577 if (thr->valstack_top >= thr->valstack_end) {
18579 }
18580
18581 obj = duk_hthread_alloc(thr->heap,
18585 if (!obj) {
18587 }
18589#if defined(DUK_USE_ROM_STRINGS)
18590 /* Nothing to initialize, strs[] is in ROM. */
18591#else
18592#if defined(DUK_USE_HEAPPTR16)
18593 obj->strs16 = thr->strs16;
18594#else
18595 obj->strs = thr->strs;
18596#endif
18597#endif
18598 DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
18599
18600 /* make the new thread reachable */
18601 tv_slot = thr->valstack_top;
18602 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18603 DUK_HTHREAD_INCREF(thr, obj);
18604 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18605 thr->valstack_top++;
18606
18607 /* important to do this *after* pushing, to make the thread reachable for gc */
18608 if (!duk_hthread_init_stacks(thr->heap, obj)) {
18610 }
18611
18612 /* initialize built-ins - either by copying or creating new ones */
18613 if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
18615 } else {
18617 }
18618
18619 /* default prototype (Note: 'obj' must be reachable) */
18621
18622 /* Initial stack size satisfies the stack spare constraints so there
18623 * is no need to require stack here.
18624 */
18627
18628 return ret;
18629}
18630
18632 duk_hthread *thr = (duk_hthread *) ctx;
18634 duk_idx_t ret;
18635 duk_tval *tv_slot;
18636
18638
18639 /* check stack first */
18640 if (thr->valstack_top >= thr->valstack_end) {
18642 }
18643
18644 /* Template functions are not strictly constructable (they don't
18645 * have a "prototype" property for instance), so leave the
18646 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
18647 */
18648
18653 if (!obj) {
18655 }
18656
18657 DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
18658
18659 tv_slot = thr->valstack_top;
18660 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18661 DUK_HOBJECT_INCREF(thr, obj);
18662 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18663 thr->valstack_top++;
18664
18665 /* default prototype (Note: 'obj' must be reachable) */
18667
18668 return ret;
18669}
18670
18672 duk_hthread *thr = (duk_hthread *) ctx;
18674 duk_idx_t ret;
18675 duk_tval *tv_slot;
18676 duk_int16_t func_nargs;
18677
18679
18680 /* check stack first */
18681 if (thr->valstack_top >= thr->valstack_end) {
18683 }
18684 if (func == NULL) {
18685 goto api_error;
18686 }
18687 if (nargs >= 0 && nargs < DUK_HNATIVEFUNCTION_NARGS_MAX) {
18688 func_nargs = (duk_int16_t) nargs;
18689 } else if (nargs == DUK_VARARGS) {
18691 } else {
18692 goto api_error;
18693 }
18694
18695 obj = duk_hnativefunction_alloc(thr->heap, flags);
18696 if (!obj) {
18698 }
18699
18700 obj->func = func;
18701 obj->nargs = func_nargs;
18702
18703 DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
18704 (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
18706 tv_slot = thr->valstack_top;
18707 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18708 DUK_HOBJECT_INCREF(thr, obj);
18709 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18710 thr->valstack_top++;
18711
18712 /* default prototype (Note: 'obj' must be reachable) */
18714
18715 return ret;
18716
18717 api_error:
18719 return 0; /* not reached */
18720}
18721
18737}
18752 (void) duk__push_c_function_raw(ctx, func, nargs, flags);
18754
18756 duk_uint_t flags;
18757
18759
18766
18767 (void) duk__push_c_function_raw(ctx, func, nargs, flags);
18768}
18769
18771 duk_hthread *thr = (duk_hthread *) ctx;
18772 duk_tval tv_tmp;
18773 duk_small_uint_t lf_flags;
18774
18776
18777 /* check stack first */
18778 if (thr->valstack_top >= thr->valstack_end) {
18780 }
18781
18782 if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
18783 /* as is */
18784 } else if (nargs == DUK_VARARGS) {
18786 } else {
18787 goto api_error;
18788 }
18789 if (!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX)) {
18790 goto api_error;
18791 }
18792 if (!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX)) {
18793 goto api_error;
18794 }
18795
18796 lf_flags = DUK_LFUNC_FLAGS_PACK(magic, length, nargs);
18797 DUK_TVAL_SET_LIGHTFUNC(&tv_tmp, func, lf_flags);
18798 duk_push_tval(ctx, &tv_tmp); /* XXX: direct valstack write */
18800 return ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
18801
18802 api_error:
18804 return 0; /* not reached */
18805}
18806
18807DUK_INTERNAL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
18808 duk_hthread *thr = (duk_hthread *) ctx;
18809 duk_hbufferobject *obj;
18810 duk_tval *tv_slot;
18811
18812 DUK_ASSERT(ctx != NULL);
18813 DUK_ASSERT(prototype_bidx >= 0);
18814
18815 /* check stack first */
18816 if (thr->valstack_top >= thr->valstack_end) {
18818 }
18819
18820 obj = duk_hbufferobject_alloc(thr->heap, hobject_flags_and_class);
18821 if (!obj) {
18824
18825 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
18827
18828 tv_slot = thr->valstack_top;
18829 DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18830 DUK_HOBJECT_INCREF(thr, obj);
18831 thr->valstack_top++;
18832
18833 return obj;
18834}
18835
18836/* XXX: There's quite a bit of overlap with buffer creation handling in
18837 * duk_bi_buffer.c. Look for overlap and refactor.
18838 */
18839#define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,isview) \
18840 (((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (isview))
18841
18842#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
18843static const duk_uint32_t duk__bufobj_flags_lookup[] = {
18857};
18858#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
18859/* Only allow Duktape.Buffer when support disabled. */
18860static const duk_uint32_t duk__bufobj_flags_lookup[] = {
18862};
18863#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
18864#undef DUK__PACK_ARGS
18865
18866DUK_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) {
18867 duk_hthread *thr;
18868 duk_hbufferobject *h_bufobj;
18869 duk_hbuffer *h_val;
18870 duk_uint32_t tmp;
18871 duk_uint_t classnum;
18872 duk_uint_t protobidx;
18873 duk_uint_t lookupidx;
18874 duk_uint_t uint_offset, uint_length, uint_added;
18875
18877 thr = (duk_hthread *) ctx;
18878 DUK_UNREF(thr);
18879
18880 /* The underlying types for offset/length in duk_hbufferobject is
18881 * duk_uint_t; make sure argument values fit and that offset + length
18882 * does not wrap.
18883 */
18884 uint_offset = (duk_uint_t) byte_offset;
18885 uint_length = (duk_uint_t) byte_length;
18886 if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
18887 if ((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length) {
18888 goto range_error;
18889 }
18890 }
18891 uint_added = uint_offset + uint_length;
18892 if (uint_added < uint_offset) {
18893 goto range_error;
18894 }
18895 DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
18896
18897 DUK_ASSERT_DISABLE(flags >= 0); /* flags is unsigned */
18898 lookupidx = flags & 0x0f; /* 4 low bits */
18899 if (lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t)) {
18900 goto arg_error;
18901 }
18902 tmp = duk__bufobj_flags_lookup[lookupidx];
18903 classnum = tmp >> 24;
18904 protobidx = (tmp >> 16) & 0xff;
18905
18906 h_val = duk_require_hbuffer(ctx, idx_buffer);
18907 DUK_ASSERT(h_val != NULL);
18908
18909 h_bufobj = duk_push_bufferobject_raw(ctx,
18913 protobidx);
18914 DUK_ASSERT(h_bufobj != NULL);
18915
18916 h_bufobj->buf = h_val;
18917 DUK_HBUFFER_INCREF(thr, h_val);
18918 h_bufobj->offset = uint_offset;
18919 h_bufobj->length = uint_length;
18920 h_bufobj->shift = (tmp >> 4) & 0x0f;
18921 h_bufobj->elem_type = (tmp >> 8) & 0xff;
18922 h_bufobj->is_view = tmp & 0x0f;
18924
18925#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
18926 /* TypedArray views need an automatic ArrayBuffer which must be
18927 * provided as .buffer property of the view. Just create a new
18928 * ArrayBuffer sharing the same underlying buffer.
18929 */
18930 if (flags & DUK_BUFOBJ_CREATE_ARRBUF) {
18931 h_bufobj = duk_push_bufferobject_raw(ctx,
18936
18937 DUK_ASSERT(h_bufobj != NULL);
18938
18939 h_bufobj->buf = h_val;
18940 DUK_HBUFFER_INCREF(thr, h_val);
18941 h_bufobj->offset = uint_offset;
18942 h_bufobj->length = uint_length;
18943 DUK_ASSERT(h_bufobj->shift == 0);
18945 DUK_ASSERT(h_bufobj->is_view == 0);
18949 duk_compact(ctx, -1);
18950 }
18951#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
18952
18953 return;
18954
18955 range_error:
18957 return; /* not reached */
18958
18959 arg_error:
18961 return; /* not reached */
18962}
18963
18964DUK_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) {
18965 duk_hthread *thr = (duk_hthread *) ctx;
18966 duk_idx_t ret;
18968#ifdef DUK_USE_AUGMENT_ERROR_CREATE
18969 duk_bool_t noblame_fileline;
18970#endif
18971
18973 DUK_ASSERT(thr != NULL);
18974 DUK_UNREF(filename);
18975 DUK_UNREF(line);
18976
18977 /* Error code also packs a tracedata related flag. */
18978#ifdef DUK_USE_AUGMENT_ERROR_CREATE
18979 noblame_fileline = err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE;
18980#endif
18981 err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
18982
18983 /* error gets its 'name' from the prototype */
18984 proto = duk_error_prototype_from_code(thr, err_code);
18988 proto);
18989
18990 /* ... and its 'message' from an instance property */
18991 if (fmt) {
18992 duk_push_vsprintf(ctx, fmt, ap);
18994 } else {
18995 /* If no explicit message given, put error code into message field
18996 * (as a number). This is not fully in keeping with the Ecmascript
18997 * error model because messages are supposed to be strings (Error
18998 * constructors use ToString() on their argument). However, it's
18999 * probably more useful than having a separate 'code' property.
19000 */
19001 duk_push_int(ctx, err_code);
19003 }
19004
19005 /* XXX: .code = err_code disabled, not sure if useful */
19006
19007 /* Creation time error augmentation */
19008#ifdef DUK_USE_AUGMENT_ERROR_CREATE
19009 /* filename may be NULL in which case file/line is not recorded */
19010 duk_err_augment_error_create(thr, thr, filename, line, noblame_fileline); /* may throw an error */
19011#endif
19013 return ret;
19014}
19015
19016DUK_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, ...) {
19017 va_list ap;
19018 duk_idx_t ret;
19019
19021
19022 va_start(ap, fmt);
19023 ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19024 va_end(ap);
19025 return ret;
19026}
19027
19028#if !defined(DUK_USE_VARIADIC_MACROS)
19030 const char *filename = duk_api_global_filename;
19032 va_list ap;
19033 duk_idx_t ret;
19034
19036
19039 va_start(ap, fmt);
19040 ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19041 va_end(ap);
19042 return ret;
19043}
19044#endif /* DUK_USE_VARIADIC_MACROS */
19045
19047 duk_hthread *thr = (duk_hthread *) ctx;
19048 duk_tval *tv_slot;
19049 duk_hbuffer *h;
19050 void *buf_data;
19051
19053
19054 /* check stack first */
19055 if (thr->valstack_top >= thr->valstack_end) {
19057 }
19058
19059 /* Check for maximum buffer length. */
19062 }
19063
19064 h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
19065 if (!h) {
19067 }
19068
19069 tv_slot = thr->valstack_top;
19070 DUK_TVAL_SET_BUFFER(tv_slot, h);
19071 DUK_HBUFFER_INCREF(thr, h);
19072 thr->valstack_top++;
19073
19074 return (void *) buf_data;
19075}
19076
19078 duk_hthread *thr = (duk_hthread *) ctx;
19079 duk_idx_t ret;
19080
19082
19083 ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
19084
19085 if (ptr == NULL) {
19086 goto push_undefined;
19087 }
19088
19089 switch ((int) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
19090 case DUK_HTYPE_STRING:
19091 duk_push_hstring(ctx, (duk_hstring *) ptr);
19092 break;
19093 case DUK_HTYPE_OBJECT:
19094 duk_push_hobject(ctx, (duk_hobject *) ptr);
19095 break;
19096 case DUK_HTYPE_BUFFER:
19097 duk_push_hbuffer(ctx, (duk_hbuffer *) ptr);
19098 break;
19099 default:
19100 goto push_undefined;
19101 }
19102 return ret;
19103
19104 push_undefined:
19105 duk_push_undefined(ctx);
19106 return ret;
19113 -1); /* no prototype */
19115
19117 duk_tval tv;
19119 DUK_ASSERT(h != NULL);
19120 DUK_TVAL_SET_STRING(&tv, h);
19121 duk_push_tval(ctx, &tv);
19123
19125 duk_hthread *thr = (duk_hthread *) ctx;
19126 DUK_UNREF(thr);
19127 DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
19128 duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
19129}
19132 duk_tval tv;
19134 DUK_ASSERT(h != NULL);
19135 DUK_TVAL_SET_OBJECT(&tv, h);
19136 duk_push_tval(ctx, &tv);
19137}
19138
19140 duk_tval tv;
19142 DUK_ASSERT(h != NULL);
19144 duk_push_tval(ctx, &tv);
19145}
19146
19148 duk_hthread *thr = (duk_hthread *) ctx;
19150 DUK_ASSERT(thr != NULL);
19151 DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
19152 DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
19153 duk_push_hobject(ctx, thr->builtins[builtin_idx]);
19154}
19155
19156/*
19157 * Poppers
19158 */
19159
19160DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) {
19161 duk_hthread *thr = (duk_hthread *) ctx;
19162 duk_tval *tv;
19163
19165
19166 if (DUK_UNLIKELY(count < 0)) {
19168 return;
19169 }
19170
19172 if (DUK_UNLIKELY((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count)) {
19174 }
19175
19176 /*
19177 * Must be very careful here, every DECREF may cause reallocation
19178 * of our valstack.
19179 */
19180
19181 /* XXX: inlined DECREF macro would be nice here: no NULL check,
19182 * refzero queueing but no refzero algorithm run (= no pointer
19183 * instability), inline code.
19184 */
19185
19186 /* XXX: optimize loops */
19187
19188#if defined(DUK_USE_REFERENCE_COUNTING)
19189 while (count > 0) {
19190 count--;
19191 tv = --thr->valstack_top; /* tv points to element just below prev top */
19192 DUK_ASSERT(tv >= thr->valstack_bottom);
19193 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
19194 }
19195#else
19196 tv = thr->valstack_top;
19197 while (count > 0) {
19198 count--;
19199 tv--;
19200 DUK_ASSERT(tv >= thr->valstack_bottom);
19202 }
19203 thr->valstack_top = tv;
19204#endif
19205
19207}
19208
19209/* Popping one element is called so often that when footprint is not an issue,
19210 * compile a specialized function for it.
19211 */
19212#if defined(DUK_USE_PREFER_SIZE)
19213DUK_EXTERNAL void duk_pop(duk_context *ctx) {
19215 duk_pop_n(ctx, 1);
19216}
19217#else
19218DUK_EXTERNAL void duk_pop(duk_context *ctx) {
19219 duk_hthread *thr = (duk_hthread *) ctx;
19220 duk_tval *tv;
19226 }
19228 tv = --thr->valstack_top; /* tv points to element just below prev top */
19229 DUK_ASSERT(tv >= thr->valstack_bottom);
19230#ifdef DUK_USE_REFERENCE_COUNTING
19231 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
19232#else
19234#endif
19237#endif /* !DUK_USE_PREFER_SIZE */
19238
19241 duk_pop_n(ctx, 2);
19242}
19243
19246 duk_pop_n(ctx, 3);
19247}
19248
19249/*
19250 * Error throwing
19251 */
19252
19254 duk_hthread *thr = (duk_hthread *) ctx;
19255
19256 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
19258 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
19259
19260 if (thr->valstack_top == thr->valstack_bottom) {
19262 }
19263
19264 /* Errors are augmented when they are created, not when they are
19265 * thrown or re-thrown. The current error handler, however, runs
19266 * just before an error is thrown.
19267 */
19268
19269 /* Sync so that augmentation sees up-to-date activations, NULL
19270 * thr->ptr_curr_pc so that it's not used if side effects occur
19271 * in augmentation or longjmp handling.
19272 */
19274
19275#if defined(DUK_USE_AUGMENT_ERROR_THROW)
19276 DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
19278#endif
19279 DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
19280
19282
19283 /* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
19284 * need to check that here. If the value is NULL, a panic occurs because
19285 * we can't return.
19286 */
19287
19288 duk_err_longjmp(thr);
19290}
19291
19292DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg) {
19293 duk_hthread *thr = (duk_hthread *) ctx;
19294
19296 DUK_ASSERT(thr != NULL);
19297 DUK_ASSERT(thr->heap != NULL);
19298 DUK_ASSERT(thr->heap->fatal_func != NULL);
19299
19300 DUK_D(DUK_DPRINT("fatal error occurred, code %ld, message %s",
19301 (long) err_code, (const char *) err_msg));
19303 /* fatal_func should be noreturn, but noreturn declarations on function
19304 * pointers has a very spotty support apparently so it's not currently
19305 * done.
19306 */
19307 thr->heap->fatal_func(ctx, err_code, err_msg);
19308
19309 DUK_PANIC(DUK_ERR_API_ERROR, "fatal handler returned");
19310}
19311
19312DUK_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) {
19315 duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19316 duk_throw(ctx);
19317}
19318
19319DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
19320 va_list ap;
19321
19323
19324 va_start(ap, fmt);
19325 duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19326 va_end(ap);
19327 duk_throw(ctx);
19328}
19329
19330#if !defined(DUK_USE_VARIADIC_MACROS)
19331DUK_EXTERNAL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
19332 const char *filename;
19333 duk_int_t line;
19334 va_list ap;
19335
19338 filename = duk_api_global_filename;
19339 line = duk_api_global_line;
19342
19343 va_start(ap, fmt);
19344 duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19345 va_end(ap);
19346 duk_throw(ctx);
19347}
19348#endif /* DUK_USE_VARIADIC_MACROS */
19349
19350/*
19351 * Comparison
19352 */
19353
19355 duk_hthread *thr = (duk_hthread *) ctx;
19356 duk_tval *tv1, *tv2;
19357
19359
19360 tv1 = duk_get_tval(ctx, index1);
19361 tv2 = duk_get_tval(ctx, index2);
19362 if ((tv1 == NULL) || (tv2 == NULL)) {
19363 return 0;
19364 }
19365
19366 /* Coercion may be needed, the helper handles that by pushing the
19367 * tagged values to the stack.
19368 */
19369 return duk_js_equals(thr, tv1, tv2);
19370}
19371
19373 duk_tval *tv1, *tv2;
19376
19377 tv1 = duk_get_tval(ctx, index1);
19378 tv2 = duk_get_tval(ctx, index2);
19379 if ((tv1 == NULL) || (tv2 == NULL)) {
19380 return 0;
19381 }
19382
19383 /* No coercions or other side effects, so safe */
19384 return duk_js_strict_equals(tv1, tv2);
19385}
19386
19387/*
19388 * instanceof
19389 */
19390
19392 duk_tval *tv1, *tv2;
19393
19395
19396 /* Index validation is strict, which differs from duk_equals().
19397 * The strict behavior mimics how instanceof itself works, e.g.
19398 * it is a TypeError if rval is not a -callable- object. It would
19399 * be somewhat inconsistent if rval would be allowed to be
19400 * non-existent without a TypeError.
19401 */
19402 tv1 = duk_require_tval(ctx, index1);
19403 DUK_ASSERT(tv1 != NULL);
19404 tv2 = duk_require_tval(ctx, index2);
19405 DUK_ASSERT(tv2 != NULL);
19406
19407 return duk_js_instanceof((duk_hthread *) ctx, tv1, tv2);
19408}
19409
19410/*
19411 * Lightfunc
19412 */
19413
19415 duk_c_function func;
19416
19418
19419 /* Lightfunc name, includes Duktape/C native function pointer, which
19420 * can often be used to locate the function from a symbol table.
19421 * The name also includes the 16-bit duk_tval flags field because it
19422 * includes the magic value. Because a single native function often
19423 * provides different functionality depending on the magic value, it
19424 * seems reasonably to include it in the name.
19425 *
19426 * On the other hand, a complicated name increases string table
19427 * pressure in low memory environments (but only when function name
19428 * is accessed).
19429 */
19430
19432 duk_push_sprintf(ctx, "light_");
19433 duk_push_string_funcptr(ctx, (duk_uint8_t *) &func, sizeof(func));
19434 duk_push_sprintf(ctx, "_%04x", (unsigned int) DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv));
19435 duk_concat(ctx, 3);
19436}
19440
19441 duk_push_string(ctx, "function ");
19442 duk_push_lightfunc_name(ctx, tv);
19443 duk_push_string(ctx, "() {\"light\"}");
19444 duk_concat(ctx, 3);
19445}
19446
19447/*
19448 * Function pointers
19449 *
19450 * Printing function pointers is non-portable, so we do that by hex printing
19451 * bytes from memory.
19452 */
19453
19454DUK_INTERNAL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz) {
19455 duk_uint8_t buf[32 * 2];
19456 duk_uint8_t *p, *q;
19459
19460 DUK_ASSERT(sz <= 32); /* sanity limit for function pointer size */
19461
19462 p = buf;
19463#if defined(DUK_USE_INTEGER_LE)
19464 q = ptr + sz;
19465#else
19466 q = ptr;
19467#endif
19468 for (i = 0; i < sz; i++) {
19469#if defined(DUK_USE_INTEGER_LE)
19470 t = *(--q);
19471#else
19472 t = *(q++);
19473#endif
19474 *p++ = duk_lc_digits[t >> 4];
19475 *p++ = duk_lc_digits[t & 0x0f];
19476 }
19477
19478 duk_push_lstring(ctx, (const char *) buf, sz * 2);
19480
19481#if !defined(DUK_USE_PARANOID_ERRORS)
19482/*
19483 * Push readable string summarizing duk_tval. The operation is side effect
19484 * free and will only throw from internal errors (e.g. out of memory).
19485 * This is used by e.g. property access code to summarize a key/base safely,
19486 * and is not intended to be fast (but small and safe).
19487 */
19488
19489#define DUK__READABLE_STRING_MAXCHARS 32
19490
19491/* String sanitizer which escapes ASCII control characters and a few other
19492 * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
19493 * question marks. No errors are thrown for any input string, except in out
19494 * of memory situations.
19495 */
19497 duk_hthread *thr;
19498 const duk_uint8_t *p, *p_start, *p_end;
19500 2 /*quotes*/ + 3 /*periods*/];
19501 duk_uint8_t *q;
19503 duk_small_uint_t nchars;
19504
19506 DUK_ASSERT(h_input != NULL);
19507 thr = (duk_hthread *) ctx;
19508
19509 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19510 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19511 p = p_start;
19512 q = buf;
19513
19514 nchars = 0;
19515 *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
19516 for (;;) {
19517 if (p >= p_end) {
19518 break;
19519 }
19520 if (nchars == DUK__READABLE_STRING_MAXCHARS) {
19521 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19522 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19523 *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19524 break;
19525 }
19526 if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
19527 if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
19528 DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4); /* estimate is valid */
19529 DUK_ASSERT((cp >> 4) <= 0x0f);
19530 *q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
19531 *q++ = (duk_uint8_t) DUK_ASC_LC_X;
19532 *q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
19533 *q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
19534 } else {
19535 q += duk_unicode_encode_xutf8(cp, q);
19536 }
19537 } else {
19538 p++; /* advance manually */
19539 *q++ = (duk_uint8_t) DUK_ASC_QUESTION;
19540 }
19541 nchars++;
19542 }
19543 *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
19544
19545 duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (q - buf));
19546}
19547
19549 duk_hthread *thr;
19550
19552 thr = (duk_hthread *) ctx;
19553 DUK_UNREF(thr);
19554
19555 if (tv == NULL) {
19556 duk_push_string(ctx, "none");
19557 } else {
19558 switch (DUK_TVAL_GET_TAG(tv)) {
19559 case DUK_TAG_STRING: {
19561 break;
19562 }
19563 case DUK_TAG_OBJECT: {
19565 DUK_ASSERT(h != NULL);
19567 break;
19568 }
19569 case DUK_TAG_BUFFER: {
19570 /* XXX: Hex encoded, length limited buffer summary here? */
19572 DUK_ASSERT(h != NULL);
19573 duk_push_sprintf(ctx, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
19574 break;
19575 }
19576 case DUK_TAG_POINTER: {
19577 /* Surround with parentheses like in JX, ensures NULL pointer
19578 * is distinguishable from null value ("(null)" vs "null").
19579 */
19580 duk_push_tval(ctx, tv);
19581 duk_push_sprintf(ctx, "(%s)", duk_to_string(ctx, -1));
19582 duk_remove(ctx, -2);
19583 break;
19584 }
19585 default: {
19586 duk_push_tval(ctx, tv);
19587 break;
19588 }
19589 }
19590 }
19591
19592 return duk_to_string(ctx, -1);
19593}
19598}
19599#endif /* !DUK_USE_PARANOID_ERRORS */
19600
19601#undef DUK__CHECK_SPACE
19602#undef DUK__PACK_ARGS
19603#undef DUK__READABLE_STRING_MAXCHARS
19604#line 1 "duk_api_string.c"
19605/*
19606 * String manipulation
19607 */
19608
19609/* include removed: duk_internal.h */
19610
19612 duk_hthread *thr = (duk_hthread *) ctx;
19613 duk_uint_t count;
19614 duk_uint_t i;
19615 duk_size_t idx;
19616 duk_size_t len;
19617 duk_hstring *h;
19618 duk_uint8_t *buf;
19619
19621
19622 if (DUK_UNLIKELY(count_in <= 0)) {
19623 if (count_in < 0) {
19625 return;
19626 }
19627 DUK_ASSERT(count_in == 0);
19629 return;
19630 }
19631 count = (duk_uint_t) count_in;
19632
19633 if (is_join) {
19634 duk_size_t t1, t2, limit;
19635 h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1);
19636 DUK_ASSERT(h != NULL);
19637
19638 /* A bit tricky overflow test, see doc/code-issues.rst. */
19640 t2 = (duk_size_t) (count - 1);
19642 if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
19643 /* Combined size of separators already overflows */
19644 goto error_overflow;
19645 }
19646 len = (duk_size_t) (t1 * t2);
19647 } else {
19648 len = (duk_size_t) 0;
19649 }
19650
19651 for (i = count; i >= 1; i--) {
19652 duk_size_t new_len;
19653 duk_to_string(ctx, -((duk_idx_t) i));
19654 h = duk_require_hstring(ctx, -((duk_idx_t) i));
19655 new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
19656
19657 /* Impose a string maximum length, need to handle overflow
19658 * correctly.
19659 */
19660 if (new_len < len || /* wrapped */
19661 new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
19662 goto error_overflow;
19663 }
19664 len = new_len;
19665 }
19666
19667 DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
19668 (unsigned long) count, (unsigned long) len));
19669
19670 /* use stack allocated buffer to ensure reachability in errors (e.g. intern error) */
19671 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len);
19672 DUK_ASSERT(buf != NULL);
19673
19674 /* [... (sep) str1 str2 ... strN buf] */
19675
19676 idx = 0;
19677 for (i = count; i >= 1; i--) {
19678 if (is_join && i != count) {
19679 h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2); /* extra -1 for buffer */
19681 idx += DUK_HSTRING_GET_BYTELEN(h);
19682 }
19683 h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1); /* extra -1 for buffer */
19685 idx += DUK_HSTRING_GET_BYTELEN(h);
19686 }
19687
19688 DUK_ASSERT(idx == len);
19689
19690 /* [... (sep) str1 str2 ... strN buf] */
19691
19692 /* get rid of the strings early to minimize memory use before intern */
19693
19694 if (is_join) {
19695 duk_replace(ctx, -((duk_idx_t) count) - 2); /* overwrite sep */
19696 duk_pop_n(ctx, count);
19697 } else {
19698 duk_replace(ctx, -((duk_idx_t) count) - 1); /* overwrite str1 */
19699 duk_pop_n(ctx, count-1);
19700 }
19701
19702 /* [... buf] */
19703
19704 (void) duk_to_string(ctx, -1);
19705
19706 /* [... res] */
19707 return;
19708
19709 error_overflow:
19711}
19713DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) {
19715
19716 duk__concat_and_join_helper(ctx, count, 0 /*is_join*/);
19717}
19718
19719DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) {
19721
19722 duk__concat_and_join_helper(ctx, count, 1 /*is_join*/);
19723}
19724
19725/* XXX: could map/decode be unified with duk_unicode_support.c code?
19726 * Case conversion needs also the character surroundings though.
19727 */
19728
19730 duk_hthread *thr = (duk_hthread *) ctx;
19731 duk_hstring *h_input;
19732 const duk_uint8_t *p, *p_start, *p_end;
19733 duk_codepoint_t cp;
19734
19737 h_input = duk_require_hstring(ctx, index);
19738 DUK_ASSERT(h_input != NULL);
19739
19740 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19741 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19742 p = p_start;
19743
19744 for (;;) {
19745 if (p >= p_end) {
19746 break;
19747 }
19748 cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
19749 callback(udata, cp);
19750 }
19751}
19752
19754 duk_hthread *thr = (duk_hthread *) ctx;
19755 duk_hstring *h_input;
19756 duk_bufwriter_ctx bw_alloc;
19758 const duk_uint8_t *p, *p_start, *p_end;
19759 duk_codepoint_t cp;
19760
19762
19764
19765 h_input = duk_require_hstring(ctx, index);
19766 DUK_ASSERT(h_input != NULL);
19767
19768 bw = &bw_alloc;
19769 DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* reasonable output estimate */
19770
19771 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19772 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19773 p = p_start;
19774
19775 for (;;) {
19776 /* XXX: could write output in chunks with fewer ensure calls,
19777 * but relative benefit would be small here.
19778 */
19779
19780 if (p >= p_end) {
19781 break;
19782 }
19783 cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
19784 cp = callback(udata, cp);
19785
19786 DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
19787 }
19788
19789 DUK_BW_COMPACT(thr, bw);
19790 duk_to_string(ctx, -1);
19791 duk_replace(ctx, index);
19792}
19793
19794DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset) {
19795 duk_hthread *thr = (duk_hthread *) ctx;
19796 duk_hstring *h;
19797 duk_hstring *res;
19798 duk_size_t start_byte_offset;
19799 duk_size_t end_byte_offset;
19800
19802
19804 h = duk_require_hstring(ctx, index);
19805 DUK_ASSERT(h != NULL);
19806
19807 if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
19808 end_offset = DUK_HSTRING_GET_CHARLEN(h);
19809 }
19810 if (start_offset > end_offset) {
19811 start_offset = end_offset;
19812 }
19813
19814 DUK_ASSERT_DISABLE(start_offset >= 0);
19815 DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
19816 DUK_ASSERT_DISABLE(end_offset >= 0);
19817 DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
19818
19819 /* guaranteed by string limits */
19820 DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
19821 DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
19822
19823 start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
19824 end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
19825
19826 DUK_ASSERT(end_byte_offset >= start_byte_offset);
19827 DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* guaranteed by string limits */
19828
19829 /* no size check is necessary */
19831 DUK_HSTRING_GET_DATA(h) + start_byte_offset,
19832 (duk_uint32_t) (end_byte_offset - start_byte_offset));
19833
19834 duk_push_hstring(ctx, res);
19835 duk_replace(ctx, index);
19836}
19837
19838/* XXX: this is quite clunky. Add Unicode helpers to scan backwards and
19839 * forwards with a callback to process codepoints?
19840 */
19842 duk_hthread *thr = (duk_hthread *) ctx;
19843 duk_hstring *h;
19844 const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */
19845 const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */
19846 duk_codepoint_t cp;
19847
19849
19851 h = duk_require_hstring(ctx, index);
19852 DUK_ASSERT(h != NULL);
19853
19854 p_start = DUK_HSTRING_GET_DATA(h);
19855 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
19856
19857 p = p_start;
19858 while (p < p_end) {
19859 p_tmp1 = p;
19860 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
19862 break;
19863 }
19864 p = p_tmp1;
19865 }
19866 q_start = p;
19867 if (p == p_end) {
19868 /* entire string is whitespace */
19869 q_end = p;
19870 goto scan_done;
19871 }
19872
19873 p = p_end;
19874 while (p > p_start) {
19875 p_tmp1 = p;
19876 while (p > p_start) {
19877 p--;
19878 if (((*p) & 0xc0) != 0x80) {
19879 break;
19880 }
19881 }
19882 p_tmp2 = p;
19883
19884 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
19886 p = p_tmp1;
19887 break;
19888 }
19889 }
19890 q_end = p;
19891
19892 scan_done:
19893 /* This may happen when forward and backward scanning disagree
19894 * (possible for non-extended-UTF-8 strings).
19895 */
19896 if (q_end < q_start) {
19897 q_end = q_start;
19898 }
19899
19900 DUK_ASSERT(q_start >= p_start && q_start <= p_end);
19901 DUK_ASSERT(q_end >= p_start && q_end <= p_end);
19902 DUK_ASSERT(q_end >= q_start);
19903
19904 DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
19905 (const void *) p_start, (const void *) p_end,
19906 (const void *) q_start, (const void *) q_end));
19907
19908 if (q_start == p_start && q_end == p_end) {
19909 DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
19910 return;
19911 }
19912
19913 duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start));
19914 duk_replace(ctx, index);
19915}
19916
19918 duk_hthread *thr = (duk_hthread *) ctx;
19919 duk_hstring *h;
19921
19923
19924 h = duk_require_hstring(ctx, index);
19925 DUK_ASSERT(h != NULL);
19927 DUK_ASSERT_DISABLE(char_offset >= 0); /* always true, arg is unsigned */
19928 if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
19929 return 0;
19930 }
19931
19932 DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* guaranteed by string limits */
19933 cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset);
19934 return (duk_codepoint_t) cp;
19935}
19936#line 1 "duk_api_var.c"
19937/*
19938 * Variable access
19939 */
19940
19941/* include removed: duk_internal.h */
19942
19944 duk_hthread *thr = (duk_hthread *) ctx;
19945 duk_activation *act;
19946 duk_hstring *h_varname;
19947 duk_small_int_t throw_flag = 1; /* always throw ReferenceError for unresolvable */
19948
19950
19951 h_varname = duk_require_hstring(ctx, -1); /* XXX: tostring? */
19952 DUK_ASSERT(h_varname != NULL);
19953
19955 if (act) {
19956 (void) duk_js_getvar_activation(thr, act, h_varname, throw_flag); /* -> [ ... varname val this ] */
19957 } else {
19958 /* Outside any activation -> look up from global. */
19960 (void) duk_js_getvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, throw_flag);
19961 }
19962
19963 /* [ ... varname val this ] (because throw_flag == 1, always resolved) */
19964
19965 duk_pop(ctx);
19966 duk_remove(ctx, -2);
19967
19968 /* [ ... val ] */
19969
19970 /* Return value would be pointless: because throw_flag==1, we always
19971 * throw if the identifier doesn't resolve.
19972 */
19973 return;
19974}
19975
19977 duk_hthread *thr = (duk_hthread *) ctx;
19978 duk_activation *act;
19979 duk_hstring *h_varname;
19980 duk_tval *tv_val;
19981 duk_small_int_t throw_flag;
19982
19984
19985 h_varname = duk_require_hstring(ctx, -2); /* XXX: tostring? */
19986 DUK_ASSERT(h_varname != NULL);
19987
19988 tv_val = duk_require_tval(ctx, -1);
19989
19990 throw_flag = duk_is_strict_call(ctx);
19991
19993 if (act) {
19994 duk_js_putvar_activation(thr, act, h_varname, tv_val, throw_flag); /* -> [ ... varname val this ] */
19995 } else {
19996 /* Outside any activation -> put to global. */
19998 duk_js_putvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, tv_val, throw_flag);
19999 }
20001 /* [ ... varname val ] */
20002
20003 duk_pop_2(ctx);
20004
20005 /* [ ... ] */
20006
20007 return;
20008}
20009
20012
20014 return 0;
20015}
20016
20019
20021 return 0;
20022}
20023#line 1 "duk_bi_array.c"
20024/*
20025 * Array built-ins
20026 *
20027 * Note that most Array built-ins are intentionally generic and work even
20028 * when the 'this' binding is not an Array instance. To ensure this,
20029 * Array algorithms do not assume "magical" Array behavior for the "length"
20030 * property, for instance.
20031 *
20032 * XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
20033 * [[Delete]] operations, but it's currently false throughout. Go through
20034 * all put/delete cases and check throw flag use. Need a new API primitive
20035 * which allows throws flag to be specified.
20036 *
20037 * XXX: array lengths above 2G won't work reliably. There are many places
20038 * where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
20039 * i.e. -33- bits). Although array 'length' cannot be written to be outside
20040 * the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
20041 * some intermediate values may be above 0xffffffff and this may not be always
20042 * correctly handled now (duk_uint32_t is not enough for all algorithms).
20043 *
20044 * For instance, push() can legitimately write entries beyond length 0xffffffff
20045 * and cause a RangeError only at the end. To do this properly, the current
20046 * push() implementation tracks the array index using a 'double' instead of a
20047 * duk_uint32_t (which is somewhat awkward). See test-bi-array-push-maxlen.js.
20048 *
20049 * On using "put" vs. "def" prop
20050 * =============================
20051 *
20052 * Code below must be careful to use the appropriate primitive as it matters
20053 * for compliance. When using "put" there may be inherited properties in
20054 * Array.prototype which cause side effects when values are written. When
20055 * using "define" there are no such side effects, and many test262 test cases
20056 * check for this (for real world code, such side effects are very rare).
20057 * Both "put" and "define" are used in the E5.1 specification; as a rule,
20058 * "put" is used when modifying an existing array (or a non-array 'this'
20059 * binding) and "define" for setting values into a fresh result array.
20061 * Also note that Array instance 'length' should be writable, but not
20062 * enumerable and definitely not configurable: even Duktape code internally
20063 * assumes that an Array instance will always have a 'length' property.
20064 * Preventing deletion of the property is critical.
20065 */
20066
20067/* include removed: duk_internal.h */
20068
20069/* Perform an intermediate join when this many elements have been pushed
20070 * on the value stack.
20072#define DUK__ARRAY_MID_JOIN_LIMIT 4096
20073
20074/* Shared entry code for many Array built-ins. Note that length is left
20075 * on stack (it could be popped, but that's not necessary).
20076 */
20078 duk_uint32_t len;
20079
20082 len = duk_to_uint32(ctx, -1);
20083
20084 /* -> [ ... ToObject(this) ToUint32(length) ] */
20085 return len;
20086}
20089 /* Range limited to [0, 0x7fffffff] range, i.e. range that can be
20090 * represented with duk_int32_t. Use this when the method doesn't
20091 * handle the full 32-bit unsigned range correctly.
20092 */
20093 duk_uint32_t ret = duk__push_this_obj_len_u32(ctx);
20094 if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
20096 }
20097 return ret;
20098}
20099
20100/*
20101 * Constructor
20102 */
20103
20105 duk_idx_t nargs;
20106 duk_double_t d;
20107 duk_uint32_t len;
20108 duk_idx_t i;
20109
20110 nargs = duk_get_top(ctx);
20111 duk_push_array(ctx);
20112
20113 if (nargs == 1 && duk_is_number(ctx, 0)) {
20114 /* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
20115 d = duk_get_number(ctx, 0);
20116 len = duk_to_uint32(ctx, 0);
20117 if (((duk_double_t) len) != d) {
20118 return DUK_RET_RANGE_ERROR;
20119 }
20120
20121 /* XXX: if 'len' is low, may want to ensure array part is kept:
20122 * the caller is likely to want a dense array.
20123 */
20124 duk_push_u32(ctx, len);
20125 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W); /* [ ToUint32(len) array ToUint32(len) ] -> [ ToUint32(len) array ] */
20126 return 1;
20127 }
20128
20129 /* XXX: optimize by creating array into correct size directly, and
20130 * operating on the array part directly; values can be memcpy()'d from
20131 * value stack directly as long as refcounts are increased.
20132 */
20133 for (i = 0; i < nargs; i++) {
20134 duk_dup(ctx, i);
20136 }
20137
20138 duk_push_u32(ctx, (duk_uint32_t) nargs);
20140 return 1;
20141}
20143/*
20144 * isArray()
20145 */
20146
20148 duk_hobject *h;
20149
20151 duk_push_boolean(ctx, (h != NULL));
20152 return 1;
20153}
20154
20155/*
20156 * toString()
20157 */
20158
20162
20163 /* [ ... this func ] */
20164 if (!duk_is_callable(ctx, -1)) {
20165 /* Fall back to the initial (original) Object.toString(). We don't
20166 * currently have pointers to the built-in functions, only the top
20167 * level global objects (like "Array") so this is now done in a bit
20168 * of a hacky manner. It would be cleaner to push the (original)
20169 * function and use duk_call_method().
20170 */
20171
20172 /* XXX: 'this' will be ToObject() coerced twice, which is incorrect
20173 * but should have no visible side effects.
20174 */
20175 DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
20176 duk_set_top(ctx, 0);
20177 return duk_bi_object_prototype_to_string(ctx); /* has access to 'this' binding */
20178 }
20179
20180 /* [ ... this func ] */
20182 duk_insert(ctx, -2);
20183
20184 /* [ ... func this ] */
20185
20186 DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
20187 (duk_tval *) duk_get_tval(ctx, -2),
20188 (duk_tval *) duk_get_tval(ctx, -1)));
20189 duk_call_method(ctx, 0);
20190
20191 return 1;
20192}
20193
20194/*
20195 * concat()
20196 */
20197
20199 duk_idx_t i, n;
20200 duk_uarridx_t idx, idx_last;
20201 duk_uarridx_t j, len;
20202 duk_hobject *h;
20203
20204 /* XXX: the insert here is a bit expensive if there are a lot of items.
20205 * It could also be special cased in the outermost for loop quite easily
20206 * (as the element is dup()'d anyway).
20207 */
20208
20210 duk_insert(ctx, 0);
20211 n = duk_get_top(ctx);
20212 duk_push_array(ctx); /* -> [ ToObject(this) item1 ... itemN arr ] */
20213
20214 /* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
20215 * (which differs from the official algorithm). If no error is thrown, this
20216 * doesn't matter as the length is updated at the end. However, if an error
20217 * is thrown, the length will be unset. That shouldn't matter because the
20218 * caller won't get a reference to the intermediate value.
20219 */
20220
20221 idx = 0;
20222 idx_last = 0;
20223 for (i = 0; i < n; i++) {
20224 DUK_ASSERT_TOP(ctx, n + 1);
20225
20226 /* [ ToObject(this) item1 ... itemN arr ] */
20227
20228 duk_dup(ctx, i);
20230 if (!h) {
20231 duk_xdef_prop_index_wec(ctx, -2, idx++);
20232 idx_last = idx;
20233 continue;
20234 }
20235
20236 /* [ ToObject(this) item1 ... itemN arr item(i) ] */
20237
20238 /* XXX: an array can have length higher than 32 bits; this is not handled
20239 * correctly now.
20240 */
20241 len = (duk_uarridx_t) duk_get_length(ctx, -1);
20242 for (j = 0; j < len; j++) {
20243 if (duk_get_prop_index(ctx, -1, j)) {
20244 /* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
20245 duk_xdef_prop_index_wec(ctx, -3, idx++);
20246 idx_last = idx;
20247 } else {
20248 idx++;
20249 duk_pop(ctx);
20250#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)
20251 /* According to E5.1 Section 15.4.4.4 nonexistent trailing
20252 * elements do not affect 'length' of the result. Test262
20253 * and other engines disagree, so update idx_last here too.
20254 */
20255 idx_last = idx;
20256#else
20257 /* Strict standard behavior, ignore trailing elements for
20258 * result 'length'.
20259 */
20260#endif
20261 }
20262 }
20263 duk_pop(ctx);
20264 }
20265
20266 /* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly
20267 * in the end, but because we're operating with an internal value which
20268 * is known to be an array, this should be equivalent.
20269 */
20270 duk_push_uarridx(ctx, idx_last);
20272
20273 DUK_ASSERT_TOP(ctx, n + 1);
20274 return 1;
20275}
20276
20277/*
20278 * join(), toLocaleString()
20279 *
20280 * Note: checking valstack is necessary, but only in the per-element loop.
20281 *
20282 * Note: the trivial approach of pushing all the elements on the value stack
20283 * and then calling duk_join() fails when the array contains a large number
20284 * of elements. This problem can't be offloaded to duk_join() because the
20285 * elements to join must be handled here and have special handling. Current
20286 * approach is to do intermediate joins with very large number of elements.
20287 * There is no fancy handling; the prefix gets re-joined multiple times.
20288 */
20289
20291 duk_uint32_t len, count;
20292 duk_uint32_t idx;
20293 duk_small_int_t to_locale_string = duk_get_current_magic(ctx);
20294 duk_idx_t valstack_required;
20295
20296 /* For join(), nargs is 1. For toLocaleString(), nargs is 0 and
20297 * setting the top essentially pushes an undefined to the stack,
20298 * thus defaulting to a comma separator.
20299 */
20300 duk_set_top(ctx, 1);
20301 if (duk_is_undefined(ctx, 0)) {
20302 duk_pop(ctx);
20304 } else {
20305 duk_to_string(ctx, 0);
20306 }
20307
20308 len = duk__push_this_obj_len_u32(ctx);
20309
20310 /* [ sep ToObject(this) len ] */
20311
20312 DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
20313 (duk_tval *) duk_get_tval(ctx, 0),
20314 (duk_tval *) duk_get_tval(ctx, 1),
20315 (unsigned long) len));
20316
20317 /* The extra (+4) is tight. */
20318 valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ?
20319 DUK__ARRAY_MID_JOIN_LIMIT : len) + 4;
20320 duk_require_stack(ctx, valstack_required);
20321
20322 duk_dup(ctx, 0);
20323
20324 /* [ sep ToObject(this) len sep ] */
20325
20326 count = 0;
20327 idx = 0;
20328 for (;;) {
20329 if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */
20330 idx >= len) { /* end of loop (careful with len==0) */
20331 /* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
20332 DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
20333 (long) count, (long) idx, (long) len));
20334 duk_join(ctx, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */
20335 duk_dup(ctx, 0); /* -> [ sep ToObject(this) len str sep ] */
20336 duk_insert(ctx, -2); /* -> [ sep ToObject(this) len sep str ] */
20337 count = 1;
20338 }
20339 if (idx >= len) {
20340 /* if true, the stack already contains the final result */
20341 break;
20342 }
20343
20344 duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx);
20345 if (duk_is_null_or_undefined(ctx, -1)) {
20346 duk_pop(ctx);
20348 } else {
20349 if (to_locale_string) {
20350 duk_to_object(ctx, -1);
20352 duk_insert(ctx, -2); /* -> [ ... toLocaleString ToObject(val) ] */
20353 duk_call_method(ctx, 0);
20354 duk_to_string(ctx, -1);
20355 } else {
20357 }
20358 }
20359
20360 count++;
20361 idx++;
20362 }
20363
20364 /* [ sep ToObject(this) len sep result ] */
20365
20366 return 1;
20367}
20368
20369/*
20370 * pop(), push()
20371 */
20372
20374 duk_uint32_t len;
20375 duk_uint32_t idx;
20377 DUK_ASSERT_TOP(ctx, 0);
20378 len = duk__push_this_obj_len_u32(ctx);
20379 if (len == 0) {
20380 duk_push_int(ctx, 0);
20382 return 0;
20383 }
20384 idx = len - 1;
20385
20386 duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx);
20387 duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx);
20388 duk_push_u32(ctx, idx);
20390 return 1;
20391}
20392
20394 /* Note: 'this' is not necessarily an Array object. The push()
20395 * algorithm is supposed to work for other kinds of objects too,
20396 * so the algorithm has e.g. an explicit update for the 'length'
20397 * property which is normally "magical" in arrays.
20398 */
20399
20400 duk_uint32_t len;
20401 duk_idx_t i, n;
20402
20403 n = duk_get_top(ctx);
20404 len = duk__push_this_obj_len_u32(ctx);
20405
20406 /* [ arg1 ... argN obj length ] */
20407
20408 /* Technically Array.prototype.push() can create an Array with length
20409 * longer than 2^32-1, i.e. outside the 32-bit range. The final length
20410 * is *not* wrapped to 32 bits in the specification.
20411 *
20412 * This implementation tracks length with a uint32 because it's much
20413 * more practical.
20414 *
20415 * See: test-bi-array-push-maxlen.js.
20416 */
20417
20418 if (len + (duk_uint32_t) n < len) {
20419 DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
20420 return DUK_RET_RANGE_ERROR;
20421 }
20422
20423 for (i = 0; i < n; i++) {
20424 duk_dup(ctx, i);
20425 duk_put_prop_index(ctx, -3, len + i);
20426 }
20427 len += n;
20428
20429 duk_push_u32(ctx, len);
20432
20433 /* [ arg1 ... argN obj length new_length ] */
20434 return 1;
20435}
20436
20437/*
20438 * sort()
20439 *
20440 * Currently qsort with random pivot. This is now really, really slow,
20441 * because there is no fast path for array parts.
20442 *
20443 * Signed indices are used because qsort() leaves and degenerate cases
20444 * may use a negative offset.
20445 */
20446
20448 duk_bool_t have1, have2;
20449 duk_bool_t undef1, undef2;
20450 duk_small_int_t ret;
20451 duk_idx_t idx_obj = 1; /* fixed offsets in valstack */
20452 duk_idx_t idx_fn = 0;
20453 duk_hstring *h1, *h2;
20454
20455 /* Fast exit if indices are identical. This is valid for a non-existent property,
20456 * for an undefined value, and almost always for ToString() coerced comparison of
20457 * arbitrary values (corner cases where this is not the case include e.g. a an
20458 * object with varying ToString() coercion).
20459 *
20460 * The specification does not prohibit "caching" of values read from the array, so
20461 * assuming equality for comparing an index with itself falls into the category of
20462 * "caching".
20463 *
20464 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
20465 * have an effect on the final result. The specification does not require any
20466 * specific behavior for inconsistent compare functions, so again, this fast path
20467 * is OK.
20468 */
20469
20470 if (idx1 == idx2) {
20471 DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
20472 (long) idx1, (long) idx2));
20473 return 0;
20474 }
20475
20476 have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1);
20477 have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2);
20478
20479 DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
20480 (long) idx1, (long) idx2, (long) have1, (long) have2,
20481 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
20482
20483 if (have1) {
20484 if (have2) {
20485 ;
20486 } else {
20487 ret = -1;
20488 goto pop_ret;
20489 }
20490 } else {
20491 if (have2) {
20492 ret = 1;
20493 goto pop_ret;
20494 } else {
20495 ret = 0;
20496 goto pop_ret;
20497 }
20498 }
20499
20500 undef1 = duk_is_undefined(ctx, -2);
20501 undef2 = duk_is_undefined(ctx, -1);
20502 if (undef1) {
20503 if (undef2) {
20504 ret = 0;
20505 goto pop_ret;
20506 } else {
20507 ret = 1;
20508 goto pop_ret;
20509 }
20510 } else {
20511 if (undef2) {
20512 ret = -1;
20513 goto pop_ret;
20514 } else {
20515 ;
20516 }
20517 }
20518
20519 if (!duk_is_undefined(ctx, idx_fn)) {
20520 duk_double_t d;
20521
20522 /* no need to check callable; duk_call() will do that */
20523 duk_dup(ctx, idx_fn); /* -> [ ... x y fn ] */
20524 duk_insert(ctx, -3); /* -> [ ... fn x y ] */
20525 duk_call(ctx, 2); /* -> [ ... res ] */
20526
20527 /* The specification is a bit vague what to do if the return
20528 * value is not a number. Other implementations seem to
20529 * tolerate non-numbers but e.g. V8 won't apparently do a
20530 * ToNumber().
20531 */
20532
20533 /* XXX: best behavior for real world compatibility? */
20534
20535 d = duk_to_number(ctx, -1);
20536 if (d < 0.0) {
20537 ret = -1;
20538 } else if (d > 0.0) {
20539 ret = 1;
20540 } else {
20541 ret = 0;
20542 }
20543
20544 duk_pop(ctx);
20545 DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
20546 return ret;
20547 }
20549 /* string compare is the default (a bit oddly) */
20550
20551 h1 = duk_to_hstring(ctx, -2);
20552 h2 = duk_to_hstring(ctx, -1);
20553 DUK_ASSERT(h1 != NULL);
20554 DUK_ASSERT(h2 != NULL);
20555
20556 ret = duk_js_string_compare(h1, h2); /* retval is directly usable */
20557 goto pop_ret;
20558
20559 pop_ret:
20560 duk_pop_2(ctx);
20561 DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
20562 return ret;
20563}
20564
20566 duk_bool_t have_l, have_r;
20567 duk_idx_t idx_obj = 1; /* fixed offset in valstack */
20568
20569 if (l == r) {
20570 return;
20571 }
20572
20573 /* swap elements; deal with non-existent elements correctly */
20574 have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20575 have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20576
20577 if (have_r) {
20578 /* right exists, [[Put]] regardless whether or not left exists */
20579 duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20580 } else {
20581 duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20582 duk_pop(ctx);
20583 }
20584
20585 if (have_l) {
20586 duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20587 } else {
20588 duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20589 duk_pop(ctx);
20590 }
20591}
20592
20593#if defined(DUK_USE_DDDPRINT)
20594/* Debug print which visualizes the qsort partitioning process. */
20595DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
20596 char buf[4096];
20597 char *ptr = buf;
20598 duk_int_t i, n;
20599 n = (duk_int_t) duk_get_length(ctx, 1);
20600 if (n > 4000) {
20601 n = 4000;
20602 }
20603 *ptr++ = '[';
20604 for (i = 0; i < n; i++) {
20605 if (i == pivot) {
20606 *ptr++ = '|';
20607 } else if (i == lo) {
20608 *ptr++ = '<';
20609 } else if (i == hi) {
20610 *ptr++ = '>';
20611 } else if (i >= lo && i <= hi) {
20612 *ptr++ = '-';
20613 } else {
20614 *ptr++ = ' ';
20615 }
20616 }
20617 *ptr++ = ']';
20618 *ptr++ = '\0';
20619
20620 DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)",
20621 (const char *) buf, (long) lo, (long) hi, (long) pivot));
20622}
20623#endif
20624
20626 duk_hthread *thr = (duk_hthread *) ctx;
20627 duk_int_t p, l, r;
20628
20629 /* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
20630
20631 DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
20632 (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1)));
20633
20634 DUK_ASSERT_TOP(ctx, 3);
20635
20636 /* In some cases it may be that lo > hi, or hi < 0; these
20637 * degenerate cases happen e.g. for empty arrays, and in
20638 * recursion leaves.
20639 */
20640
20641 /* trivial cases */
20642 if (hi - lo < 1) {
20643 DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
20644 return;
20645 }
20646 DUK_ASSERT(hi > lo);
20647 DUK_ASSERT(hi - lo + 1 >= 2);
20648
20649 /* randomized pivot selection */
20650 p = lo + (duk_util_tinyrandom_get_bits(thr, 30) % (hi - lo + 1)); /* rnd in [lo,hi] */
20651 DUK_ASSERT(p >= lo && p <= hi);
20652 DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld",
20653 (long) lo, (long) hi, (long) p));
20654
20655 /* move pivot out of the way */
20656 duk__array_sort_swap(ctx, p, lo);
20657 p = lo;
20658 DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20659
20660 l = lo + 1;
20661 r = hi;
20662 for (;;) {
20663 /* find elements to swap */
20664 for (;;) {
20665 DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
20666 (long) l, (long) r, (long) p));
20667 if (l >= hi) {
20668 break;
20669 }
20670 if (duk__array_sort_compare(ctx, l, p) >= 0) { /* !(l < p) */
20671 break;
20672 }
20673 l++;
20674 }
20675 for (;;) {
20676 DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
20677 (long) l, (long) r, (long) p));
20678 if (r <= lo) {
20679 break;
20680 }
20681 if (duk__array_sort_compare(ctx, p, r) >= 0) { /* !(p < r) */
20682 break;
20683 }
20684 r--;
20685 }
20686 if (l >= r) {
20687 goto done;
20688 }
20689 DUK_ASSERT(l < r);
20690
20691 DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
20692
20693 duk__array_sort_swap(ctx, l, r);
20694
20695 DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20696 l++;
20697 r--;
20698 }
20699 done:
20700 /* Note that 'l' and 'r' may cross, i.e. r < l */
20701 DUK_ASSERT(l >= lo && l <= hi);
20702 DUK_ASSERT(r >= lo && r <= hi);
20703
20704 /* XXX: there's no explicit recursion bound here now. For the average
20705 * qsort recursion depth O(log n) that's not really necessary: e.g. for
20706 * 2**32 recursion depth would be about 32 which is OK. However, qsort
20707 * worst case recursion depth is O(n) which may be a problem.
20708 */
20709
20710 /* move pivot to its final place */
20711 DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20712 duk__array_sort_swap(ctx, lo, r);
20713
20714#if defined(DUK_USE_DDDPRINT)
20715 duk__debuglog_qsort_state(ctx, lo, hi, r);
20716#endif
20717
20718 DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1)));
20719 duk__array_qsort(ctx, lo, r - 1);
20720 duk__array_qsort(ctx, r + 1, hi);
20721}
20722
20724 duk_uint32_t len;
20725
20726 /* XXX: len >= 0x80000000 won't work below because a signed type
20727 * is needed by qsort.
20728 */
20730
20731 /* stack[0] = compareFn
20732 * stack[1] = ToObject(this)
20733 * stack[2] = ToUint32(length)
20734 */
20735
20736 if (len > 0) {
20737 /* avoid degenerate cases, so that (len - 1) won't underflow */
20738 duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1));
20739 }
20740
20741 DUK_ASSERT_TOP(ctx, 3);
20743 return 1; /* return ToObject(this) */
20744}
20745
20746/*
20747 * splice()
20748 */
20749
20750/* XXX: this compiles to over 500 bytes now, even without special handling
20751 * for an array part. Uses signed ints so does not handle full array range correctly.
20752 */
20753
20754/* XXX: can shift() / unshift() use the same helper?
20755 * shift() is (close to?) <--> splice(0, 1)
20756 * unshift is (close to?) <--> splice(0, 0, [items])?
20757 */
20758
20760 duk_idx_t nargs;
20761 duk_uint32_t len;
20762 duk_bool_t have_delcount;
20763 duk_int_t item_count;
20764 duk_int_t act_start;
20765 duk_int_t del_count;
20766 duk_int_t i, n;
20767
20768 DUK_UNREF(have_delcount);
20769
20770 nargs = duk_get_top(ctx);
20771 if (nargs < 2) {
20772 duk_set_top(ctx, 2);
20773 nargs = 2;
20774 have_delcount = 0;
20775 } else {
20776 have_delcount = 1;
20777 }
20778
20779 /* XXX: len >= 0x80000000 won't work below because we need to be
20780 * able to represent -len.
20781 */
20783
20784 act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
20785 if (act_start < 0) {
20786 act_start = len + act_start;
20787 }
20788 DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len);
20789
20790#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
20791 if (have_delcount) {
20792#endif
20793 del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start);
20794#ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
20795 } else {
20796 /* E5.1 standard behavior when deleteCount is not given would be
20797 * to treat it just like if 'undefined' was given, which coerces
20798 * ultimately to 0. Real world behavior is to splice to the end
20799 * of array, see test-bi-array-proto-splice-no-delcount.js.
20800 */
20801 del_count = len - act_start;
20802 }
20803#endif
20804
20805 DUK_ASSERT(nargs >= 2);
20806 item_count = (duk_int_t) (nargs - 2);
20807
20808 DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start);
20809 DUK_ASSERT(del_count + act_start <= (duk_int_t) len);
20810
20811 /* For now, restrict result array into 32-bit length range. */
20812 if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
20813 DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
20814 return DUK_RET_RANGE_ERROR;
20815 }
20816
20817 duk_push_array(ctx);
20818
20819 /* stack[0] = start
20820 * stack[1] = deleteCount
20821 * stack[2...nargs-1] = items
20822 * stack[nargs] = ToObject(this) -3
20823 * stack[nargs+1] = ToUint32(length) -2
20824 * stack[nargs+2] = result array -1
20825 */
20826
20827 DUK_ASSERT_TOP(ctx, nargs + 3);
20828
20829 /* Step 9: copy elements-to-be-deleted into the result array */
20830
20831 for (i = 0; i < del_count; i++) {
20832 if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) {
20833 duk_xdef_prop_index_wec(ctx, -2, i); /* throw flag irrelevant (false in std alg) */
20834 } else {
20835 duk_pop(ctx);
20836 }
20837 }
20838 duk_push_u32(ctx, (duk_uint32_t) del_count);
20840
20841 /* Steps 12 and 13: reorganize elements to make room for itemCount elements */
20842
20843 if (item_count < del_count) {
20844 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 1
20845 * -> [ A B F G H ] (conceptual intermediate step)
20846 * -> [ A B . F G H ] (placeholder marked)
20847 * [ A B C F G H ] (actual result at this point, C will be replaced)
20848 */
20849
20850 DUK_ASSERT_TOP(ctx, nargs + 3);
20851
20852 n = len - del_count;
20853 for (i = act_start; i < n; i++) {
20854 if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
20855 duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
20856 } else {
20857 duk_pop(ctx);
20858 duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
20859 }
20860 }
20861
20862 DUK_ASSERT_TOP(ctx, nargs + 3);
20863
20864 /* loop iterator init and limit changed from standard algorithm */
20865 n = len - del_count + item_count;
20866 for (i = len - 1; i >= n; i--) {
20867 duk_del_prop_index(ctx, -3, (duk_uarridx_t) i);
20868 }
20869
20870 DUK_ASSERT_TOP(ctx, nargs + 3);
20871 } else if (item_count > del_count) {
20872 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 4
20873 * -> [ A B F G H ] (conceptual intermediate step)
20874 * -> [ A B . . . . F G H ] (placeholder marked)
20875 * [ A B C D E F F G H ] (actual result at this point)
20876 */
20877
20878 DUK_ASSERT_TOP(ctx, nargs + 3);
20879
20880 /* loop iterator init and limit changed from standard algorithm */
20881 for (i = len - del_count - 1; i >= act_start; i--) {
20882 if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
20883 duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
20884 } else {
20885 duk_pop(ctx);
20886 duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
20887 }
20888 }
20889
20890 DUK_ASSERT_TOP(ctx, nargs + 3);
20891 } else {
20892 /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 3
20893 * -> [ A B F G H ] (conceptual intermediate step)
20894 * -> [ A B . . . F G H ] (placeholder marked)
20895 * [ A B C D E F G H ] (actual result at this point)
20896 */
20897 }
20898 DUK_ASSERT_TOP(ctx, nargs + 3);
20899
20900 /* Step 15: insert itemCount elements into the hole made above */
20901
20902 for (i = 0; i < item_count; i++) {
20903 duk_dup(ctx, i + 2); /* args start at index 2 */
20904 duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i));
20905 }
20907 /* Step 16: update length; note that the final length may be above 32 bit range
20908 * (but we checked above that this isn't the case here)
20909 */
20910
20911 duk_push_u32(ctx, len - del_count + item_count);
20913
20914 /* result array is already at the top of stack */
20915 DUK_ASSERT_TOP(ctx, nargs + 3);
20916 return 1;
20917}
20918
20919/*
20920 * reverse()
20921 */
20922
20924 duk_uint32_t len;
20925 duk_uint32_t middle;
20926 duk_uint32_t lower, upper;
20927 duk_bool_t have_lower, have_upper;
20928
20929 len = duk__push_this_obj_len_u32(ctx);
20930 middle = len / 2;
20931
20932 /* If len <= 1, middle will be 0 and for-loop bails out
20933 * immediately (0 < 0 -> false).
20934 */
20935
20936 for (lower = 0; lower < middle; lower++) {
20937 DUK_ASSERT(len >= 2);
20938 DUK_ASSERT_TOP(ctx, 2);
20939
20940 DUK_ASSERT(len >= lower + 1);
20941 upper = len - lower - 1;
20942
20943 have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower);
20944 have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper);
20945
20946 /* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
20947
20948 if (have_upper) {
20949 duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower);
20950 } else {
20951 duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower);
20952 duk_pop(ctx);
20953 }
20954
20955 if (have_lower) {
20956 duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper);
20957 } else {
20958 duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper);
20959 duk_pop(ctx);
20960 }
20961
20962 DUK_ASSERT_TOP(ctx, 2);
20963 }
20964
20965 DUK_ASSERT_TOP(ctx, 2);
20966 duk_pop(ctx); /* -> [ ToObject(this) ] */
20967 return 1;
20968}
20969
20970/*
20971 * slice()
20972 */
20973
20975 duk_uint32_t len;
20976 duk_int_t start, end;
20977 duk_int_t i;
20978 duk_uarridx_t idx;
20979 duk_uint32_t res_length = 0;
20980
20981 /* XXX: len >= 0x80000000 won't work below because we need to be
20982 * able to represent -len.
20983 */
20985 duk_push_array(ctx);
20986
20987 /* stack[0] = start
20988 * stack[1] = end
20989 * stack[2] = ToObject(this)
20990 * stack[3] = ToUint32(length)
20991 * stack[4] = result array
20992 */
20993
20994 start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
20995 if (start < 0) {
20996 start = len + start;
20997 }
20998 /* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
20999 * (the upper limit)?
21000 */
21001 if (duk_is_undefined(ctx, 1)) {
21002 end = len;
21003 } else {
21004 end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len);
21005 if (end < 0) {
21006 end = len + end;
21007 }
21008 }
21009 DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len);
21010 DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len);
21011
21012 idx = 0;
21013 for (i = start; i < end; i++) {
21014 DUK_ASSERT_TOP(ctx, 5);
21015 if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21016 duk_xdef_prop_index_wec(ctx, 4, idx);
21017 res_length = idx + 1;
21018 } else {
21020 }
21021 idx++;
21022 DUK_ASSERT_TOP(ctx, 5);
21023 }
21024
21025 duk_push_u32(ctx, res_length);
21027
21028 DUK_ASSERT_TOP(ctx, 5);
21029 return 1;
21030}
21031
21032/*
21033 * shift()
21034 */
21035
21037 duk_uint32_t len;
21038 duk_uint32_t i;
21039
21040 len = duk__push_this_obj_len_u32(ctx);
21041 if (len == 0) {
21042 duk_push_int(ctx, 0);
21044 return 0;
21045 }
21046
21047 duk_get_prop_index(ctx, 0, 0);
21048
21049 /* stack[0] = object (this)
21050 * stack[1] = ToUint32(length)
21051 * stack[2] = elem at index 0 (retval)
21052 */
21053
21054 for (i = 1; i < len; i++) {
21055 DUK_ASSERT_TOP(ctx, 3);
21056 if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) {
21057 /* fromPresent = true */
21058 duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
21059 } else {
21060 /* fromPresent = false */
21062 duk_pop(ctx);
21063 }
21064 }
21065 duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1));
21066
21067 duk_push_u32(ctx, (duk_uint32_t) (len - 1));
21069
21070 DUK_ASSERT_TOP(ctx, 3);
21071 return 1;
21072}
21073
21074/*
21075 * unshift()
21076 */
21077
21079 duk_idx_t nargs;
21080 duk_uint32_t len;
21081 duk_uint32_t i;
21082
21083 nargs = duk_get_top(ctx);
21084 len = duk__push_this_obj_len_u32(ctx);
21085
21086 /* stack[0...nargs-1] = unshift args (vararg)
21087 * stack[nargs] = ToObject(this)
21088 * stack[nargs+1] = ToUint32(length)
21089 */
21090
21091 DUK_ASSERT_TOP(ctx, nargs + 2);
21092
21093 /* Note: unshift() may operate on indices above unsigned 32-bit range
21094 * and the final length may be >= 2**32. However, we restrict the
21095 * final result to 32-bit range for practicality.
21096 */
21097
21098 if (len + (duk_uint32_t) nargs < len) {
21099 DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
21100 return DUK_RET_RANGE_ERROR;
21101 }
21102
21103 i = len;
21104 while (i > 0) {
21105 DUK_ASSERT_TOP(ctx, nargs + 2);
21106 i--;
21107 /* k+argCount-1; note that may be above 32-bit range */
21108
21109 if (duk_get_prop_index(ctx, -2, (duk_uarridx_t) i)) {
21110 /* fromPresent = true */
21111 /* [ ... ToObject(this) ToUint32(length) val ] */
21112 duk_put_prop_index(ctx, -3, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
21113 } else {
21114 /* fromPresent = false */
21115 /* [ ... ToObject(this) ToUint32(length) val ] */
21116 duk_pop(ctx);
21117 duk_del_prop_index(ctx, -2, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
21118 }
21119 DUK_ASSERT_TOP(ctx, nargs + 2);
21120 }
21121
21122 for (i = 0; i < (duk_uint32_t) nargs; i++) {
21123 DUK_ASSERT_TOP(ctx, nargs + 2);
21124 duk_dup(ctx, i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
21125 duk_put_prop_index(ctx, -3, (duk_uarridx_t) i);
21126 DUK_ASSERT_TOP(ctx, nargs + 2);
21127 }
21128
21129 DUK_ASSERT_TOP(ctx, nargs + 2);
21130 duk_push_u32(ctx, len + nargs);
21131 duk_dup_top(ctx); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
21133 return 1;
21134}
21135
21136/*
21137 * indexOf(), lastIndexOf()
21138 */
21139
21141 duk_idx_t nargs;
21142 duk_int_t i, len;
21143 duk_int_t from_index;
21144 duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for indexOf, -1 for lastIndexOf */
21145
21146 /* lastIndexOf() needs to be a vararg function because we must distinguish
21147 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
21148 * made vararg for symmetry although it doesn't strictly need to be.
21149 */
21150
21151 nargs = duk_get_top(ctx);
21152 duk_set_top(ctx, 2);
21153
21154 /* XXX: must be able to represent -len */
21156 if (len == 0) {
21157 goto not_found;
21158 }
21159
21160 /* Index clamping is a bit tricky, we must ensure that we'll only iterate
21161 * through elements that exist and that the specific requirements from E5.1
21162 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
21163 *
21164 * - indexOf: clamp to [-len,len], negative handling -> [0,len],
21165 * if clamped result is len, for-loop bails out immediately
21166 *
21167 * - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
21168 * if clamped result is -1, for-loop bails out immediately
21169 *
21170 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
21171 * for indexOf() but incorrect for lastIndexOf(). Hence special handling,
21172 * and why lastIndexOf() needs to be a vararg function.
21173 */
21174
21175 if (nargs >= 2) {
21176 /* indexOf: clamp fromIndex to [-len, len]
21177 * (if fromIndex == len, for-loop terminates directly)
21178 *
21179 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
21180 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
21181 */
21182 from_index = duk_to_int_clamped(ctx,
21183 1,
21184 (idx_step > 0 ? -len : -len - 1),
21185 (idx_step > 0 ? len : len - 1));
21186 if (from_index < 0) {
21187 /* for lastIndexOf, result may be -1 (mark immediate termination) */
21188 from_index = len + from_index;
21189 }
21190 } else {
21191 /* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
21192 * handle both indexOf and lastIndexOf specially here.
21193 */
21194 if (idx_step > 0) {
21195 from_index = 0;
21196 } else {
21197 from_index = len - 1;
21198 }
21199 }
21200
21201 /* stack[0] = searchElement
21202 * stack[1] = fromIndex
21203 * stack[2] = object
21204 * stack[3] = length (not needed, but not popped above)
21205 */
21206
21207 for (i = from_index; i >= 0 && i < len; i += idx_step) {
21208 DUK_ASSERT_TOP(ctx, 4);
21209
21210 if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21211 DUK_ASSERT_TOP(ctx, 5);
21212 if (duk_strict_equals(ctx, 0, 4)) {
21214 return 1;
21218 duk_pop(ctx);
21219 }
21220
21221 not_found:
21222 duk_push_int(ctx, -1);
21223 return 1;
21225
21226/*
21227 * every(), some(), forEach(), map(), filter()
21228 */
21229
21230#define DUK__ITER_EVERY 0
21231#define DUK__ITER_SOME 1
21232#define DUK__ITER_FOREACH 2
21233#define DUK__ITER_MAP 3
21234#define DUK__ITER_FILTER 4
21235
21236/* XXX: This helper is a bit awkward because the handling for the different iteration
21237 * callers is quite different. This now compiles to a bit less than 500 bytes, so with
21238 * 5 callers the net result is about 100 bytes / caller.
21239 */
21240
21242 duk_uint32_t len;
21243 duk_uint32_t i;
21244 duk_uarridx_t k;
21245 duk_bool_t bval;
21246 duk_small_int_t iter_type = duk_get_current_magic(ctx);
21247 duk_uint32_t res_length = 0;
21248
21249 /* each call this helper serves has nargs==2 */
21250 DUK_ASSERT_TOP(ctx, 2);
21251
21252 len = duk__push_this_obj_len_u32(ctx);
21253 duk_require_callable(ctx, 0);
21254 /* if thisArg not supplied, behave as if undefined was supplied */
21255
21256 if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
21257 duk_push_array(ctx);
21258 } else {
21259 duk_push_undefined(ctx);
21260 }
21261
21262 /* stack[0] = callback
21263 * stack[1] = thisArg
21264 * stack[2] = object
21265 * stack[3] = ToUint32(length) (unused, but avoid unnecessary pop)
21266 * stack[4] = result array (or undefined)
21267 */
21268
21269 k = 0; /* result index for filter() */
21270 for (i = 0; i < len; i++) {
21271 DUK_ASSERT_TOP(ctx, 5);
21272
21273 if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21274#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER)
21275 /* Real world behavior for map(): trailing non-existent
21276 * elements don't invoke the user callback, but are still
21277 * counted towards result 'length'.
21278 */
21279 if (iter_type == DUK__ITER_MAP) {
21280 res_length = i + 1;
21281 }
21282#else
21283 /* Standard behavior for map(): trailing non-existent
21284 * elements don't invoke the user callback and are not
21285 * counted towards result 'length'.
21286 */
21287#endif
21288 duk_pop(ctx);
21289 continue;
21290 }
21291
21292 /* The original value needs to be preserved for filter(), hence
21293 * this funny order. We can't re-get the value because of side
21294 * effects.
21295 */
21296
21297 duk_dup(ctx, 0);
21298 duk_dup(ctx, 1);
21299 duk_dup(ctx, -3);
21300 duk_push_u32(ctx, i);
21301 duk_dup(ctx, 2); /* [ ... val callback thisArg val i obj ] */
21302 duk_call_method(ctx, 3); /* -> [ ... val retval ] */
21303
21304 switch (iter_type) {
21305 case DUK__ITER_EVERY:
21306 bval = duk_to_boolean(ctx, -1);
21307 if (!bval) {
21308 /* stack top contains 'false' */
21309 return 1;
21310 }
21311 break;
21312 case DUK__ITER_SOME:
21313 bval = duk_to_boolean(ctx, -1);
21314 if (bval) {
21315 /* stack top contains 'true' */
21316 return 1;
21317 }
21318 break;
21319 case DUK__ITER_FOREACH:
21320 /* nop */
21321 break;
21322 case DUK__ITER_MAP:
21323 duk_dup(ctx, -1);
21324 duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) i); /* retval to result[i] */
21325 res_length = i + 1;
21326 break;
21327 case DUK__ITER_FILTER:
21328 bval = duk_to_boolean(ctx, -1);
21329 if (bval) {
21330 duk_dup(ctx, -2); /* orig value */
21332 k++;
21333 res_length = k;
21334 }
21335 break;
21336 default:
21338 break;
21339 }
21340 duk_pop_2(ctx);
21341
21342 DUK_ASSERT_TOP(ctx, 5);
21343 }
21344
21345 switch (iter_type) {
21346 case DUK__ITER_EVERY:
21347 duk_push_true(ctx);
21348 break;
21349 case DUK__ITER_SOME:
21350 duk_push_false(ctx);
21351 break;
21352 case DUK__ITER_FOREACH:
21353 duk_push_undefined(ctx);
21354 break;
21355 case DUK__ITER_MAP:
21356 case DUK__ITER_FILTER:
21358 DUK_ASSERT(duk_is_array(ctx, -1)); /* topmost element is the result array already */
21359 duk_push_u32(ctx, res_length);
21361 break;
21362 default:
21364 break;
21365 }
21366
21367 return 1;
21368}
21369
21370/*
21371 * reduce(), reduceRight()
21372 */
21373
21375 duk_idx_t nargs;
21376 duk_bool_t have_acc;
21377 duk_uint32_t i, len;
21378 duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for reduce, -1 for reduceRight */
21379
21380 /* We're a varargs function because we need to detect whether
21381 * initialValue was given or not.
21382 */
21383 nargs = duk_get_top(ctx);
21384 DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
21385
21386 duk_set_top(ctx, 2);
21387 len = duk__push_this_obj_len_u32(ctx);
21388 if (!duk_is_callable(ctx, 0)) {
21389 goto type_error;
21390 }
21391
21392 /* stack[0] = callback fn
21393 * stack[1] = initialValue
21394 * stack[2] = object (coerced this)
21395 * stack[3] = length (not needed, but not popped above)
21396 * stack[4] = accumulator
21397 */
21398
21399 have_acc = 0;
21400 if (nargs >= 2) {
21401 duk_dup(ctx, 1);
21402 have_acc = 1;
21403 }
21404 DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
21405 (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3)));
21406
21407 /* For len == 0, i is initialized to len - 1 which underflows.
21408 * The condition (i < len) will then exit the for-loop on the
21409 * first round which is correct. Similarly, loop termination
21410 * happens by i underflowing.
21411 */
21412
21413 for (i = (idx_step >= 0 ? 0 : len - 1);
21414 i < len; /* i >= 0 would always be true */
21415 i += idx_step) {
21416 DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
21417 (long) i, (long) len, (long) have_acc,
21418 (long) duk_get_top(ctx),
21419 (duk_tval *) duk_get_tval(ctx, 4)));
21420
21421 DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) ||
21422 (!have_acc && duk_get_top(ctx) == 4));
21423
21424 if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21425 continue;
21426 }
21427
21428 if (!have_acc) {
21429 DUK_ASSERT_TOP(ctx, 4);
21430 duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
21431 have_acc = 1;
21432 DUK_ASSERT_TOP(ctx, 5);
21433 } else {
21434 DUK_ASSERT_TOP(ctx, 5);
21435 duk_dup(ctx, 0);
21436 duk_dup(ctx, 4);
21437 duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
21438 duk_push_u32(ctx, i);
21439 duk_dup(ctx, 2);
21440 DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
21441 (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4),
21442 (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
21443 (duk_tval *) duk_get_tval(ctx, -1)));
21444 duk_call(ctx, 4);
21445 DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
21446 duk_replace(ctx, 4);
21447 DUK_ASSERT_TOP(ctx, 5);
21448 }
21449 }
21450
21451 if (!have_acc) {
21452 goto type_error;
21453 }
21454
21455 DUK_ASSERT_TOP(ctx, 5);
21456 return 1;
21457
21458 type_error:
21459 return DUK_RET_TYPE_ERROR;
21460}
21461
21462#undef DUK__ARRAY_MID_JOIN_LIMIT
21463
21464#undef DUK__ITER_EVERY
21465#undef DUK__ITER_SOME
21466#undef DUK__ITER_FOREACH
21467#undef DUK__ITER_MAP
21468#undef DUK__ITER_FILTER
21469#line 1 "duk_bi_boolean.c"
21470/*
21471 * Boolean built-ins
21472 */
21473
21474/* include removed: duk_internal.h */
21475
21476/* Shared helper to provide toString() and valueOf(). Checks 'this', gets
21477 * the primitive value to stack top, and optionally coerces with ToString().
21478 */
21480 duk_tval *tv;
21481 duk_hobject *h;
21482 duk_small_int_t coerce_tostring = duk_get_current_magic(ctx);
21483
21484 /* XXX: there is room to use a shared helper here, many built-ins
21485 * check the 'this' type, and if it's an object, check its class,
21486 * then get its internal value, etc.
21487 */
21488
21489 duk_push_this(ctx);
21490 tv = duk_get_tval(ctx, -1);
21491 DUK_ASSERT(tv != NULL);
21492
21493 if (DUK_TVAL_IS_BOOLEAN(tv)) {
21494 goto type_ok;
21495 } else if (DUK_TVAL_IS_OBJECT(tv)) {
21496 h = DUK_TVAL_GET_OBJECT(tv);
21497 DUK_ASSERT(h != NULL);
21501 DUK_ASSERT(duk_is_boolean(ctx, -1));
21502 goto type_ok;
21503 }
21504 }
21505
21506 return DUK_RET_TYPE_ERROR;
21507
21508 type_ok:
21509 if (coerce_tostring) {
21510 duk_to_string(ctx, -1);
21511 }
21512 return 1;
21513}
21514
21516 duk_hthread *thr = (duk_hthread *) ctx;
21517 duk_hobject *h_this;
21518
21519 DUK_UNREF(thr);
21520
21521 duk_to_boolean(ctx, 0);
21522
21523 if (duk_is_constructor_call(ctx)) {
21524 /* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
21525 duk_push_this(ctx);
21526 h_this = duk_get_hobject(ctx, -1);
21527 DUK_ASSERT(h_this != NULL);
21529
21531
21532 duk_dup(ctx, 0); /* -> [ val obj val ] */
21533 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); /* XXX: proper flags? */
21534 } /* unbalanced stack */
21535
21536 return 1;
21537}
21538#line 1 "duk_bi_buffer.c"
21539/*
21540 * Duktape.Buffer, Node.js Buffer, and Khronos/ES6 TypedArray built-ins
21541 */
21542
21543/* include removed: duk_internal.h */
21544
21545/*
21546 * Misc helpers
21547 */
21548
21549#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21550/* Map DUK_HBUFFEROBJECT_ELEM_xxx to duk_hobject class number.
21551 * Sync with duk_hbufferobject.h and duk_hobject.h.
21552 */
21564#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21565
21566#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21567/* Map DUK_HBUFFEROBJECT_ELEM_xxx to prototype object built-in index.
21568 * Sync with duk_hbufferobject.h.
21580};
21581#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21582
21583#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21584/* Map DUK__FLX_xxx to byte size.
21585 */
21586static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
21587 1, /* DUK__FLD_8BIT */
21588 2, /* DUK__FLD_16BIT */
21589 4, /* DUK__FLD_32BIT */
21590 4, /* DUK__FLD_FLOAT */
21591 8, /* DUK__FLD_DOUBLE */
21592 0 /* DUK__FLD_VARINT; not relevant here */
21593};
21594#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21595
21596#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21597/* Bitfield for each DUK_HBUFFEROBJECT_ELEM_xxx indicating which element types
21598 * are compatible with a blind byte copy for the TypedArray set() method (also
21599 * used for TypedArray constructor). Array index is target buffer elem type,
21600 * bitfield indicates compatible source types. The types must have same byte
21601 * size and they must be coercion compatible.
21602 */
21603static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
21604 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8 */
21608
21609 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED
21610 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
21611 */
21614
21615 /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT8 */
21619
21620 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT16 */
21623
21624 /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT16 */
21627
21628 /* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT32 */
21631
21632 /* xxx -> DUK_HBUFFEROBJECT_ELEM_INT32 */
21635
21636 /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT32 */
21638
21639 /* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT64 */
21641};
21642#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21643
21644#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21645/* Shared helper. */
21647 duk_hthread *thr;
21648 duk_tval *tv;
21649 duk_hbufferobject *h_this;
21650
21651 DUK_ASSERT(ctx != NULL);
21652 thr = (duk_hthread *) ctx;
21653
21655 DUK_ASSERT(tv != NULL);
21656 if (DUK_TVAL_IS_OBJECT(tv)) {
21658 DUK_ASSERT(h_this != NULL);
21659 if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_this)) {
21661 return h_this;
21662 }
21663 }
21664
21665 if (throw_flag) {
21667 }
21668 return NULL;
21669}
21670#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21671
21672#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21673/* Check that 'this' is a duk_hbufferobject and return a pointer to it. */
21675 return duk__getrequire_bufobj_this(ctx, 0);
21676}
21677#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21678
21679#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21680/* Check that 'this' is a duk_hbufferobject and return a pointer to it
21681 * (NULL if not).
21682 */
21684 return duk__getrequire_bufobj_this(ctx, 1);
21685}
21686#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21687
21688#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21689/* Check that value is a duk_hbufferobject and return a pointer to it. */
21691 duk_hthread *thr;
21692 duk_tval *tv;
21693 duk_hbufferobject *h_obj;
21694
21695 thr = (duk_hthread *) ctx;
21696
21697 /* Don't accept relative indices now. */
21698 DUK_ASSERT(index >= 0);
21700 tv = duk_require_tval(ctx, index);
21701 DUK_ASSERT(tv != NULL);
21702 if (DUK_TVAL_IS_OBJECT(tv)) {
21703 h_obj = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv);
21704 DUK_ASSERT(h_obj != NULL);
21707 return h_obj;
21708 }
21709 }
21710
21712 return NULL; /* not reachable */
21713}
21714#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21715
21717 duk_hthread *thr;
21718
21719 thr = (duk_hthread *) ctx;
21720 DUK_UNREF(thr);
21722 DUK_ASSERT(ctx != NULL);
21723 DUK_ASSERT(h_bufobj != NULL);
21724 DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */
21725 DUK_ASSERT(h_val != NULL);
21727
21728 h_bufobj->buf = h_val;
21729 DUK_HBUFFER_INCREF(thr, h_val);
21730 h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
21731 DUK_ASSERT(h_bufobj->shift == 0);
21733
21735}
21736
21737#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21739 duk_hbuffer *h_val;
21740 duk_hbufferobject *h_bufobj;
21741
21742 (void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
21743 h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
21744 DUK_ASSERT(h_val != NULL);
21746 h_bufobj = duk_push_bufferobject_raw(ctx,
21751 DUK_ASSERT(h_bufobj != NULL);
21752
21753 duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
21755
21756 return h_bufobj;
21757}
21758#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21759
21760#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21761/* Shared offset/length coercion helper. */
21763 duk_hbufferobject *h_bufarg,
21764 duk_idx_t idx_offset,
21765 duk_idx_t idx_length,
21766 duk_uint_t *out_offset,
21767 duk_uint_t *out_length,
21768 duk_bool_t throw_flag) {
21769 duk_hthread *thr;
21770 duk_int_t offset_signed;
21771 duk_int_t length_signed;
21772 duk_uint_t offset;
21773 duk_uint_t length;
21774
21775 thr = (duk_hthread *) ctx;
21776 DUK_UNREF(thr);
21777
21778 offset_signed = duk_to_int(ctx, idx_offset);
21779 if (offset_signed < 0) {
21780 goto fail_range;
21781 }
21782 offset = (duk_uint_t) offset_signed;
21783 if (offset > h_bufarg->length) {
21784 goto fail_range;
21785 }
21786 DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */
21787 DUK_ASSERT(offset <= h_bufarg->length);
21788
21789 if (duk_is_undefined(ctx, idx_length)) {
21790 DUK_ASSERT(h_bufarg->length >= offset);
21791 length = h_bufarg->length - offset; /* >= 0 */
21792 } else {
21793 length_signed = duk_to_int(ctx, idx_length);
21794 if (length_signed < 0) {
21795 goto fail_range;
21796 }
21797 length = (duk_uint_t) length_signed;
21798 DUK_ASSERT(h_bufarg->length >= offset);
21799 if (length > h_bufarg->length - offset) {
21800 /* Unlike for negative arguments, some call sites
21801 * want length to be clamped if it's positive.
21802 */
21803 if (throw_flag) {
21804 goto fail_range;
21805 } else {
21806 length = h_bufarg->length - offset;
21807 }
21808 }
21810 DUK_ASSERT_DISABLE(length >= 0); /* unsigned */
21811 DUK_ASSERT(offset + length <= h_bufarg->length);
21812
21813 *out_offset = offset;
21814 *out_length = length;
21815 return;
21816
21817 fail_range:
21819}
21820#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21821
21822#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21823/* Shared lenient buffer length clamping helper. No negative indices, no
21824 * element/byte shifting.
21825 */
21827 duk_hbufferobject *h_bufobj,
21828 duk_idx_t idx_start,
21829 duk_idx_t idx_end,
21830 duk_int_t *out_start_offset,
21831 duk_int_t *out_end_offset) {
21832 duk_int_t buffer_length;
21833 duk_int_t start_offset;
21834 duk_int_t end_offset;
21835
21836 DUK_ASSERT(out_start_offset != NULL);
21837 DUK_ASSERT(out_end_offset != NULL);
21838
21839 buffer_length = (duk_int_t) h_bufobj->length;
21840
21841 /* undefined coerces to zero which is correct */
21842 start_offset = duk_to_int_clamped(ctx, idx_start, 0, buffer_length);
21843 if (duk_is_undefined(ctx, idx_end)) {
21844 end_offset = buffer_length;
21845 } else {
21846 end_offset = duk_to_int_clamped(ctx, idx_end, start_offset, buffer_length);
21847 }
21848
21849 DUK_ASSERT(start_offset >= 0);
21850 DUK_ASSERT(start_offset <= buffer_length);
21851 DUK_ASSERT(end_offset >= 0);
21852 DUK_ASSERT(end_offset <= buffer_length);
21853 DUK_ASSERT(start_offset <= end_offset);
21854
21855 *out_start_offset = start_offset;
21856 *out_end_offset = end_offset;
21857}
21858#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21859
21860#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21861/* Shared lenient buffer length clamping helper. Indices are treated as
21862 * element indices (though output values are byte offsets) which only
21863 * really matters for TypedArray views as other buffer object have a zero
21864 * shift. Negative indices are counted from end of input slice; crossed
21865 * indices are clamped to zero length; and final indices are clamped
21866 * against input slice. Used for e.g. ArrayBuffer slice().
21867 */
21869 duk_hbufferobject *h_bufobj,
21870 duk_idx_t idx_start,
21871 duk_idx_t idx_end,
21872 duk_int_t *out_start_offset,
21873 duk_int_t *out_end_offset) {
21874 duk_int_t buffer_length;
21875 duk_int_t start_offset;
21876 duk_int_t end_offset;
21877
21878 DUK_ASSERT(out_start_offset != NULL);
21879 DUK_ASSERT(out_end_offset != NULL);
21880
21881 buffer_length = (duk_int_t) h_bufobj->length;
21882 buffer_length >>= h_bufobj->shift; /* as elements */
21883
21884 /* Resolve start/end offset as element indices first; arguments
21885 * at idx_start/idx_end are element offsets. Working with element
21886 * indices first also avoids potential for wrapping.
21887 */
21888
21889 start_offset = duk_to_int(ctx, idx_start);
21890 if (start_offset < 0) {
21891 start_offset = buffer_length + start_offset;
21892 }
21893 if (duk_is_undefined(ctx, idx_end)) {
21894 end_offset = buffer_length;
21895 } else {
21896 end_offset = duk_to_int(ctx, idx_end);
21897 if (end_offset < 0) {
21898 end_offset = buffer_length + end_offset;
21899 }
21900 }
21901 /* Note: start_offset/end_offset can still be < 0 here. */
21902
21903 if (start_offset < 0) {
21904 start_offset = 0;
21905 } else if (start_offset > buffer_length) {
21906 start_offset = buffer_length;
21907 }
21908 if (end_offset < start_offset) {
21909 end_offset = start_offset;
21910 } else if (end_offset > buffer_length) {
21911 end_offset = buffer_length;
21912 }
21913 DUK_ASSERT(start_offset >= 0);
21914 DUK_ASSERT(start_offset <= buffer_length);
21915 DUK_ASSERT(end_offset >= 0);
21916 DUK_ASSERT(end_offset <= buffer_length);
21917 DUK_ASSERT(start_offset <= end_offset);
21918
21919 /* Convert indices to byte offsets. */
21920 start_offset <<= h_bufobj->shift;
21921 end_offset <<= h_bufobj->shift;
21922
21923 *out_start_offset = start_offset;
21924 *out_end_offset = end_offset;
21925}
21926#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21927
21928/*
21929 * Indexed read/write helpers (also used from outside this file)
21930 */
21931
21934
21935 DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);
21936
21937 switch (h_bufobj->elem_type) {
21939#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21941#endif
21942 duk_push_uint(ctx, (duk_uint_t) du.uc[0]);
21943 break;
21944#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21945 /* These are not needed when only Duktape.Buffer is supported. */
21947 duk_push_int(ctx, (duk_int_t) (duk_int8_t) du.uc[0]);
21948 break;
21950 duk_push_uint(ctx, (duk_uint_t) du.us[0]);
21951 break;
21953 duk_push_int(ctx, (duk_int_t) (duk_int16_t) du.us[0]);
21954 break;
21957 break;
21959 duk_push_int(ctx, (duk_int_t) (duk_int32_t) du.ui[0]);
21960 break;
21962 duk_push_number(ctx, (duk_double_t) du.f[0]);
21963 break;
21965 duk_push_number(ctx, (duk_double_t) du.d);
21966 break;
21967#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
21968 default:
21970 }
21971}
21972
21973DUK_INTERNAL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
21975
21976 /* NOTE! Caller must ensure that any side effects from the
21977 * coercions below are safe. If that cannot be guaranteed
21978 * (which is normally the case), caller must coerce the
21979 * argument using duk_to_number() before any pointer
21980 * validations; the result of duk_to_number() always coerces
21981 * without side effects here.
21982 */
21983
21984 switch (h_bufobj->elem_type) {
21986 du.uc[0] = (duk_uint8_t) duk_to_uint32(ctx, -1);
21987 break;
21988#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21989 /* These are not needed when only Duktape.Buffer is supported. */
21991 du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(ctx, -1);
21992 break;
21994 du.uc[0] = (duk_uint8_t) duk_to_int32(ctx, -1);
21995 break;
21997 du.us[0] = (duk_uint16_t) duk_to_uint32(ctx, -1);
21998 break;
22000 du.us[0] = (duk_uint16_t) duk_to_int32(ctx, -1);
22001 break;
22003 du.ui[0] = (duk_uint32_t) duk_to_uint32(ctx, -1);
22004 break;
22006 du.ui[0] = (duk_uint32_t) duk_to_int32(ctx, -1);
22007 break;
22009 du.f[0] = (duk_float_t) duk_to_number(ctx, -1);
22010 break;
22012 du.d = (duk_double_t) duk_to_number(ctx, -1);
22013 break;
22014#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22015 default:
22017 }
22018
22019 DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);
22020}
22021
22022/*
22023 * Duktape.Buffer: constructor
22024 */
22025
22027 duk_hthread *thr;
22028 duk_size_t buf_size;
22029 duk_small_int_t buf_dynamic;
22030 duk_uint8_t *buf_data;
22031 const duk_uint8_t *src_data;
22032
22033 thr = (duk_hthread *) ctx;
22034 DUK_UNREF(thr);
22035
22036 /*
22037 * Constructor arguments are currently somewhat compatible with
22038 * (keep it that way if possible):
22039 *
22040 * http://nodejs.org/api/buffer.html
22041 *
22042 * Note that the ToBuffer() coercion (duk_to_buffer()) does NOT match
22043 * the constructor behavior.
22044 */
22045
22046 buf_dynamic = duk_get_boolean(ctx, 1); /* default to false */
22047
22048 switch (duk_get_type(ctx, 0)) {
22049 case DUK_TYPE_NUMBER: {
22050 /* new buffer of specified size */
22051 buf_size = (duk_size_t) duk_to_int(ctx, 0);
22052 (void) duk_push_buffer(ctx, buf_size, buf_dynamic);
22053 break;
22054 }
22055 case DUK_TYPE_BUFFER: {
22056 /* return input buffer, converted to a Duktape.Buffer object
22057 * if called as a constructor (no change if called as a
22058 * function).
22059 */
22060 duk_set_top(ctx, 1);
22061 break;
22062 }
22063 case DUK_TYPE_STRING: {
22064 /* new buffer with string contents */
22065 src_data = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &buf_size);
22066 DUK_ASSERT(src_data != NULL); /* even for zero-length string */
22067 buf_data = (duk_uint8_t *) duk_push_buffer(ctx, buf_size, buf_dynamic);
22068 DUK_MEMCPY((void *) buf_data, (const void *) src_data, (size_t) buf_size);
22069 break;
22070 }
22071 case DUK_TYPE_OBJECT: {
22072 /* For all duk_hbufferobjects, get the plain buffer inside
22073 * without making a copy. This is compatible with Duktape 1.2
22074 * but means that a slice/view information is ignored and the
22075 * full underlying buffer is returned.
22076 *
22077 * If called as a constructor, a new Duktape.Buffer object
22078 * pointing to the same plain buffer is created below.
22079 */
22080 duk_hbufferobject *h_bufobj;
22081 h_bufobj = (duk_hbufferobject *) duk_get_hobject(ctx, 0);
22082 DUK_ASSERT(h_bufobj != NULL);
22083 if (!DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)) {
22084 return DUK_RET_TYPE_ERROR;
22085 }
22086 if (h_bufobj->buf == NULL) {
22087 return DUK_RET_TYPE_ERROR;
22088 }
22089 duk_push_hbuffer(ctx, h_bufobj->buf);
22090 break;
22091 }
22092 case DUK_TYPE_NONE:
22093 default: {
22094 return DUK_RET_TYPE_ERROR;
22095 }
22096 }
22097 DUK_ASSERT(duk_is_buffer(ctx, -1));
22098
22099 /* stack is unbalanced, but: [ <something> buf ] */
22100
22101 if (duk_is_constructor_call(ctx)) {
22102 duk_hbufferobject *h_bufobj;
22103 duk_hbuffer *h_val;
22104
22105 h_val = duk_get_hbuffer(ctx, -1);
22106 DUK_ASSERT(h_val != NULL);
22107
22108 h_bufobj = duk_push_bufferobject_raw(ctx,
22113 DUK_ASSERT(h_bufobj != NULL);
22114
22115 duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
22116
22118 }
22119 /* Note: unbalanced stack on purpose */
22120
22121 return 1;
22122}
22123
22124/*
22125 * Node.js Buffer: constructor
22126 */
22127
22128#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22130 /* Internal class is Object: Object.prototype.toString.call(new Buffer(0))
22131 * prints "[object Object]".
22132 */
22133 duk_int_t len;
22134 duk_int_t i;
22135 duk_hbuffer *h_buf;
22136 duk_hbufferobject *h_bufobj;
22137 duk_size_t buf_size;
22138
22139 switch (duk_get_type(ctx, 0)) {
22140 case DUK_TYPE_BUFFER: {
22141 /* Custom behavior: plain buffer is used as internal buffer
22142 * without making a copy (matches Duktape.Buffer).
22143 */
22144 duk_set_top(ctx, 1); /* -> [ buffer ] */
22145 break;
22146 }
22147 case DUK_TYPE_NUMBER: {
22148 len = duk_to_int_clamped(ctx, 0, 0, DUK_INT_MAX);
22149 (void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22150 break;
22151 }
22152 case DUK_TYPE_OBJECT: {
22153 duk_uint8_t *buf;
22154
22155 (void) duk_get_prop_string(ctx, 0, "length");
22156 len = duk_to_int_clamped(ctx, -1, 0, DUK_INT_MAX);
22157 duk_pop(ctx);
22158 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22159 for (i = 0; i < len; i++) {
22160 /* XXX: fast path for array arguments? */
22161 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
22162 buf[i] = (duk_uint8_t) (duk_to_uint32(ctx, -1) & 0xffU);
22163 duk_pop(ctx);
22164 }
22165 break;
22166 }
22167 case DUK_TYPE_STRING: {
22168 /* ignore encoding for now */
22169 duk_dup(ctx, 0);
22170 (void) duk_to_buffer(ctx, -1, &buf_size);
22171 break;
22172 }
22173 default:
22174 return DUK_RET_TYPE_ERROR;
22175 }
22176
22177 DUK_ASSERT(duk_is_buffer(ctx, -1));
22178 h_buf = duk_get_hbuffer(ctx, -1);
22179 DUK_ASSERT(h_buf != NULL);
22180
22181 h_bufobj = duk_push_bufferobject_raw(ctx,
22186 DUK_ASSERT(h_bufobj != NULL);
22187
22188 h_bufobj->buf = h_buf;
22189 DUK_HBUFFER_INCREF(thr, h_buf);
22190 DUK_ASSERT(h_bufobj->offset == 0);
22191 h_bufobj->length = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_buf);
22195
22196 return 1;
22197}
22198#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22200 DUK_UNREF(ctx);
22202}
22203#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22204
22205/*
22206 * ArrayBuffer, DataView, and TypedArray constructors
22207 */
22208
22209#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22211 duk_hthread *thr;
22212 duk_hbufferobject *h_bufobj;
22213 duk_hbuffer *h_val;
22214
22216 thr = (duk_hthread *) ctx;
22217 DUK_UNREF(thr);
22218
22219 /* XXX: function flag to make this automatic? */
22220 if (!duk_is_constructor_call(ctx)) {
22221 return DUK_RET_TYPE_ERROR;
22222 }
22223
22224 if (duk_is_buffer(ctx, 0)) {
22225 /* Custom behavior: plain buffer is used as internal buffer
22226 * without making a copy (matches Duktape.Buffer).
22227 */
22228
22229 h_val = duk_get_hbuffer(ctx, 0);
22230 DUK_ASSERT(h_val != NULL);
22231
22232 /* XXX: accept any duk_hbufferobject type as an input also? */
22233 } else {
22234 duk_int_t len;
22235 len = duk_to_int(ctx, 0);
22236 if (len < 0) {
22237 goto fail_length;
22238 }
22239 (void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22240 h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
22241 DUK_ASSERT(h_val != NULL);
22242
22243#if !defined(DUK_USE_ZERO_BUFFER_DATA)
22244 /* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
22245 * is not set.
22246 */
22248 DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) len);
22249#endif
22250 }
22251
22252 h_bufobj = duk_push_bufferobject_raw(ctx,
22257 DUK_ASSERT(h_bufobj != NULL);
22258
22259 duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
22261
22262 return 1;
22263
22264 fail_length:
22265 return DUK_RET_RANGE_ERROR;
22266}
22267#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22269 DUK_UNREF(ctx);
22271}
22272#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22273
22274
22275/* Format of magic, bits:
22276 * 0...1: elem size shift (0-3)
22277 * 2...5: elem type (DUK_HBUFFEROBJECT_ELEM_xxx)
22278 */
22279
22280#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22282 duk_hthread *thr;
22283 duk_tval *tv;
22284 duk_hobject *h_obj;
22285 duk_hbufferobject *h_bufobj = NULL;
22286 duk_hbufferobject *h_bufarr = NULL;
22287 duk_hbufferobject *h_bufarg = NULL;
22288 duk_hbuffer *h_val;
22289 duk_small_uint_t magic;
22290 duk_small_uint_t shift;
22291 duk_small_uint_t elem_type;
22292 duk_small_uint_t elem_size;
22293 duk_small_uint_t class_num;
22294 duk_small_uint_t proto_bidx;
22295 duk_uint_t align_mask;
22296 duk_uint_t elem_length;
22297 duk_int_t elem_length_signed;
22298 duk_uint_t byte_length;
22299 duk_small_uint_t copy_mode;
22300
22301 thr = (duk_hthread *) ctx;
22302 DUK_UNREF(thr);
22303
22304 /* XXX: function flag to make this automatic? */
22305 if (!duk_is_constructor_call(ctx)) {
22306 return DUK_RET_TYPE_ERROR;
22307 }
22308
22309 /* We could fit built-in index into magic but that'd make the magic
22310 * number dependent on built-in numbering (genbuiltins.py doesn't
22311 * handle that yet). So map both class and prototype from the
22312 * element type.
22313 */
22314 magic = duk_get_current_magic(ctx);
22315 shift = magic & 0x03; /* bits 0...1: shift */
22316 elem_type = (magic >> 2) & 0x0f; /* bits 2...5: type */
22317 elem_size = 1 << shift;
22318 align_mask = elem_size - 1;
22319 DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
22320 proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
22321 DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
22322 DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
22323 class_num = duk__buffer_class_from_elemtype[elem_type];
22324
22325 DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
22326 "elem_size=%d, proto_bidx=%d, class_num=%d",
22327 (int) magic, (int) shift, (int) elem_type, (int) elem_size,
22328 (int) proto_bidx, (int) class_num));
22329
22330 /* Argument variants. When the argument is an ArrayBuffer a view to
22331 * the same buffer is created; otherwise a new ArrayBuffer is always
22332 * created.
22333 */
22334
22335 tv = duk_get_tval(ctx, 0);
22336 DUK_ASSERT(tv != NULL); /* arg count */
22337 if (DUK_TVAL_IS_OBJECT(tv)) {
22338 h_obj = DUK_TVAL_GET_OBJECT(tv);
22339 DUK_ASSERT(h_obj != NULL);
22340
22342 /* ArrayBuffer: unlike any other argument variant, create
22343 * a view into the existing buffer.
22344 */
22345
22346 duk_int_t byte_offset_signed;
22347 duk_uint_t byte_offset;
22348
22349 h_bufarg = (duk_hbufferobject *) h_obj;
22350
22351 byte_offset_signed = duk_to_int(ctx, 1);
22352 if (byte_offset_signed < 0) {
22353 goto fail_arguments;
22354 }
22355 byte_offset = (duk_uint_t) byte_offset_signed;
22356 if (byte_offset > h_bufarg->length ||
22357 (byte_offset & align_mask) != 0) {
22358 /* Must be >= 0 and multiple of element size. */
22359 goto fail_arguments;
22360 }
22361 if (duk_is_undefined(ctx, 2)) {
22362 DUK_ASSERT(h_bufarg->length >= byte_offset);
22363 byte_length = h_bufarg->length - byte_offset;
22364 if ((byte_length & align_mask) != 0) {
22365 /* Must be element size multiple from
22366 * start offset to end of buffer.
22367 */
22368 goto fail_arguments;
22369 }
22370 elem_length = (byte_length >> shift);
22371 } else {
22372 elem_length_signed = duk_to_int(ctx, 2);
22373 if (elem_length_signed < 0) {
22374 goto fail_arguments;
22375 }
22376 elem_length = (duk_uint_t) elem_length_signed;
22377 byte_length = elem_length << shift;
22378 if ((byte_length >> shift) != elem_length) {
22379 /* Byte length would overflow. */
22380 /* XXX: easier check with less code? */
22381 goto fail_arguments;
22382 }
22383 DUK_ASSERT(h_bufarg->length >= byte_offset);
22384 if (byte_length > h_bufarg->length - byte_offset) {
22385 /* Not enough data. */
22386 goto fail_arguments;
22387 }
22388 }
22389 DUK_UNREF(elem_length);
22390 DUK_ASSERT_DISABLE(byte_offset >= 0);
22391 DUK_ASSERT(byte_offset <= h_bufarg->length);
22392 DUK_ASSERT_DISABLE(byte_length >= 0);
22393 DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
22394 DUK_ASSERT((elem_length << shift) == byte_length);
22395
22396 h_bufobj = duk_push_bufferobject_raw(ctx,
22399 DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
22400 proto_bidx);
22401 h_val = h_bufarg->buf;
22402 if (h_val == NULL) {
22403 return DUK_RET_TYPE_ERROR;
22404 }
22405 h_bufobj->buf = h_val;
22406 DUK_HBUFFER_INCREF(thr, h_val);
22407 h_bufobj->offset = h_bufarg->offset + byte_offset;
22408 h_bufobj->length = byte_length;
22409 h_bufobj->shift = (duk_uint8_t) shift;
22410 h_bufobj->elem_type = (duk_uint8_t) elem_type;
22411 h_bufobj->is_view = 1;
22413
22414 /* Set .buffer to the argument ArrayBuffer. */
22415 duk_dup(ctx, 0);
22417 duk_compact(ctx, -1);
22418 return 1;
22419 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
22420 /* TypedArray (or other non-ArrayBuffer duk_hbufferobject).
22421 * Conceptually same behavior as for an Array-like argument,
22422 * with a few fast paths.
22423 */
22424
22425 h_bufarg = (duk_hbufferobject *) h_obj;
22427 elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
22428 if (h_bufarg->buf == NULL) {
22429 return DUK_RET_TYPE_ERROR;
22430 }
22431
22432 /* Select copy mode. Must take into account element
22433 * compatibility and validity of the underlying source
22434 * buffer.
22435 */
22436
22437 DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
22438 "src byte_length=%ld, src shift=%d, "
22439 "src/dst elem_length=%ld; "
22440 "dst shift=%d -> dst byte_length=%ld",
22441 (long) h_bufarg->length, (int) h_bufarg->shift,
22442 (long) elem_length_signed, (int) shift,
22443 (long) (elem_length_signed << shift)));
22444
22445 copy_mode = 2; /* default is explicit index read/write copy */
22446 DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
22447 if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
22448 if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
22449 DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
22450 DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */
22451 copy_mode = 0;
22452 } else {
22453 DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
22454 copy_mode = 1;
22455 }
22456 }
22457 } else {
22458 /* Array or Array-like */
22459 elem_length_signed = (duk_int_t) duk_get_length(ctx, 0);
22460 copy_mode = 2;
22461 }
22462 } else if (DUK_TVAL_IS_BUFFER(tv)) {
22463 /* Accept plain buffer values like array initializers
22464 * (new in Duktape 1.4.0).
22465 */
22466 duk_hbuffer *h_srcbuf;
22467 h_srcbuf = DUK_TVAL_GET_BUFFER(tv);
22468 elem_length_signed = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_srcbuf);
22469 copy_mode = 2; /* XXX: could add fast path for u8 compatible views */
22470 } else {
22471 /* Non-object argument is simply int coerced, matches
22472 * V8 behavior (except for "null", which we coerce to
22473 * 0 but V8 TypeErrors).
22474 */
22475 elem_length_signed = duk_to_int(ctx, 0);
22476 copy_mode = 3;
22477 }
22478 if (elem_length_signed < 0) {
22479 goto fail_arguments;
22480 }
22481 elem_length = (duk_uint_t) elem_length_signed;
22482 byte_length = (duk_uint_t) (elem_length << shift);
22483 if ((byte_length >> shift) != elem_length) {
22484 /* Byte length would overflow. */
22485 /* XXX: easier check with less code? */
22486 goto fail_arguments;
22487 }
22488
22489 DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
22490 (long) elem_length, (long) byte_length));
22491
22492 /* ArrayBuffer argument is handled specially above; the rest of the
22493 * argument variants are handled by shared code below.
22494 */
22495
22496 /* Push a new ArrayBuffer (becomes view .buffer) */
22497 h_bufarr = duk__push_arraybuffer_with_length(ctx, byte_length);
22498 DUK_ASSERT(h_bufarr != NULL);
22499 h_val = h_bufarr->buf;
22500 DUK_ASSERT(h_val != NULL);
22501
22502 /* Push the resulting view object and attach the ArrayBuffer. */
22503 h_bufobj = duk_push_bufferobject_raw(ctx,
22506 DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
22507 proto_bidx);
22508
22509 h_bufobj->buf = h_val;
22510 DUK_HBUFFER_INCREF(thr, h_val);
22511 DUK_ASSERT(h_bufobj->offset == 0);
22512 h_bufobj->length = byte_length;
22513 h_bufobj->shift = (duk_uint8_t) shift;
22514 h_bufobj->elem_type = (duk_uint8_t) elem_type;
22515 h_bufobj->is_view = 1;
22517
22518 /* Set .buffer */
22519 duk_dup(ctx, -2);
22521 duk_compact(ctx, -1);
22522
22523 /* Copy values, the copy method depends on the arguments.
22524 *
22525 * Copy mode decision may depend on the validity of the underlying
22526 * buffer of the source argument; there must be no harmful side effects
22527 * from there to here for copy_mode to still be valid.
22528 */
22529 DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
22530 switch (copy_mode) {
22531 case 0: {
22532 /* Use byte copy. */
22533
22534 duk_uint8_t *p_src;
22535 duk_uint8_t *p_dst;
22536
22537 DUK_ASSERT(h_bufobj != NULL);
22538 DUK_ASSERT(h_bufobj->buf != NULL);
22540 DUK_ASSERT(h_bufarg != NULL);
22541 DUK_ASSERT(h_bufarg->buf != NULL);
22543
22544 p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
22545 p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
22546
22547 DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
22548 (void *) p_src, (void *) p_dst, (long) byte_length));
22549
22550 DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length);
22551 break;
22552 }
22553 case 1: {
22554 /* Copy values through direct validated reads and writes. */
22555
22556 duk_small_uint_t src_elem_size;
22557 duk_small_uint_t dst_elem_size;
22558 duk_uint8_t *p_src;
22559 duk_uint8_t *p_src_end;
22560 duk_uint8_t *p_dst;
22561
22562 DUK_ASSERT(h_bufobj != NULL);
22563 DUK_ASSERT(h_bufobj->buf != NULL);
22565 DUK_ASSERT(h_bufarg != NULL);
22566 DUK_ASSERT(h_bufarg->buf != NULL);
22568
22569 src_elem_size = 1 << h_bufarg->shift;
22570 dst_elem_size = elem_size;
22571
22572 p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
22573 p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
22574 p_src_end = p_src + h_bufarg->length;
22575
22576 DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
22577 "src_elem_size=%d, dst_elem_size=%d",
22578 (void *) p_src, (void *) p_src_end, (void *) p_dst,
22579 (int) src_elem_size, (int) dst_elem_size));
22580
22581 while (p_src != p_src_end) {
22582 DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
22583 "p_src=%p, p_src_end=%p, p_dst=%p",
22584 (void *) p_src, (void *) p_src_end, (void *) p_dst));
22585 /* A validated read() is always a number, so it's write coercion
22586 * is always side effect free an won't invalidate pointers etc.
22587 */
22588 duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
22589 duk_hbufferobject_validated_write(ctx, h_bufobj, p_dst, dst_elem_size);
22590 duk_pop(ctx);
22591 p_src += src_elem_size;
22592 p_dst += dst_elem_size;
22593 }
22594 break;
22595 }
22596 case 2: {
22597 /* Copy values by index reads and writes. Let virtual
22598 * property handling take care of coercion.
22599 */
22600 duk_uint_t i;
22601
22602 DUK_DDD(DUK_DDDPRINT("using slow copy"));
22603
22604 for (i = 0; i < elem_length; i++) {
22605 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
22606 duk_put_prop_index(ctx, -2, (duk_uarridx_t) i);
22607 }
22608 break;
22609 }
22610 default:
22611 case 3: {
22612 /* No copy, leave zero bytes in the buffer. There's no
22613 * ambiguity with Float32/Float64 because zero bytes also
22614 * represent 0.0.
22615 */
22616#if !defined(DUK_USE_ZERO_BUFFER_DATA)
22617 /* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
22618 * is not set.
22619 */
22621 DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) byte_length);
22622#endif
22623
22624 DUK_DDD(DUK_DDDPRINT("using no copy"));
22625 break;
22626 }
22627 }
22628
22629 return 1;
22630
22631 fail_arguments:
22632 return DUK_RET_RANGE_ERROR;
22633}
22634#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22636 DUK_UNREF(ctx);
22638}
22639#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22640
22641#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22643 duk_hbufferobject *h_bufarg;
22644 duk_hbufferobject *h_bufobj;
22645 duk_hbuffer *h_val;
22646 duk_uint_t offset;
22647 duk_uint_t length;
22648
22649 /* XXX: function flag to make this automatic? */
22650 if (!duk_is_constructor_call(ctx)) {
22651 return DUK_RET_TYPE_ERROR;
22652 }
22653
22654 h_bufarg = duk__require_bufobj_value(ctx, 0);
22655 DUK_ASSERT(h_bufarg != NULL);
22656
22657 duk__resolve_offset_opt_length(ctx, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
22658 DUK_ASSERT(offset <= h_bufarg->length);
22659 DUK_ASSERT(offset + length <= h_bufarg->length);
22660
22661 h_bufobj = duk_push_bufferobject_raw(ctx,
22666
22667 h_val = h_bufarg->buf;
22668 if (h_val == NULL) {
22669 return DUK_RET_TYPE_ERROR;
22670 }
22671 h_bufobj->buf = h_val;
22672 DUK_HBUFFER_INCREF(thr, h_val);
22673 h_bufobj->offset = h_bufarg->offset + offset;
22674 h_bufobj->length = length;
22675 DUK_ASSERT(h_bufobj->shift == 0);
22677 h_bufobj->is_view = 1;
22678
22679 /* The DataView .buffer property is ordinarily set to the argument
22680 * which is an ArrayBuffer. We accept any duk_hbufferobject as
22681 * an argument and .buffer will be set to the argument regardless
22682 * of what it is. This may be a bit confusing if the argument
22683 * is e.g. a DataView or another TypedArray view.
22684 *
22685 * XXX: Copy .buffer property from a DataView/TypedArray argument?
22686 * Create a fresh ArrayBuffer for Duktape.Buffer and Node.js Buffer
22687 * arguments? See: test-bug-dataview-buffer-prop.js.
22688 */
22689
22690 duk_dup(ctx, 0);
22692 duk_compact(ctx, -1);
22693
22695 return 1;
22696}
22697#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22699 DUK_UNREF(ctx);
22701}
22702#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22703
22704/*
22705 * ArrayBuffer.isView()
22706 */
22707
22708#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22710 duk_hobject *h_obj;
22711 duk_bool_t ret = 0;
22712
22713 h_obj = duk_get_hobject(ctx, 0);
22714 if (h_obj != NULL && DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
22715 ret = ((duk_hbufferobject *) h_obj)->is_view;
22716 }
22717 duk_push_boolean(ctx, ret);
22718 return 1;
22719}
22720#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22722 DUK_UNREF(ctx);
22724}
22725#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22726
22727/*
22728 * Node.js Buffer: toString([encoding], [start], [end])
22729 */
22730
22731#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22733 duk_hthread *thr;
22734 duk_hbufferobject *h_this;
22735 duk_int_t start_offset, end_offset;
22736 duk_uint8_t *buf_slice;
22737 duk_size_t slice_length;
22738
22739 thr = (duk_hthread *) ctx;
22740 DUK_UNREF(thr);
22741
22742 h_this = duk__get_bufobj_this(ctx);
22743 if (h_this == NULL) {
22744 /* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
22745 duk_push_string(ctx, "[object Object]");
22746 return 1;
22747 }
22749
22750 /* ignore encoding for now */
22751
22752 duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &start_offset, &end_offset);
22753
22754 slice_length = (duk_size_t) (end_offset - start_offset);
22755 buf_slice = (duk_uint8_t *) duk_push_fixed_buffer(ctx, slice_length);
22756 DUK_ASSERT(buf_slice != NULL);
22757
22758 if (h_this->buf == NULL) {
22759 goto type_error;
22760 }
22761
22762 if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) {
22763 DUK_MEMCPY((void *) buf_slice,
22764 (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
22765 (size_t) slice_length);
22766 } else {
22767 /* not covered, return all zeroes */
22768 ;
22769 }
22770
22771 duk_to_string(ctx, -1);
22772 return 1;
22773
22774 type_error:
22775 return DUK_RET_TYPE_ERROR;
22776}
22777#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22779 DUK_UNREF(ctx);
22781}
22782#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22783
22784/*
22785 * Duktape.Buffer: toString(), valueOf()
22786 */
22787
22788#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22790 duk_hthread *thr;
22791 duk_tval *tv;
22792 duk_small_int_t to_string = duk_get_current_magic(ctx);
22793
22794 thr = (duk_hthread *) ctx;
22795 DUK_UNREF(thr);
22796
22798 DUK_ASSERT(tv != NULL);
22799
22800 if (DUK_TVAL_IS_BUFFER(tv)) {
22801 duk_hbuffer *h_buf;
22802 h_buf = DUK_TVAL_GET_BUFFER(tv);
22803 DUK_ASSERT(h_buf != NULL);
22804 duk_push_hbuffer(ctx, h_buf);
22805 } else if (DUK_TVAL_IS_OBJECT(tv)) {
22806 duk_hobject *h;
22807 duk_hbufferobject *h_bufobj;
22808
22809 /* Accept any duk_hbufferobject, though we're only normally
22810 * called for Duktape.Buffer values.
22811 */
22812 h = DUK_TVAL_GET_OBJECT(tv);
22813 DUK_ASSERT(h != NULL);
22815 DUK_DD(DUK_DDPRINT("toString/valueOf() called for a non-bufferobject object"));
22816 goto type_error;
22817 }
22818 h_bufobj = (duk_hbufferobject *) h;
22820
22821 if (h_bufobj->buf == NULL) {
22822 DUK_DD(DUK_DDPRINT("toString/valueOf() called for a bufferobject with NULL buf"));
22823 goto type_error;
22824 }
22825 duk_push_hbuffer(ctx, h_bufobj->buf);
22826 } else {
22827 goto type_error;
22828 }
22829
22830 if (to_string) {
22831 duk_to_string(ctx, -1);
22832 }
22833 return 1;
22834
22835 type_error:
22836 return DUK_RET_TYPE_ERROR;
22837}
22838#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22840 DUK_UNREF(ctx);
22842}
22843#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22844
22845/*
22846 * Node.js Buffer.prototype: toJSON()
22847 */
22848
22849#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22851 duk_hthread *thr;
22852 duk_hbufferobject *h_this;
22853 duk_uint8_t *buf;
22854 duk_uint_t i;
22855
22856 thr = (duk_hthread *) ctx;
22857 DUK_UNREF(thr);
22858 h_this = duk__require_bufobj_this(ctx);
22859 DUK_ASSERT(h_this != NULL);
22860
22861 if (h_this->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
22862 /* Serialize uncovered backing buffer as a null; doesn't
22863 * really matter as long we're memory safe.
22864 */
22865 duk_push_null(ctx);
22866 return 1;
22867 }
22868
22869 duk_push_object(ctx);
22872
22873 duk_push_array(ctx);
22874 for (i = 0; i < h_this->length; i++) {
22875 /* XXX: regetting the pointer may be overkill - we're writing
22876 * to a side-effect free array here.
22877 */
22878 DUK_ASSERT(h_this->buf != NULL);
22879 buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
22880 duk_push_uint(ctx, (duk_uint_t) buf[i]);
22881 duk_put_prop_index(ctx, -2, (duk_idx_t) i);
22882 }
22885 return 1;
22886}
22887#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22889 DUK_UNREF(ctx);
22891}
22892#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22893
22894/*
22895 * Node.js Buffer.prototype.equals()
22896 * Node.js Buffer.prototype.compare()
22897 * Node.js Buffer.compare()
22898 */
22899
22900#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22902 duk_hthread *thr;
22903 duk_small_uint_t magic;
22904 duk_hbufferobject *h_bufarg1;
22905 duk_hbufferobject *h_bufarg2;
22906 duk_small_int_t comp_res;
22907
22908 thr = (duk_hthread *) ctx;
22909 DUK_UNREF(thr);
22910
22911 magic = duk_get_current_magic(ctx);
22912 if (magic & 0x02) {
22913 /* Static call style. */
22914 h_bufarg1 = duk__require_bufobj_value(ctx, 0);
22915 h_bufarg2 = duk__require_bufobj_value(ctx, 1);
22916 } else {
22917 h_bufarg1 = duk__require_bufobj_this(ctx);
22918 h_bufarg2 = duk__require_bufobj_value(ctx, 0);
22919 }
22920 DUK_ASSERT(h_bufarg1 != NULL);
22921 DUK_ASSERT(h_bufarg2 != NULL);
22922
22923 /* We want to compare the slice/view areas of the arguments.
22924 * If either slice/view is invalid (underlying buffer is shorter)
22925 * ensure equals() is false, but otherwise the only thing that
22926 * matters is to be memory safe.
22927 */
22928
22929 if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg1) &&
22930 DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg2)) {
22931 comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
22932 (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
22933 (duk_size_t) h_bufarg1->length,
22934 (duk_size_t) h_bufarg2->length);
22935 } else {
22936 comp_res = -1; /* either nonzero value is ok */
22937 }
22938
22939 if (magic & 0x01) {
22940 /* compare: similar to string comparison but for buffer data. */
22941 duk_push_int(ctx, comp_res);
22942 } else {
22943 /* equals */
22944 duk_push_boolean(ctx, (comp_res == 0));
22945 }
22946
22947 return 1;
22948}
22949#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
22951 DUK_UNREF(ctx);
22953}
22954#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
22955
22956/*
22957 * Node.js Buffer.prototype.fill()
22958 */
22959
22960#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22962 duk_hthread *thr;
22963 duk_hbufferobject *h_this;
22964 const duk_uint8_t *fill_str_ptr;
22965 duk_size_t fill_str_len;
22966 duk_uint8_t fill_value;
22967 duk_int_t fill_offset;
22968 duk_int_t fill_end;
22969 duk_size_t fill_length;
22970 duk_uint8_t *p;
22971
22972 thr = (duk_hthread *) ctx;
22973 DUK_UNREF(thr);
22974
22975 h_this = duk__require_bufobj_this(ctx);
22976 DUK_ASSERT(h_this != NULL);
22977 if (h_this->buf == NULL) {
22978 return DUK_RET_TYPE_ERROR;
22979 }
22980
22981 /* [ value offset end ] */
22982
22983 if (duk_is_string(ctx, 0)) {
22984 fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &fill_str_len);
22985 DUK_ASSERT(fill_str_ptr != NULL);
22986 } else {
22987 fill_value = (duk_uint8_t) duk_to_uint32(ctx, 0);
22988 fill_str_ptr = (const duk_uint8_t *) &fill_value;
22989 fill_str_len = 1;
22990 }
22991
22992 /* Fill offset handling is more lenient than in Node.js. */
22993
22994 duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &fill_offset, &fill_end);
22995
22996 DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
22997 (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
22998
22999 DUK_ASSERT(fill_end - fill_offset >= 0);
23000 DUK_ASSERT(h_this->buf != NULL);
23001
23002 p = (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
23003 fill_length = (duk_size_t) (fill_end - fill_offset);
23004 if (fill_str_len == 1) {
23005 /* Handle single character fills as memset() even when
23006 * the fill data comes from a one-char argument.
23007 */
23008 DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
23009 } else if (fill_str_len > 1) {
23010 duk_size_t i, n, t;
23011
23012 for (i = 0, n = (fill_end - fill_offset), t = 0; i < n; i++) {
23013 p[i] = fill_str_ptr[t++];
23014 if (t >= fill_str_len) {
23015 t = 0;
23016 }
23017 }
23018 } else {
23019 DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
23020 }
23022 /* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
23023 duk_push_this(ctx);
23024 return 1;
23025}
23026#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23028 DUK_UNREF(ctx);
23030}
23031#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23032
23033/*
23034 * Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
23035 */
23036
23037#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23039 duk_hthread *thr;
23040 duk_hbufferobject *h_this;
23041 duk_uint_t offset;
23042 duk_uint_t length;
23043 const duk_uint8_t *str_data;
23045
23046 thr = (duk_hthread *) ctx;
23047 DUK_UNREF(thr);
23048
23049 h_this = duk__require_bufobj_this(ctx);
23050 DUK_ASSERT(h_this != NULL);
23051
23052 /* Argument must be a string, e.g. a buffer is not allowed. */
23053 str_data = (const duk_uint8_t *) duk_require_lstring(ctx, 0, &str_len);
23054
23055 duk__resolve_offset_opt_length(ctx, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
23056 DUK_ASSERT(offset <= h_this->length);
23057 DUK_ASSERT(offset + length <= h_this->length);
23058
23059 /* XXX: encoding is ignored now. */
23060
23061 if (length > str_len) {
23062 length = (duk_uint_t) str_len;
23063 }
23064
23065 if (DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
23066 /* Cannot overlap. */
23067 DUK_MEMCPY((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset),
23068 (const void *) str_data,
23069 (size_t) length);
23070 } else {
23071 DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
23073
23074 duk_push_uint(ctx, length);
23075 return 1;
23076}
23077#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23079 DUK_UNREF(ctx);
23081}
23082#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23083
23084/*
23085 * Node.js Buffer.prototype.copy()
23086 */
23087
23088#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23090 duk_hthread *thr;
23091 duk_hbufferobject *h_this;
23092 duk_hbufferobject *h_bufarg;
23093 duk_int_t source_length;
23094 duk_int_t target_length;
23095 duk_int_t target_start, source_start, source_end;
23096 duk_uint_t target_ustart, source_ustart, source_uend;
23097 duk_uint_t copy_size = 0;
23098
23099 /* [ targetBuffer targetStart sourceStart sourceEnd ] */
23100
23101 thr = (duk_hthread *) ctx;
23102 DUK_UNREF(thr);
23103
23104 h_this = duk__require_bufobj_this(ctx);
23105 h_bufarg = duk__require_bufobj_value(ctx, 0);
23106 DUK_ASSERT(h_this != NULL);
23107 DUK_ASSERT(h_bufarg != NULL);
23108 source_length = (duk_int_t) h_this->length;
23109 target_length = (duk_int_t) h_bufarg->length;
23110
23111 target_start = duk_to_int(ctx, 1);
23112 source_start = duk_to_int(ctx, 2);
23113 if (duk_is_undefined(ctx, 3)) {
23114 source_end = source_length;
23115 } else {
23116 source_end = duk_to_int(ctx, 3);
23117 }
23118
23119 DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
23120 "source_start=%ld, source_end=%ld, source_length=%ld",
23121 (long) target_start, (long) h_bufarg->length,
23122 (long) source_start, (long) source_end, (long) source_length));
23123
23124 /* This behavior mostly mimics Node.js now. */
23125
23126 if (source_start < 0 || source_end < 0 || target_start < 0) {
23127 /* Negative offsets cause a RangeError. */
23128 goto fail_bounds;
23129 }
23130 source_ustart = (duk_uint_t) source_start;
23131 source_uend = (duk_uint_t) source_end;
23132 target_ustart = (duk_uint_t) target_start;
23133 if (source_ustart >= source_uend || /* crossed offsets or zero size */
23134 source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */
23135 target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */
23136 goto silent_ignore;
23137 }
23138 if (source_uend >= (duk_uint_t) source_length) {
23139 /* Source end clamped silently to available length. */
23140 source_uend = source_length;
23141 }
23142 copy_size = source_uend - source_ustart;
23143 if (target_ustart + copy_size > (duk_uint_t) target_length) {
23144 /* Clamp to target's end if too long.
23145 *
23146 * NOTE: there's no overflow possibility in the comparison;
23147 * both target_ustart and copy_size are >= 0 and based on
23148 * values in duk_int_t range. Adding them as duk_uint_t
23149 * values is then guaranteed not to overflow.
23150 */
23151 DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */
23152 DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */
23153 copy_size = (duk_uint_t) target_length - target_ustart;
23154 }
23155
23156 DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
23157 (unsigned long) target_ustart, (unsigned long) source_ustart,
23158 (unsigned long) copy_size));
23159
23160 DUK_ASSERT(copy_size >= 1);
23161 DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
23162 DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
23163 DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
23164 DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
23165
23166 /* Ensure copy is covered by underlying buffers. */
23167 DUK_ASSERT(h_bufarg->buf != NULL); /* length check */
23168 DUK_ASSERT(h_this->buf != NULL); /* length check */
23169 if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
23170 DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
23171 /* Must use memmove() because copy area may overlap (source and target
23172 * buffer may be the same, or from different slices.
23173 */
23174 DUK_MEMMOVE((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
23175 (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
23176 (size_t) copy_size);
23177 } else {
23178 DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
23179 }
23180
23181 silent_ignore:
23182 /* Return value is like write(), number of bytes written.
23183 * The return value matters because of code like:
23184 * "off += buf.copy(...)".
23185 */
23186 duk_push_uint(ctx, copy_size);
23187 return 1;
23188
23189 fail_bounds:
23190 return DUK_RET_RANGE_ERROR;
23191}
23192#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23194 DUK_UNREF(ctx);
23196}
23197#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23198
23199/*
23200 * TypedArray.prototype.set()
23201 *
23202 * TypedArray set() is pretty interesting to implement because:
23203 *
23204 * - The source argument may be a plain array or a typedarray. If the
23205 * source is a TypedArray, values are decoded and re-encoded into the
23206 * target (not as a plain byte copy). This may happen even when the
23207 * element byte size is the same, e.g. integer values may be re-encoded
23208 * into floats.
23209 *
23210 * - Source and target may refer to the same underlying buffer, so that
23211 * the set() operation may overlap. The specification requires that this
23212 * must work as if a copy was made before the operation. Note that this
23213 * is NOT a simple memmove() situation because the source and target
23214 * byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
23215 * expand to a 16-byte target (Uint32Array) so that the target overlaps
23216 * the source both from beginning and the end (unlike in typical memmove).
23217 *
23218 * - Even if 'buf' pointers of the source and target differ, there's no
23219 * guarantee that their memory areas don't overlap. This may be the
23220 * case with external buffers.
23221 *
23222 * Even so, it is nice to optimize for the common case:
23223 *
23224 * - Source and target separate buffers or non-overlapping.
23225 *
23226 * - Source and target have a compatible type so that a plain byte copy
23227 * is possible. Note that while e.g. uint8 and int8 are compatible
23228 * (coercion one way or another doesn't change the byte representation),
23229 * e.g. int8 and uint8clamped are NOT compatible when writing int8
23230 * values into uint8clamped typedarray (-1 would clamp to 0 for instance).
23231 *
23232 * See test-bi-typedarray-proto-set.js.
23233 */
23234
23235#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23237 duk_hthread *thr;
23238 duk_hbufferobject *h_this;
23239 duk_hobject *h_obj;
23240 duk_uarridx_t i, n;
23241 duk_int_t offset_signed;
23242 duk_uint_t offset_elems;
23243 duk_uint_t offset_bytes;
23244
23245 thr = (duk_hthread *) ctx;
23246 DUK_UNREF(thr);
23247
23248 h_this = duk__require_bufobj_this(ctx);
23249 DUK_ASSERT(h_this != NULL);
23251
23252 if (h_this->buf == NULL) {
23253 DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
23254 return 0;
23255 }
23256
23257 h_obj = duk_require_hobject(ctx, 0);
23258 DUK_ASSERT(h_obj != NULL);
23259
23260 /* XXX: V8 throws a TypeError for negative values. Would it
23261 * be more useful to interpret negative offsets here from the
23262 * end of the buffer too?
23263 */
23264 offset_signed = duk_to_int(ctx, 1);
23265 if (offset_signed < 0) {
23266 return DUK_RET_TYPE_ERROR;
23267 }
23268 offset_elems = (duk_uint_t) offset_signed;
23269 offset_bytes = offset_elems << h_this->shift;
23270 if ((offset_bytes >> h_this->shift) != offset_elems) {
23271 /* Byte length would overflow. */
23272 /* XXX: easier check with less code? */
23273 return DUK_RET_RANGE_ERROR;
23274 }
23275 if (offset_bytes > h_this->length) {
23276 /* Equality may be OK but >length not. Checking
23277 * this explicitly avoids some overflow cases
23278 * below.
23279 */
23280 return DUK_RET_RANGE_ERROR;
23281 }
23282 DUK_ASSERT(offset_bytes <= h_this->length);
23283
23284 /* Fast path: source is a TypedArray (or any bufferobject). */
23285
23286 if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
23287 duk_hbufferobject *h_bufarg;
23288 duk_uint16_t comp_mask;
23289 duk_small_int_t no_overlap = 0;
23290 duk_uint_t src_length;
23291 duk_uint_t dst_length;
23292 duk_uint_t dst_length_elems;
23293 duk_uint8_t *p_src_base;
23294 duk_uint8_t *p_src_end;
23295 duk_uint8_t *p_src;
23296 duk_uint8_t *p_dst_base;
23297 duk_uint8_t *p_dst;
23298 duk_small_uint_t src_elem_size;
23299 duk_small_uint_t dst_elem_size;
23300
23301 h_bufarg = (duk_hbufferobject *) h_obj;
23303
23304 if (h_bufarg->buf == NULL) {
23305 DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
23306 return 0;
23307 }
23308
23309 /* Nominal size check. */
23310 src_length = h_bufarg->length; /* bytes in source */
23311 dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */
23312 dst_length = dst_length_elems << h_this->shift; /* bytes in dest */
23313 if ((dst_length >> h_this->shift) != dst_length_elems) {
23314 /* Byte length would overflow. */
23315 /* XXX: easier check with less code? */
23316 return DUK_RET_RANGE_ERROR;
23317 }
23318 DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
23319 (long) src_length, (long) dst_length));
23320 DUK_ASSERT(offset_bytes <= h_this->length);
23321 if (dst_length > h_this->length - offset_bytes) {
23322 /* Overflow not an issue because subtraction is used on the right
23323 * side and guaranteed to be >= 0.
23324 */
23325 DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
23326 return DUK_RET_RANGE_ERROR;
23327 }
23328 if (!DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
23329 DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
23330 return 0;
23331 }
23332
23333 p_src_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
23334 p_dst_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
23335
23336 /* Check actual underlying buffers for validity and that they
23337 * cover the copy. No side effects are allowed after the check
23338 * so that the validity status doesn't change.
23339 */
23340 if (!DUK_HBUFFEROBJECT_VALID_SLICE(h_this) ||
23341 !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
23342 /* The condition could be more narrow and check for the
23343 * copy area only, but there's no need for fine grained
23344 * behavior when the underlying buffer is misconfigured.
23345 */
23346 DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
23347 return 0;
23348 }
23349
23350 /* We want to do a straight memory copy if possible: this is
23351 * an important operation because .set() is the TypedArray
23352 * way to copy chunks of memory. However, because set()
23353 * conceptually works in terms of elements, not all views are
23354 * compatible with direct byte copying.
23355 *
23356 * If we do manage a direct copy, the "overlap issue" handled
23357 * below can just be solved using memmove() because the source
23358 * and destination element sizes are necessarily equal.
23359 */
23360
23361 DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
23363 if (comp_mask & (1 << h_bufarg->elem_type)) {
23364 DUK_ASSERT(src_length == dst_length);
23365
23366 DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
23367 DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
23368 return 0;
23369 }
23370 DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
23371
23372 /* We want to avoid making a copy to process set() but that's
23373 * not always possible: the source and the target may overlap
23374 * and because element sizes are different, the overlap cannot
23375 * always be handled with a memmove() or choosing the copy
23376 * direction in a certain way. For example, if source type is
23377 * uint8 and target type is uint32, the target area may exceed
23378 * the source area from both ends!
23379 *
23380 * Note that because external buffers may point to the same
23381 * memory areas, we must ultimately make this check using
23382 * pointers.
23383 *
23384 * NOTE: careful with side effects: any side effect may cause
23385 * a buffer resize (or external buffer pointer/length update)!
23386 */
23387
23388 DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
23389 "p_dst_base=%p, dst_length=%ld",
23390 (void *) p_src_base, (long) src_length,
23391 (void *) p_dst_base, (long) dst_length));
23392
23393 if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */
23394 p_src_base + src_length <= p_dst_base) { /* source ends before dest starts */
23395 no_overlap = 1;
23396 }
23397
23398 if (!no_overlap) {
23399 /* There's overlap: the desired end result is that
23400 * conceptually a copy is made to avoid "trampling"
23401 * of source data by destination writes. We make
23402 * an actual temporary copy to handle this case.
23403 */
23404 duk_uint8_t *p_src_copy;
23405
23406 DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
23407 p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_length);
23408 DUK_ASSERT(p_src_copy != NULL);
23409 DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
23410
23411 p_src_base = p_src_copy; /* use p_src_base from now on */
23412 }
23413 /* Value stack intentionally mixed size here. */
23414
23415 DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
23416 "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
23417 (void *) p_src_base, (long) src_length,
23418 (void *) p_dst_base, (long) dst_length,
23419 (long) duk_get_top(ctx)));
23420
23421 /* Ready to make the copy. We must proceed element by element
23422 * and must avoid any side effects that might cause the buffer
23423 * validity check above to become invalid.
23424 *
23425 * Although we work through the value stack here, only plain
23426 * numbers are handled which should be side effect safe.
23427 */
23428
23429 src_elem_size = 1 << h_bufarg->shift;
23430 dst_elem_size = 1 << h_this->shift;
23431 p_src = p_src_base;
23432 p_dst = p_dst_base;
23433 p_src_end = p_src_base + src_length;
23434
23435 while (p_src != p_src_end) {
23436 DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
23437 "p_src=%p, p_src_end=%p, p_dst=%p",
23438 (void *) p_src, (void *) p_src_end, (void *) p_dst));
23439 /* A validated read() is always a number, so it's write coercion
23440 * is always side effect free an won't invalidate pointers etc.
23441 */
23442 duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
23443 duk_hbufferobject_validated_write(ctx, h_this, p_dst, dst_elem_size);
23444 duk_pop(ctx);
23445 p_src += src_elem_size;
23446 p_dst += dst_elem_size;
23447 }
23448
23449 return 0;
23450 } else {
23451 /* Slow path: quite slow, but we save space by using the property code
23452 * to write coerce target values. We don't need to worry about overlap
23453 * here because the source is not a TypedArray.
23454 *
23455 * We could use the bufferobject write coercion helper but since the
23456 * property read may have arbitrary side effects, full validity checks
23457 * would be needed for every element anyway.
23458 */
23459
23460 n = (duk_uarridx_t) duk_get_length(ctx, 0);
23461 DUK_ASSERT(offset_bytes <= h_this->length);
23462 if ((n << h_this->shift) > h_this->length - offset_bytes) {
23463 /* Overflow not an issue because subtraction is used on the right
23464 * side and guaranteed to be >= 0.
23465 */
23466 DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
23467 return DUK_RET_RANGE_ERROR;
23468 }
23469
23470 /* There's no need to check for buffer validity status for the
23471 * target here: the property access code will do that for each
23472 * element. Moreover, if we did check the validity here, side
23473 * effects from reading the source argument might invalidate
23474 * the results anyway.
23475 */
23476
23477 DUK_ASSERT_TOP(ctx, 2);
23478 duk_push_this(ctx);
23479
23480 for (i = 0; i < n; i++) {
23481 duk_get_prop_index(ctx, 0, i);
23482 duk_put_prop_index(ctx, 2, offset_elems + i);
23483 }
23484 }
23485
23486 return 0;
23487}
23488#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23490 DUK_UNREF(ctx);
23492}
23493#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23494
23495/*
23496 * Node.js Buffer.prototype.slice([start], [end])
23497 * ArrayBuffer.prototype.slice(begin, [end])
23498 * TypedArray.prototype.slice(begin, [end])
23499 *
23500 * The API calls are almost identical; negative indices are counted from end
23501 * of buffer, and final indices are clamped (allowing crossed indices). Main
23502 * differences:
23503 *
23504 * - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
23505 * views, ArrayBuffer .slice() creates a copy
23506 *
23507 * - Resulting object has a different class and prototype depending on the
23508 * call (or 'this' argument)
23509 *
23510 * - TypedArray .subarray() arguments are element indices, not byte offsets
23511 */
23512
23513#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23515 duk_hthread *thr;
23516 duk_small_int_t magic;
23517 duk_small_uint_t res_class_num;
23518 duk_hobject *res_proto;
23519 duk_hbufferobject *h_this;
23520 duk_hbufferobject *h_bufobj;
23521 duk_hbuffer *h_val;
23522 duk_int_t start_offset, end_offset;
23523 duk_uint_t slice_length;
23524
23525 thr = (duk_hthread *) ctx;
23526 DUK_UNREF(thr);
23527
23528 /* [ start end ] */
23529
23530 magic = duk_get_current_magic(ctx);
23531 h_this = duk__require_bufobj_this(ctx);
23532
23533 /* Slice offsets are element (not byte) offsets, which only matters
23534 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
23535 * zero so byte and element offsets are the same. Negative indices
23536 * are counted from end of slice, crossed indices are allowed (and
23537 * result in zero length result), and final values are clamped
23538 * against the current slice. There's intentionally no check
23539 * against the underlying buffer here.
23540 */
23541
23542 duk__clamp_startend_negidx_shifted(ctx, h_this, 0 /*idx_start*/, 1 /*idx_end*/, &start_offset, &end_offset);
23543 DUK_ASSERT(end_offset >= start_offset);
23544 slice_length = (duk_uint_t) (end_offset - start_offset);
23545
23546 /* The resulting buffer object gets the same class and prototype as
23547 * the buffer in 'this', e.g. if the input is a Node.js Buffer the
23548 * result is a Node.js Buffer; if the input is a Float32Array, the
23549 * result is a Float32Array.
23550 *
23551 * For the class number this seems correct. The internal prototype
23552 * is not so clear: if 'this' is a bufferobject with a non-standard
23553 * prototype object, that value gets copied over into the result
23554 * (instead of using the standard prototype for that object type).
23555 */
23556
23557 res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
23558 h_bufobj = duk_push_bufferobject_raw(ctx,
23561 DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
23562 DUK_BIDX_OBJECT_PROTOTYPE); /* replaced */
23563 DUK_ASSERT(h_bufobj != NULL);
23564 res_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_this); /* may be NULL */
23565 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_bufobj, res_proto);
23566
23567 h_bufobj->length = slice_length;
23568 h_bufobj->shift = h_this->shift; /* inherit */
23569 h_bufobj->elem_type = h_this->elem_type; /* inherit */
23570 h_bufobj->is_view = magic & 0x01;
23571 DUK_ASSERT(h_bufobj->is_view == 0 || h_bufobj->is_view == 1);
23572
23573 h_val = h_this->buf;
23574 if (h_val == NULL) {
23575 return DUK_RET_TYPE_ERROR;
23576 }
23577
23578 if (magic & 0x02) {
23579 /* non-zero: make copy */
23580 duk_uint8_t *p_copy;
23581 duk_size_t copy_length;
23582
23583 p_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) slice_length);
23584 DUK_ASSERT(p_copy != NULL);
23585
23586 /* Copy slice, respecting underlying buffer limits; remainder
23587 * is left as zero.
23588 */
23589 copy_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, slice_length);
23590 DUK_MEMCPY((void *) p_copy,
23591 (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
23592 copy_length);
23593
23594 h_val = duk_get_hbuffer(ctx, -1);
23595 DUK_ASSERT(h_val != NULL);
23596
23597 h_bufobj->buf = h_val;
23598 DUK_HBUFFER_INCREF(thr, h_val);
23599 DUK_ASSERT(h_bufobj->offset == 0);
23600
23601 duk_pop(ctx); /* reachable so pop OK */
23602 } else {
23603 h_bufobj->buf = h_val;
23604 DUK_HBUFFER_INCREF(thr, h_val);
23605 h_bufobj->offset = (duk_uint_t) (h_this->offset + start_offset);
23606
23607 /* Copy the .buffer property, needed for TypedArray.prototype.subarray().
23608 *
23609 * XXX: limit copy only for TypedArray classes specifically?
23610 */
23611
23612 duk_push_this(ctx);
23615 duk_pop(ctx);
23616 } else {
23617 duk_pop_2(ctx);
23618 }
23619 }
23620 /* unbalanced stack on purpose */
23621
23623 return 1;
23624}
23625#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23627 DUK_UNREF(ctx);
23629}
23630#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23631
23632/*
23633 * Node.js Buffer.isEncoding()
23634 */
23635
23636#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23638 const char *encoding;
23639
23640 /* only accept lowercase 'utf8' now. */
23641
23642 encoding = duk_to_string(ctx, 0);
23643 DUK_ASSERT(duk_is_string(ctx, 0)); /* guaranteed by duk_to_string() */
23644 duk_push_boolean(ctx, DUK_STRCMP(encoding, "utf8") == 0);
23645 return 1;
23646}
23647#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23649 DUK_UNREF(ctx);
23651}
23652#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23653
23654/*
23655 * Node.js Buffer.isBuffer()
23656 */
23657
23658#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23660 duk_hthread *thr;
23661 duk_tval *tv;
23662 duk_hobject *h;
23663 duk_hobject *h_proto;
23664 duk_bool_t ret = 0;
23665
23666 thr = (duk_hthread *) ctx;
23667
23668 DUK_ASSERT(duk_get_top(ctx) >= 1); /* nargs */
23669 tv = duk_get_tval(ctx, 0);
23670 DUK_ASSERT(tv != NULL);
23671
23672 if (DUK_TVAL_IS_OBJECT(tv)) {
23673 h = DUK_TVAL_GET_OBJECT(tv);
23674 DUK_ASSERT(h != NULL);
23675
23677 DUK_ASSERT(h_proto != NULL);
23678
23679 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
23680 if (h) {
23681 ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
23682 }
23684
23685 duk_push_boolean(ctx, ret);
23686 return 1;
23687}
23688#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23690 DUK_UNREF(ctx);
23692}
23693#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23694
23695/*
23696 * Node.js Buffer.byteLength()
23697 */
23698
23699#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23701 const char *str;
23702 duk_size_t len;
23703
23704 /* At the moment Buffer(<str>) will just use the string bytes as
23705 * is (ignoring encoding), so we return the string length here
23706 * unconditionally.
23707 */
23708
23709 str = duk_to_lstring(ctx, 0, &len);
23710 DUK_UNREF(str);
23711 duk_push_size_t(ctx, len);
23712 return 1;
23713}
23714#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23716 DUK_UNREF(ctx);
23718}
23719#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23720
23721/*
23722 * Node.js Buffer.concat()
23723 */
23724
23725#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23727 duk_hthread *thr;
23728 duk_hobject *h_arg;
23729 duk_int_t total_length = 0;
23730 duk_hbufferobject *h_bufobj;
23731 duk_hbufferobject *h_bufres;
23732 duk_hbuffer *h_val;
23733 duk_uint_t i, n;
23734 duk_uint8_t *p;
23735 duk_size_t space_left;
23736 duk_size_t copy_size;
23737
23738 thr = (duk_hthread *) ctx;
23739 DUK_UNREF(thr);
23740
23741 /* Node.js accepts only actual Arrays. */
23742 h_arg = duk_require_hobject(ctx, 0);
23744 return DUK_RET_TYPE_ERROR;
23745 }
23746
23747 /* Compute result length and validate argument buffers. */
23748 n = (duk_uint_t) duk_get_length(ctx, 0);
23749 for (i = 0; i < n; i++) {
23750 /* Neutered checks not necessary here: neutered buffers have
23751 * zero 'length' so we'll effectively skip them.
23752 */
23753 DUK_ASSERT_TOP(ctx, 2); /* [ array totalLength ] */
23754 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */
23755 h_bufobj = duk__require_bufobj_value(ctx, 2);
23756 DUK_ASSERT(h_bufobj != NULL);
23757 total_length += h_bufobj->length;
23758 duk_pop(ctx);
23759 }
23760 if (n == 1) {
23761 /* For the case n==1 Node.js doesn't seem to type check
23762 * the sole member but we do it before returning it.
23763 * For this case only the original buffer object is
23764 * returned (not a copy).
23765 */
23766 duk_get_prop_index(ctx, 0, 0);
23767 return 1;
23768 }
23769
23770 /* User totalLength overrides a computed length, but we'll check
23771 * every copy in the copy loop. Note that duk_to_uint() can
23772 * technically have arbitrary side effects so we need to recheck
23773 * the buffers in the copy loop.
23774 */
23775 if (!duk_is_undefined(ctx, 1) && n > 0) {
23776 /* For n == 0, Node.js ignores totalLength argument and
23777 * returns a zero length buffer.
23778 */
23779 total_length = duk_to_int(ctx, 1);
23780 }
23781 if (total_length < 0) {
23782 return DUK_RET_RANGE_ERROR;
23783 }
23784
23785 h_bufres = duk_push_bufferobject_raw(ctx,
23790 DUK_ASSERT(h_bufres != NULL);
23791
23792 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, total_length);
23793 DUK_ASSERT(p != NULL);
23794 space_left = total_length;
23795
23796 for (i = 0; i < n; i++) {
23797 DUK_ASSERT_TOP(ctx, 4); /* [ array totalLength bufres buf ] */
23798
23799 duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
23800 h_bufobj = duk__require_bufobj_value(ctx, 4);
23801 DUK_ASSERT(h_bufobj != NULL);
23802
23803 copy_size = h_bufobj->length;
23804 if (copy_size > space_left) {
23805 copy_size = space_left;
23806 }
23807
23808 if (h_bufobj->buf != NULL &&
23810 DUK_MEMCPY((void *) p,
23811 (const void *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj),
23812 copy_size);
23813 } else {
23814 /* Just skip, leaving zeroes in the result. */
23815 ;
23816 }
23817 p += copy_size;
23818 space_left -= copy_size;
23819
23820 duk_pop(ctx);
23821 }
23822
23823 h_val = duk_get_hbuffer(ctx, -1);
23824 DUK_ASSERT(h_val != NULL);
23825
23826 duk__set_bufobj_buffer(ctx, h_bufres, h_val);
23828
23829 duk_pop(ctx); /* pop plain buffer, now reachable through h_bufres */
23830
23831 return 1; /* return h_bufres */
23832}
23833#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
23835 DUK_UNREF(ctx);
23838#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
23841 * Shared readfield and writefield methods
23843 * The readfield/writefield methods need support for endianness and field
23844 * types. All offsets are byte based so no offset shifting is needed.
23846
23847#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23848/* Format of magic, bits:
23849 * 0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
23850 * 3: endianness: 0=little, 1=big
23851 * 4: signed: 1=yes, 0=no
23852 * 5: typedarray: 1=yes, 0=no
23853 */
23854#define DUK__FLD_8BIT 0
23855#define DUK__FLD_16BIT 1
23856#define DUK__FLD_32BIT 2
23857#define DUK__FLD_FLOAT 3
23858#define DUK__FLD_DOUBLE 4
23859#define DUK__FLD_VARINT 5
23860#define DUK__FLD_BIGENDIAN (1 << 3)
23861#define DUK__FLD_SIGNED (1 << 4)
23862#define DUK__FLD_TYPEDARRAY (1 << 5)
23863
23864/* XXX: split into separate functions for each field type? */
23866 duk_hthread *thr;
23868 duk_small_int_t magic_ftype;
23869 duk_small_int_t magic_bigendian;
23870 duk_small_int_t magic_signed;
23871 duk_small_int_t magic_typedarray;
23872 duk_small_int_t endswap;
23873 duk_hbufferobject *h_this;
23874 duk_bool_t no_assert;
23875 duk_int_t offset_signed;
23876 duk_uint_t offset;
23877 duk_uint_t buffer_length;
23878 duk_uint_t check_length;
23879 duk_uint8_t *buf;
23881
23882 thr = (duk_hthread *) ctx;
23883 DUK_UNREF(thr);
23884
23885 magic_ftype = magic & 0x0007;
23886 magic_bigendian = magic & 0x0008;
23887 magic_signed = magic & 0x0010;
23888 magic_typedarray = magic & 0x0020;
23889
23890 h_this = duk__require_bufobj_this(ctx);
23891 DUK_ASSERT(h_this != NULL);
23892 buffer_length = h_this->length;
23893
23894 /* [ offset noAssert ], when ftype != DUK__FLD_VARINT */
23895 /* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
23896 /* [ offset littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
23897
23898 /* Handle TypedArray vs. Node.js Buffer arg differences */
23899 if (magic_typedarray) {
23900 no_assert = 0;
23901#if defined(DUK_USE_INTEGER_LE)
23902 endswap = !duk_to_boolean(ctx, 1); /* 1=little endian */
23903#else
23904 endswap = duk_to_boolean(ctx, 1); /* 1=little endian */
23905#endif
23906 } else {
23907 no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
23908#if defined(DUK_USE_INTEGER_LE)
23909 endswap = magic_bigendian;
23910#else
23911 endswap = !magic_bigendian;
23912#endif
23913 }
23914
23915 /* Offset is coerced first to signed integer range and then to unsigned.
23916 * This ensures we can add a small byte length (1-8) to the offset in
23917 * bound checks and not wrap.
23918 */
23919 offset_signed = duk_to_int(ctx, 0);
23920 offset = (duk_uint_t) offset_signed;
23921 if (offset_signed < 0) {
23922 goto fail_bounds;
23923 }
23924
23925 DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
23926 "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
23927 "endswap=%d",
23928 (long) buffer_length, (long) offset, (int) no_assert,
23929 (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
23930 (int) (magic_signed >> 4), (int) endswap));
23931
23932 /* Update 'buffer_length' to be the effective, safe limit which
23933 * takes into account the underlying buffer. This value will be
23934 * potentially invalidated by any side effect.
23935 */
23936 check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
23937 DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
23938 (long) buffer_length, (long) check_length));
23939
23940 if (h_this->buf) {
23941 buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
23942 } else {
23943 /* Neutered. We could go into the switch-case safely with
23944 * buf == NULL because check_length == 0. To avoid scanbuild
23945 * warnings, fail directly instead.
23946 */
23947 DUK_ASSERT(check_length == 0);
23948 goto fail_neutered;
23949 }
23950 DUK_ASSERT(buf != NULL);
23951
23952 switch (magic_ftype) {
23953 case DUK__FLD_8BIT: {
23954 duk_uint8_t tmp;
23955 if (offset + 1U > check_length) {
23956 goto fail_bounds;
23957 }
23958 tmp = buf[offset];
23959 if (magic_signed) {
23960 duk_push_int(ctx, (duk_int_t) ((duk_int8_t) tmp));
23961 } else {
23962 duk_push_uint(ctx, (duk_uint_t) tmp);
23963 }
23964 break;
23965 }
23966 case DUK__FLD_16BIT: {
23967 duk_uint16_t tmp;
23968 if (offset + 2U > check_length) {
23969 goto fail_bounds;
23970 }
23971 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2);
23972 tmp = du.us[0];
23973 if (endswap) {
23974 tmp = DUK_BSWAP16(tmp);
23975 }
23976 if (magic_signed) {
23977 duk_push_int(ctx, (duk_int_t) ((duk_int16_t) tmp));
23978 } else {
23979 duk_push_uint(ctx, (duk_uint_t) tmp);
23980 }
23981 break;
23982 }
23983 case DUK__FLD_32BIT: {
23984 duk_uint32_t tmp;
23985 if (offset + 4U > check_length) {
23986 goto fail_bounds;
23987 }
23988 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
23989 tmp = du.ui[0];
23990 if (endswap) {
23991 tmp = DUK_BSWAP32(tmp);
23992 }
23993 if (magic_signed) {
23994 duk_push_int(ctx, (duk_int_t) ((duk_int32_t) tmp));
23995 } else {
23996 duk_push_uint(ctx, (duk_uint_t) tmp);
23997 }
23998 break;
23999 }
24000 case DUK__FLD_FLOAT: {
24001 duk_uint32_t tmp;
24002 if (offset + 4U > check_length) {
24003 goto fail_bounds;
24004 }
24005 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
24006 if (endswap) {
24007 tmp = du.ui[0];
24008 tmp = DUK_BSWAP32(tmp);
24009 du.ui[0] = tmp;
24010 }
24011 duk_push_number(ctx, (duk_double_t) du.f[0]);
24012 break;
24013 }
24014 case DUK__FLD_DOUBLE: {
24015 if (offset + 8U > check_length) {
24016 goto fail_bounds;
24017 }
24018 DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8);
24019 if (endswap) {
24021 }
24022 duk_push_number(ctx, (duk_double_t) du.d);
24023 break;
24024 }
24025 case DUK__FLD_VARINT: {
24026 /* Node.js Buffer variable width integer field. We don't really
24027 * care about speed here, so aim for shortest algorithm.
24028 */
24029 duk_int_t field_bytelen;
24030 duk_int_t i, i_step, i_end;
24031#if defined(DUK_USE_64BIT_OPS)
24032 duk_int64_t tmp;
24033 duk_small_uint_t shift_tmp;
24034#else
24035 duk_double_t tmp;
24036 duk_small_int_t highbyte;
24037#endif
24038 const duk_uint8_t *p;
24039
24040 field_bytelen = duk_get_int(ctx, 1); /* avoid side effects! */
24041 if (field_bytelen < 1 || field_bytelen > 6) {
24042 goto fail_field_length;
24043 }
24044 if (offset + (duk_uint_t) field_bytelen > check_length) {
24045 goto fail_bounds;
24046 }
24047 p = (const duk_uint8_t *) (buf + offset);
24048
24049 /* Slow gathering of value using either 64-bit arithmetic
24050 * or IEEE doubles if 64-bit types not available. Handling
24051 * of negative numbers is a bit non-obvious in both cases.
24052 */
24053
24054 if (magic_bigendian) {
24055 /* Gather in big endian */
24056 i = 0;
24057 i_step = 1;
24058 i_end = field_bytelen; /* one i_step over */
24059 } else {
24060 /* Gather in little endian */
24061 i = field_bytelen - 1;
24062 i_step = -1;
24063 i_end = -1; /* one i_step over */
24064 }
24065
24066#if defined(DUK_USE_64BIT_OPS)
24067 tmp = 0;
24068 do {
24069 DUK_ASSERT(i >= 0 && i < field_bytelen);
24070 tmp = (tmp << 8) + (duk_int64_t) p[i];
24071 i += i_step;
24072 } while (i != i_end);
24073
24074 if (magic_signed) {
24075 /* Shift to sign extend. */
24076 shift_tmp = 64 - (field_bytelen * 8);
24077 tmp = (tmp << shift_tmp) >> shift_tmp;
24078 }
24079
24080 duk_push_i64(ctx, tmp);
24081#else
24082 highbyte = p[i];
24083 if (magic_signed && (highbyte & 0x80) != 0) {
24084 /* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
24085 tmp = (duk_double_t) (highbyte - 256);
24086 } else {
24087 tmp = (duk_double_t) highbyte;
24088 }
24089 for (;;) {
24090 i += i_step;
24091 if (i == i_end) {
24092 break;
24093 }
24094 DUK_ASSERT(i >= 0 && i < field_bytelen);
24095 tmp = (tmp * 256.0) + (duk_double_t) p[i];
24096 }
24097
24098 duk_push_number(ctx, tmp);
24099#endif
24100 break;
24101 }
24102 default: { /* should never happen but default here */
24103 goto fail_bounds;
24104 }
24105 }
24106
24107 return 1;
24108
24109 fail_neutered:
24110 fail_field_length:
24111 fail_bounds:
24112 if (no_assert) {
24113 /* Node.js return value for noAssert out-of-bounds reads is
24114 * usually (but not always) NaN. Return NaN consistently.
24115 */
24116 duk_push_nan(ctx);
24117 return 1;
24118 }
24119
24120 return DUK_RET_RANGE_ERROR;
24121}
24122#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
24124 DUK_UNREF(ctx);
24126}
24127#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24128
24129#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24130/* XXX: split into separate functions for each field type? */
24132 duk_hthread *thr;
24134 duk_small_int_t magic_ftype;
24135 duk_small_int_t magic_bigendian;
24136 duk_small_int_t magic_signed;
24137 duk_small_int_t magic_typedarray;
24138 duk_small_int_t endswap;
24139 duk_hbufferobject *h_this;
24140 duk_bool_t no_assert;
24141 duk_int_t offset_signed;
24142 duk_uint_t offset;
24143 duk_uint_t buffer_length;
24144 duk_uint_t check_length;
24145 duk_uint8_t *buf;
24147 duk_int_t nbytes = 0;
24148
24149 thr = (duk_hthread *) ctx;
24150 DUK_UNREF(thr);
24151
24152 magic_ftype = magic & 0x0007;
24153 magic_bigendian = magic & 0x0008;
24154 magic_signed = magic & 0x0010;
24155 magic_typedarray = magic & 0x0020;
24156 DUK_UNREF(magic_signed);
24157
24158 h_this = duk__require_bufobj_this(ctx);
24159 DUK_ASSERT(h_this != NULL);
24160 buffer_length = h_this->length;
24161
24162 /* [ value offset noAssert ], when ftype != DUK__FLD_VARINT */
24163 /* [ value offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
24164 /* [ offset value littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
24165
24166 /* Handle TypedArray vs. Node.js Buffer arg differences */
24167 if (magic_typedarray) {
24168 no_assert = 0;
24169#if defined(DUK_USE_INTEGER_LE)
24170 endswap = !duk_to_boolean(ctx, 2); /* 1=little endian */
24171#else
24172 endswap = duk_to_boolean(ctx, 2); /* 1=little endian */
24173#endif
24174 duk_swap(ctx, 0, 1); /* offset/value order different from Node.js */
24175 } else {
24176 no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
24177#if defined(DUK_USE_INTEGER_LE)
24178 endswap = magic_bigendian;
24179#else
24180 endswap = !magic_bigendian;
24181#endif
24182 }
24183
24184 /* Offset is coerced first to signed integer range and then to unsigned.
24185 * This ensures we can add a small byte length (1-8) to the offset in
24186 * bound checks and not wrap.
24187 */
24188 offset_signed = duk_to_int(ctx, 1);
24189 offset = (duk_uint_t) offset_signed;
24190
24191 /* We need 'nbytes' even for a failed offset; return value must be
24192 * (offset + nbytes) even when write fails due to invalid offset.
24193 */
24194 if (magic_ftype != DUK__FLD_VARINT) {
24195 DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
24196 nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
24197 } else {
24198 nbytes = duk_get_int(ctx, 2);
24199 if (nbytes < 1 || nbytes > 6) {
24200 goto fail_field_length;
24201 }
24202 }
24203 DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
24204
24205 /* Now we can check offset validity. */
24206 if (offset_signed < 0) {
24207 goto fail_bounds;
24208 }
24209
24210 DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
24211 "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
24212 "endswap=%d",
24213 duk_get_tval(ctx, 0), (long) buffer_length, (long) offset, (int) no_assert,
24214 (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
24215 (int) (magic_signed >> 4), (int) endswap));
24216
24217 /* Coerce value to a number before computing check_length, so that
24218 * the field type specific coercion below can't have side effects
24219 * that would invalidate check_length.
24220 */
24221 duk_to_number(ctx, 0);
24222
24223 /* Update 'buffer_length' to be the effective, safe limit which
24224 * takes into account the underlying buffer. This value will be
24225 * potentially invalidated by any side effect.
24226 */
24227 check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
24228 DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
24229 (long) buffer_length, (long) check_length));
24230
24231 if (h_this->buf) {
24232 buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
24233 } else {
24234 /* Neutered. We could go into the switch-case safely with
24235 * buf == NULL because check_length == 0. To avoid scanbuild
24236 * warnings, fail directly instead.
24237 */
24238 DUK_ASSERT(check_length == 0);
24239 goto fail_neutered;
24240 }
24241 DUK_ASSERT(buf != NULL);
24242
24243 switch (magic_ftype) {
24244 case DUK__FLD_8BIT: {
24245 if (offset + 1U > check_length) {
24246 goto fail_bounds;
24247 }
24248 /* sign doesn't matter when writing */
24249 buf[offset] = (duk_uint8_t) duk_to_uint32(ctx, 0);
24250 break;
24251 }
24252 case DUK__FLD_16BIT: {
24253 duk_uint16_t tmp;
24254 if (offset + 2U > check_length) {
24255 goto fail_bounds;
24256 }
24257 tmp = (duk_uint16_t) duk_to_uint32(ctx, 0);
24258 if (endswap) {
24259 tmp = DUK_BSWAP16(tmp);
24260 }
24261 du.us[0] = tmp;
24262 /* sign doesn't matter when writing */
24263 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2);
24264 break;
24265 }
24266 case DUK__FLD_32BIT: {
24267 duk_uint32_t tmp;
24268 if (offset + 4U > check_length) {
24269 goto fail_bounds;
24270 }
24271 tmp = (duk_uint32_t) duk_to_uint32(ctx, 0);
24272 if (endswap) {
24273 tmp = DUK_BSWAP32(tmp);
24274 }
24275 du.ui[0] = tmp;
24276 /* sign doesn't matter when writing */
24277 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
24278 break;
24279 }
24280 case DUK__FLD_FLOAT: {
24281 duk_uint32_t tmp;
24282 if (offset + 4U > check_length) {
24283 goto fail_bounds;
24284 }
24285 du.f[0] = (duk_float_t) duk_to_number(ctx, 0);
24286 if (endswap) {
24287 tmp = du.ui[0];
24288 tmp = DUK_BSWAP32(tmp);
24289 du.ui[0] = tmp;
24290 }
24291 /* sign doesn't matter when writing */
24292 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
24293 break;
24294 }
24295 case DUK__FLD_DOUBLE: {
24296 if (offset + 8U > check_length) {
24297 goto fail_bounds;
24298 }
24299 du.d = (duk_double_t) duk_to_number(ctx, 0);
24300 if (endswap) {
24302 }
24303 /* sign doesn't matter when writing */
24304 DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8);
24305 break;
24306 }
24307 case DUK__FLD_VARINT: {
24308 /* Node.js Buffer variable width integer field. We don't really
24309 * care about speed here, so aim for shortest algorithm.
24310 */
24311 duk_int_t field_bytelen;
24312 duk_int_t i, i_step, i_end;
24313#if defined(DUK_USE_64BIT_OPS)
24314 duk_int64_t tmp;
24315#else
24316 duk_double_t tmp;
24317#endif
24318 duk_uint8_t *p;
24319
24320 field_bytelen = (duk_int_t) nbytes;
24321 if (offset + (duk_uint_t) field_bytelen > check_length) {
24322 goto fail_bounds;
24323 }
24324
24325 /* Slow writing of value using either 64-bit arithmetic
24326 * or IEEE doubles if 64-bit types not available. There's
24327 * no special sign handling when writing varints.
24328 */
24329
24330 if (magic_bigendian) {
24331 /* Write in big endian */
24332 i = field_bytelen; /* one i_step added at top of loop */
24333 i_step = -1;
24334 i_end = 0;
24335 } else {
24336 /* Write in little endian */
24337 i = -1; /* one i_step added at top of loop */
24338 i_step = 1;
24339 i_end = field_bytelen - 1;
24340 }
24341
24342 /* XXX: The duk_to_number() cast followed by integer coercion
24343 * is platform specific so NaN, +/- Infinity, and out-of-bounds
24344 * values result in platform specific output now.
24345 * See: test-bi-nodejs-buffer-proto-varint-special.js
24346 */
24347
24348#if defined(DUK_USE_64BIT_OPS)
24349 tmp = (duk_int64_t) duk_to_number(ctx, 0);
24350 p = (duk_uint8_t *) (buf + offset);
24351 do {
24352 i += i_step;
24353 DUK_ASSERT(i >= 0 && i < field_bytelen);
24354 p[i] = (duk_uint8_t) (tmp & 0xff);
24355 tmp = tmp >> 8; /* unnecessary shift for last byte */
24356 } while (i != i_end);
24357#else
24358 tmp = duk_to_number(ctx, 0);
24359 p = (duk_uint8_t *) (buf + offset);
24360 do {
24361 i += i_step;
24362 tmp = DUK_FLOOR(tmp);
24363 DUK_ASSERT(i >= 0 && i < field_bytelen);
24364 p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
24365 tmp = tmp / 256.0; /* unnecessary div for last byte */
24366 } while (i != i_end);
24367#endif
24368 break;
24369 }
24370 default: { /* should never happen but default here */
24371 goto fail_bounds;
24372 }
24373 }
24374
24375 /* Node.js Buffer: return offset + #bytes written (i.e. next
24376 * write offset).
24377 */
24378 if (magic_typedarray) {
24379 /* For TypedArrays 'undefined' return value is specified
24380 * by ES6 (matches V8).
24381 */
24382 return 0;
24383 }
24384 duk_push_uint(ctx, offset + nbytes);
24385 return 1;
24386
24387 fail_neutered:
24388 fail_field_length:
24389 fail_bounds:
24390 if (no_assert) {
24391 /* Node.js return value for failed writes is offset + #bytes
24392 * that would have been written.
24393 */
24394 /* XXX: for negative input offsets, 'offset' will be a large
24395 * positive value so the result here is confusing.
24396 */
24397 if (magic_typedarray) {
24398 return 0;
24399 }
24400 duk_push_uint(ctx, offset + nbytes);
24401 return 1;
24402 }
24403 return DUK_RET_RANGE_ERROR;
24404}
24405#else /* DUK_USE_BUFFEROBJECT_SUPPORT */
24407 DUK_UNREF(ctx);
24409}
24410#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24411
24412#undef DUK__FLD_8BIT
24413#undef DUK__FLD_16BIT
24414#undef DUK__FLD_32BIT
24415#undef DUK__FLD_FLOAT
24416#undef DUK__FLD_DOUBLE
24417#undef DUK__FLD_VARINT
24418#undef DUK__FLD_BIGENDIAN
24419#undef DUK__FLD_SIGNED
24420#undef DUK__FLD_TYPEDARRAY
24421#line 1 "duk_bi_date.c"
24422/*
24423 * Date built-ins
24424 *
24425 * Unlike most built-ins, Date has some platform dependencies for getting
24426 * UTC time, converting between UTC and local time, and parsing and
24427 * formatting time values. These are all abstracted behind DUK_USE_xxx
24428 * config options. There are built-in platform specific providers for
24429 * POSIX and Windows, but external providers can also be used.
24430 *
24431 * See doc/datetime.rst.
24432 *
24433 */
24435/* include removed: duk_internal.h */
24436
24437/*
24438 * Forward declarations
24439 */
24440
24446/*
24447 * Other file level defines
24448 */
24449
24450/* Debug macro to print all parts and dparts (used manually because of debug level). */
24451#define DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts) do { \
24452 DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
24453 (long) (parts)[0], (long) (parts)[1], \
24454 (long) (parts)[2], (long) (parts)[3], \
24455 (long) (parts)[4], (long) (parts)[5], \
24456 (long) (parts)[6], (long) (parts)[7], \
24457 (double) (dparts)[0], (double) (dparts)[1], \
24458 (double) (dparts)[2], (double) (dparts)[3], \
24459 (double) (dparts)[4], (double) (dparts)[5], \
24460 (double) (dparts)[6], (double) (dparts)[7])); \
24461 } while (0)
24462#define DUK__DPRINT_PARTS(parts) do { \
24463 DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
24464 (long) (parts)[0], (long) (parts)[1], \
24465 (long) (parts)[2], (long) (parts)[3], \
24466 (long) (parts)[4], (long) (parts)[5], \
24467 (long) (parts)[6], (long) (parts)[7])); \
24468 } while (0)
24469#define DUK__DPRINT_DPARTS(dparts) do { \
24470 DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
24471 (double) (dparts)[0], (double) (dparts)[1], \
24472 (double) (dparts)[2], (double) (dparts)[3], \
24473 (double) (dparts)[4], (double) (dparts)[5], \
24474 (double) (dparts)[6], (double) (dparts)[7])); \
24475 } while (0)
24476
24477/* Equivalent year for DST calculations outside [1970,2038[ range, see
24478 * E5 Section 15.9.1.8. Equivalent year has the same leap-year-ness and
24479 * starts with the same weekday on Jan 1.
24480 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
24481 */
24482#define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
24483DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
24484#if 1
24485 /* This is based on V8 EquivalentYear() algorithm (see src/genequivyear.py):
24486 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
24487 */
24488
24489 /* non-leap year: sunday, monday, ... */
24490 DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
24491 DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
24492
24493 /* leap year: sunday, monday, ... */
24494 DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
24495 DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
24496#endif
24497
24498#if 0
24499 /* This is based on Rhino EquivalentYear() algorithm:
24500 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
24501 */
24503 /* non-leap year: sunday, monday, ... */
24504 DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
24505 DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
24507 /* leap year: sunday, monday, ... */
24508 DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
24509 DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
24510#endif
24512#undef DUK__YEAR
24514/*
24515 * ISO 8601 subset parser.
24518/* Parser part count. */
24519#define DUK__NUM_ISO8601_PARSER_PARTS 9
24521/* Parser part indices. */
24522#define DUK__PI_YEAR 0
24523#define DUK__PI_MONTH 1
24524#define DUK__PI_DAY 2
24525#define DUK__PI_HOUR 3
24526#define DUK__PI_MINUTE 4
24527#define DUK__PI_SECOND 5
24528#define DUK__PI_MILLISECOND 6
24529#define DUK__PI_TZHOUR 7
24530#define DUK__PI_TZMINUTE 8
24532/* Parser part masks. */
24533#define DUK__PM_YEAR (1 << DUK__PI_YEAR)
24534#define DUK__PM_MONTH (1 << DUK__PI_MONTH)
24535#define DUK__PM_DAY (1 << DUK__PI_DAY)
24536#define DUK__PM_HOUR (1 << DUK__PI_HOUR)
24537#define DUK__PM_MINUTE (1 << DUK__PI_MINUTE)
24538#define DUK__PM_SECOND (1 << DUK__PI_SECOND)
24539#define DUK__PM_MILLISECOND (1 << DUK__PI_MILLISECOND)
24540#define DUK__PM_TZHOUR (1 << DUK__PI_TZHOUR)
24541#define DUK__PM_TZMINUTE (1 << DUK__PI_TZMINUTE)
24543/* Parser separator indices. */
24544#define DUK__SI_PLUS 0
24545#define DUK__SI_MINUS 1
24546#define DUK__SI_T 2
24547#define DUK__SI_SPACE 3
24548#define DUK__SI_COLON 4
24549#define DUK__SI_PERIOD 5
24550#define DUK__SI_Z 6
24551#define DUK__SI_NUL 7
24552
24553/* Parser separator masks. */
24554#define DUK__SM_PLUS (1 << DUK__SI_PLUS)
24555#define DUK__SM_MINUS (1 << DUK__SI_MINUS)
24556#define DUK__SM_T (1 << DUK__SI_T)
24557#define DUK__SM_SPACE (1 << DUK__SI_SPACE)
24558#define DUK__SM_COLON (1 << DUK__SI_COLON)
24559#define DUK__SM_PERIOD (1 << DUK__SI_PERIOD)
24560#define DUK__SM_Z (1 << DUK__SI_Z)
24561#define DUK__SM_NUL (1 << DUK__SI_NUL)
24563/* Rule control flags. */
24564#define DUK__CF_NEG (1 << 0) /* continue matching, set neg_tzoffset flag */
24565#define DUK__CF_ACCEPT (1 << 1) /* accept string */
24566#define DUK__CF_ACCEPT_NUL (1 << 2) /* accept string if next char is NUL (otherwise reject) */
24567
24568#define DUK__PACK_RULE(partmask,sepmask,nextpart,flags) \
24569 ((duk_uint32_t) (partmask) + \
24570 (((duk_uint32_t) (sepmask)) << 9) + \
24571 (((duk_uint32_t) (nextpart)) << 17) + \
24572 (((duk_uint32_t) (flags)) << 21))
24573
24574#define DUK__UNPACK_RULE(rule,var_nextidx,var_flags) do { \
24575 (var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
24576 (var_flags) = (duk_small_uint_t) ((rule) >> 21); \
24577 } while (0)
24578
24579#define DUK__RULE_MASK_PART_SEP 0x1ffffUL
24580
24581/* Matching separator index is used in the control table */
24582DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
24583 DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
24584 DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
24585};
24586
24587/* Rule table: first matching rule is used to determine what to do next. */
24588DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
24600
24601 /* Note1: the specification doesn't require matching a time form with
24602 * just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
24603 *
24604 * Note2: the specification doesn't require matching a timezone offset
24605 * with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
24606 */
24607};
24608
24612 duk_double_t d;
24613 const duk_uint8_t *p;
24614 duk_small_uint_t part_idx = 0;
24615 duk_int_t accum = 0;
24616 duk_small_uint_t ndigits = 0;
24617 duk_bool_t neg_year = 0;
24618 duk_bool_t neg_tzoffset = 0;
24621
24622 /* During parsing, month and day are one-based; set defaults here. */
24623 DUK_MEMZERO(parts, sizeof(parts));
24624 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */
24625 parts[DUK_DATE_IDX_MONTH] = 1;
24626 parts[DUK_DATE_IDX_DAY] = 1;
24627
24628 /* Special handling for year sign. */
24629 p = (const duk_uint8_t *) str;
24630 ch = p[0];
24631 if (ch == DUK_ASC_PLUS) {
24632 p++;
24633 } else if (ch == DUK_ASC_MINUS) {
24634 neg_year = 1;
24635 p++;
24636 }
24637
24638 for (;;) {
24639 ch = *p++;
24640 DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
24641 (long) part_idx, (long) ch,
24642 (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
24643
24644 if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
24645 if (ndigits >= 9) {
24646 DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
24647 goto reject;
24648 }
24649 if (part_idx == DUK__PI_MILLISECOND /*msec*/ && ndigits >= 3) {
24650 /* ignore millisecond fractions after 3 */
24651 } else {
24652 accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
24653 ndigits++;
24654 }
24655 } else {
24656 duk_uint_fast32_t match_val;
24657 duk_small_int_t sep_idx;
24658
24659 if (ndigits <= 0) {
24660 goto reject;
24661 }
24662 if (part_idx == DUK__PI_MILLISECOND) {
24663 /* complete the millisecond field */
24664 while (ndigits < 3) {
24665 accum *= 10;
24666 ndigits++;
24667 }
24668 }
24669 parts[part_idx] = accum;
24670 DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
24671
24672 accum = 0;
24673 ndigits = 0;
24674
24675 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
24676 if (duk__parse_iso8601_seps[i] == ch) {
24677 break;
24678 }
24679 }
24680 if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
24681 DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
24682 goto reject;
24683 }
24684
24685 sep_idx = i;
24686 match_val = (1UL << part_idx) + (1UL << (sep_idx + 9)); /* match against rule part/sep bits */
24687
24688 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
24690 duk_small_uint_t nextpart;
24691 duk_small_uint_t cflags;
24692
24693 DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
24694 (long) part_idx, (long) sep_idx,
24695 (unsigned long) match_val, (unsigned long) rule));
24696
24697 if ((rule & match_val) != match_val) {
24698 continue;
24699 }
24700
24701 DUK__UNPACK_RULE(rule, nextpart, cflags);
24702
24703 DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
24704 "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
24705 (long) part_idx, (long) sep_idx,
24706 (unsigned long) match_val, (unsigned long) rule,
24707 (long) nextpart, (unsigned long) cflags));
24708
24709 if (cflags & DUK__CF_NEG) {
24710 neg_tzoffset = 1;
24711 }
24712
24713 if (cflags & DUK__CF_ACCEPT) {
24714 goto accept;
24715 }
24716
24717 if (cflags & DUK__CF_ACCEPT_NUL) {
24718 DUK_ASSERT(*(p - 1) != (char) 0);
24719 if (*p == DUK_ASC_NUL) {
24720 goto accept;
24721 }
24722 goto reject;
24723 }
24724
24725 part_idx = nextpart;
24726 break;
24727 } /* rule match */
24728
24729 if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
24730 DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
24731 goto reject;
24732 }
24733
24734 if (ch == 0) {
24735 /* This shouldn't be necessary, but check just in case
24736 * to avoid any chance of overruns.
24737 */
24738 DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
24739 goto reject;
24740 }
24741 } /* if-digit-else-ctrl */
24742 } /* char loop */
24743
24744 /* We should never exit the loop above. */
24746
24747 reject:
24748 DUK_DDD(DUK_DDDPRINT("reject"));
24749 return 0;
24750
24751 accept:
24752 DUK_DDD(DUK_DDDPRINT("accept"));
24753
24754 /* Apply timezone offset to get the main parts in UTC */
24755 if (neg_year) {
24756 parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
24757 }
24758 if (neg_tzoffset) {
24759 parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
24760 parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
24761 } else {
24762 parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
24763 parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
24764 }
24765 parts[DUK__PI_MONTH] -= 1; /* zero-based month */
24766 parts[DUK__PI_DAY] -= 1; /* zero-based day */
24767
24768 /* Use double parts, they tolerate unnormalized time.
24769 *
24770 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
24771 * on purpose. It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
24772 * but will make the value initialized just in case, and avoid any
24773 * potential for Valgrind issues.
24774 */
24775 for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
24776 DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
24777 dparts[i] = parts[i];
24778 }
24779
24780 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
24781 duk_push_number(ctx, d);
24782 return 1;
24783}
24784
24785/*
24786 * Date/time parsing helper.
24788 * Parse a datetime string into a time value. We must first try to parse
24789 * the input according to the standard format in E5.1 Section 15.9.1.15.
24790 * If that fails, we can try to parse using custom parsing, which can
24791 * either be platform neutral (custom code) or platform specific (using
24792 * existing platform API calls).
24793 *
24794 * Note in particular that we must parse whatever toString(), toUTCString(),
24795 * and toISOString() can produce; see E5.1 Section 15.9.4.2.
24796 *
24797 * Returns 1 to allow tail calling.
24798 *
24799 * There is much room for improvement here with respect to supporting
24800 * alternative datetime formats. For instance, V8 parses '2012-01-01' as
24801 * UTC and '2012/01/01' as local time.
24802 */
24803
24804DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
24805 /* XXX: there is a small risk here: because the ISO 8601 parser is
24806 * very loose, it may end up parsing some datetime values which
24807 * would be better parsed with a platform specific parser.
24808 */
24809
24810 DUK_ASSERT(str != NULL);
24811 DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
24812
24813 if (duk__parse_string_iso8601_subset(ctx, str) != 0) {
24814 return 1;
24815 }
24816
24817#if defined(DUK_USE_DATE_PARSE_STRING)
24818 /* Contract, either:
24819 * - Push value on stack and return 1
24820 * - Don't push anything on stack and return 0
24821 */
24822
24823 if (DUK_USE_DATE_PARSE_STRING(ctx, str) != 0) {
24824 return 1;
24825 }
24826#else
24827 /* No platform-specific parsing, this is not an error. */
24828#endif
24829
24830 duk_push_nan(ctx);
24831 return 1;
24832}
24833
24834/*
24835 * Calendar helpers
24836 *
24837 * Some helpers are used for getters and can operate on normalized values
24838 * which can be represented with 32-bit signed integers. Other helpers are
24839 * needed by setters and operate on un-normalized double values, must watch
24840 * out for non-finite numbers etc.
24841 */
24842
24844 (duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
24845 (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
24846 (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
24847};
24848
24849/* Maximum iteration count for computing UTC-to-local time offset when
24850 * creating an Ecmascript time value from local parts.
24851 */
24852#define DUK__LOCAL_TZOFFSET_MAXITER 4
24853
24854/* Because 'day since epoch' can be negative and is used to compute weekday
24855 * using a modulo operation, add this multiple of 7 to avoid negative values
24856 * when year is below 1970 epoch. Ecmascript time values are restricted to
24857 * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
24858 * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
24859 */
24860#define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */
24861
24863 if ((year % 4) != 0) {
24864 return 0;
24865 }
24866 if ((year % 100) != 0) {
24867 return 1;
24868 }
24869 if ((year % 400) != 0) {
24884 return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
24885}
24888 if (!DUK_ISFINITE(x)) {
24889 return DUK_DOUBLE_NAN;
24890 }
24891
24893 return DUK_DOUBLE_NAN;
24894 }
24895
24897
24898 /* Here we'd have the option to normalize -0 to +0. */
24899 return x;
24901
24902/* Integer division which floors also negative values correctly. */
24904 DUK_ASSERT(b > 0);
24905 if (a >= 0) {
24906 return a / b;
24907 } else {
24908 /* e.g. a = -4, b = 5 --> -4 - 5 + 1 / 5 --> -8 / 5 --> -1
24909 * a = -5, b = 5 --> -5 - 5 + 1 / 5 --> -9 / 5 --> -1
24910 * a = -6, b = 5 --> -6 - 5 + 1 / 5 --> -10 / 5 --> -2
24912 return (a - b + 1) / b;
24913 }
24914}
24915
24916/* Compute day number of the first day of a given year. */
24918 /* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
24919 * values, but is incorrect for negative ones.
24920 */
24921 return 365 * (year - 1970)
24922 + duk__div_floor(year - 1969, 4)
24923 - duk__div_floor(year - 1901, 100)
24924 + duk__div_floor(year - 1601, 400);
24925}
24926
24927/* Given a day number, determine year and day-within-year. */
24929 duk_int_t year;
24930 duk_int_t diff_days;
24931
24932 /* estimate year upwards (towards positive infinity), then back down;
24933 * two iterations should be enough
24934 */
24935
24936 if (day >= 0) {
24937 year = 1970 + day / 365;
24938 } else {
24939 year = 1970 + day / 366;
24940 }
24941
24942 for (;;) {
24943 diff_days = duk__day_from_year(year) - day;
24944 DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
24945 if (diff_days <= 0) {
24946 DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */
24947 *out_day_within_year = -diff_days;
24948 DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
24949 (long) year, (long) *out_day_within_year));
24950 DUK_ASSERT(*out_day_within_year >= 0);
24951 DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
24952 return year;
24953 }
24954
24955 /* Note: this is very tricky; we must never 'overshoot' the
24956 * correction downwards.
24957 */
24958 year -= 1 + (diff_days - 1) / 366; /* conservative */
24959 }
24960}
24961
24962/* Given a (year, month, day-within-month) triple, compute day number.
24963 * The input triple is un-normalized and may contain non-finite values.
24964 */
24966 duk_int_t day_num;
24967 duk_bool_t is_leap;
24968 duk_small_int_t i, n;
24969
24970 /* Assume that year, month, day are all coerced to whole numbers.
24971 * They may also be NaN or infinity, in which case this function
24972 * must return NaN or infinity to ensure time value becomes NaN.
24973 * If 'day' is NaN, the final return will end up returning a NaN,
24974 * so it doesn't need to be checked here.
24975 */
24976
24977 if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
24978 return DUK_DOUBLE_NAN;
24979 }
24980
24981 year += DUK_FLOOR(month / 12.0);
24982
24983 month = DUK_FMOD(month, 12.0);
24984 if (month < 0.0) {
24985 /* handle negative values */
24986 month += 12.0;
24987 }
24988
24989 /* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
24990 * does not normalize the day-of-month (nor check whether or not
24991 * it is finite) because it's not necessary for finding the day
24992 * number which matches the (year,month) pair.
24993 *
24994 * We assume that duk__day_from_year() is exact here.
24995 *
24996 * Without an explicit infinity / NaN check in the beginning,
24997 * day_num would be a bogus integer here.
24998 *
24999 * It's possible for 'year' to be out of integer range here.
25000 * If so, we need to return NaN without integer overflow.
25001 * This fixes test-bug-setyear-overflow.js.
25002 */
25003
25005 DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
25006 return DUK_DOUBLE_NAN;
25007 }
25008 day_num = duk__day_from_year((duk_int_t) year);
25009 is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
25011 n = (duk_small_int_t) month;
25012 for (i = 0; i < n; i++) {
25013 day_num += duk__days_in_month[i];
25014 if (i == 1 && is_leap) {
25015 day_num++;
25016 }
25017 }
25018
25019 /* If 'day' is NaN, returns NaN. */
25020 return (duk_double_t) day_num + day;
25021}
25022
25023/* Split time value into parts. The time value is assumed to be an internal
25024 * one, i.e. finite, no fractions. Possible local time adjustment has already
25025 * been applied when reading the time value.
25026 */
25028 duk_double_t d1, d2;
25029 duk_int_t t1, t2;
25030 duk_int_t day_since_epoch;
25031 duk_int_t year; /* does not fit into 16 bits */
25032 duk_small_int_t day_in_year;
25033 duk_small_int_t month;
25034 duk_small_int_t day;
25035 duk_small_int_t dim;
25036 duk_int_t jan1_since_epoch;
25037 duk_small_int_t jan1_weekday;
25038 duk_int_t equiv_year;
25040 duk_bool_t is_leap;
25041 duk_small_int_t arridx;
25042
25043 DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */
25044 DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions in internal time */
25045
25046 /* The timevalue must be in valid Ecmascript range, but since a local
25047 * time offset can be applied, we need to allow a +/- 24h leeway to
25048 * the value. In other words, although the UTC time is within the
25049 * Ecmascript range, the local part values can be just outside of it.
25050 */
25053
25054 /* these computations are guaranteed to be exact for the valid
25055 * E5 time value range, assuming milliseconds without fractions.
25056 */
25057 d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
25058 if (d1 < 0.0) {
25059 /* deal with negative values */
25061 }
25062 d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
25063 DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
25064 /* now expected to fit into a 32-bit integer */
25065 t1 = (duk_int_t) d1;
25066 t2 = (duk_int_t) d2;
25067 day_since_epoch = t2;
25068 DUK_ASSERT((duk_double_t) t1 == d1);
25069 DUK_ASSERT((duk_double_t) t2 == d2);
25070
25071 /* t1 = milliseconds within day (fits 32 bit)
25072 * t2 = day number from epoch (fits 32 bit, may be negative)
25073 */
25074
25075 parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
25076 parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
25077 parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
25078 parts[DUK_DATE_IDX_HOUR] = t1;
25079 DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
25080 DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
25081 DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
25082 DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
25083
25084 DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
25085 (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
25086 (long) parts[DUK_DATE_IDX_HOUR],
25087 (long) parts[DUK_DATE_IDX_MINUTE],
25088 (long) parts[DUK_DATE_IDX_SECOND],
25089 (long) parts[DUK_DATE_IDX_MILLISECOND]));
25090
25091 /* This assert depends on the input parts representing time inside
25092 * the Ecmascript range.
25093 */
25095 parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
25096 DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
25097
25098 year = duk__year_from_day(t2, &day_in_year);
25099 day = day_in_year;
25100 is_leap = duk_bi_date_is_leap_year(year);
25101 for (month = 0; month < 12; month++) {
25102 dim = duk__days_in_month[month];
25103 if (month == 1 && is_leap) {
25104 dim++;
25105 }
25106 DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
25107 (long) month, (long) dim, (long) day));
25108 if (day < dim) {
25109 break;
25110 }
25111 day -= dim;
25112 }
25113 DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
25114 DUK_ASSERT(month >= 0 && month <= 11);
25115 DUK_ASSERT(day >= 0 && day <= 31);
25116
25117 /* Equivalent year mapping, used to avoid DST trouble when platform
25118 * may fail to provide reasonable DST answers for dates outside the
25119 * ordinary range (e.g. 1970-2038). An equivalent year has the same
25120 * leap-year-ness as the original year and begins on the same weekday
25121 * (Jan 1).
25122 *
25123 * The year 2038 is avoided because there seem to be problems with it
25124 * on some platforms. The year 1970 is also avoided as there were
25125 * practical problems with it; an equivalent year is used for it too,
25126 * which breaks some DST computations for 1970 right now, see e.g.
25127 * test-bi-date-tzoffset-brute-fi.js.
25128 */
25129 if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
25130 DUK_ASSERT(is_leap == 0 || is_leap == 1);
25131
25132 jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */
25133 DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
25134 jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
25135 DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
25136 arridx = jan1_weekday;
25137 if (is_leap) {
25138 arridx += 7;
25139 }
25140 DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
25141
25142 equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
25143 year = equiv_year;
25144 DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
25145 "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
25146 (long) year, (long) day_in_year, (long) day_since_epoch,
25147 (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
25148 }
25149
25150 parts[DUK_DATE_IDX_YEAR] = year;
25151 parts[DUK_DATE_IDX_MONTH] = month;
25152 parts[DUK_DATE_IDX_DAY] = day;
25153
25154 if (flags & DUK_DATE_FLAG_ONEBASED) {
25155 parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */
25156 parts[DUK_DATE_IDX_DAY]++; /* -""- */
25157 }
25158
25159 if (dparts != NULL) {
25160 for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
25161 dparts[i] = (duk_double_t) parts[i];
25162 }
25163 }
25164}
25165
25166/* Compute time value from (double) parts. The parts can be either UTC
25167 * or local time; if local, they need to be (conceptually) converted into
25168 * UTC time. The parts may represent valid or invalid time, and may be
25169 * wildly out of range (but may cancel each other and still come out in
25170 * the valid Date range).
25171 */
25173#if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
25174 /* See comments below on MakeTime why these are volatile. */
25175 volatile duk_double_t tmp_time;
25176 volatile duk_double_t tmp_day;
25177 volatile duk_double_t d;
25178#else
25179 duk_double_t tmp_time;
25180 duk_double_t tmp_day;
25181 duk_double_t d;
25182#endif
25184 duk_int_t tzoff, tzoffprev1, tzoffprev2;
25185
25186 /* Expects 'this' at top of stack on entry. */
25187
25188 /* Coerce all finite parts with ToInteger(). ToInteger() must not
25189 * be called for NaN/Infinity because it will convert e.g. NaN to
25190 * zero. If ToInteger() has already been called, this has no side
25191 * effects and is idempotent.
25192 *
25193 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
25194 * issues if the value is uninitialized.
25195 */
25196 for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
25197 /* SCANBUILD: scan-build complains here about assigned value
25198 * being garbage or undefined. This is correct but operating
25199 * on undefined values has no ill effect and is ignored by the
25200 * caller in the case where this happens.
25201 */
25202 d = dparts[i];
25203 if (DUK_ISFINITE(d)) {
25204 dparts[i] = duk_js_tointeger_number(d);
25205 }
25206 }
25207
25208 /* Use explicit steps in computation to try to ensure that
25209 * computation happens with intermediate results coerced to
25210 * double values (instead of using something more accurate).
25211 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
25212 * rules (= Ecmascript '+' and '*' operators).
25213 *
25214 * Without 'volatile' even this approach fails on some platform
25215 * and compiler combinations. For instance, gcc 4.8.1 on Ubuntu
25216 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
25217 * would fail because of some optimizations when computing tmp_time
25218 * (MakeTime below). Adding 'volatile' to tmp_time solved this
25219 * particular problem (annoyingly, also adding debug prints or
25220 * running the executable under valgrind hides it).
25221 */
25222
25223 /* MakeTime */
25224 tmp_time = 0.0;
25225 tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
25226 tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
25227 tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
25228 tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
25229
25230 /* MakeDay */
25231 tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
25232
25233 /* MakeDate */
25234 d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
25235
25236 DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
25237 (double) tmp_time, (double) tmp_day, (double) d));
25238
25239 /* Optional UTC conversion. */
25240 if (flags & DUK_DATE_FLAG_LOCALTIME) {
25241 /* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
25242 * time value computed from UTC parts. At this point we only
25243 * have 'd' which is a time value computed from local parts, so
25244 * it is off by the UTC-to-local time offset which we don't know
25245 * yet. The current solution for computing the UTC-to-local
25246 * time offset is to iterate a few times and detect a fixed
25247 * point or a two-cycle loop (or a sanity iteration limit),
25248 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
25249 *
25250 * E5.1 Section 15.9.1.9:
25251 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
25252 *
25253 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
25254 */
25255
25256#if 0
25257 /* Old solution: don't iterate, incorrect */
25258 tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
25259 DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
25260 d -= tzoff * 1000L;
25261 DUK_UNREF(tzoffprev1);
25262 DUK_UNREF(tzoffprev2);
25263#endif
25264
25265 /* Iteration solution */
25266 tzoff = 0;
25267 tzoffprev1 = 999999999L; /* invalid value which never matches */
25268 for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
25269 tzoffprev2 = tzoffprev1;
25270 tzoffprev1 = tzoff;
25271 tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
25272 DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
25273 (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25274 if (tzoff == tzoffprev1) {
25275 DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
25276 (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25277 break;
25278 } else if (tzoff == tzoffprev2) {
25279 /* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
25280 * In these cases, favor a higher tzoffset to get a consistent
25281 * result which is independent of iteration count. Not sure if
25282 * this is a generically correct solution.
25283 */
25284 DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
25285 (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25286 if (tzoffprev1 > tzoff) {
25287 tzoff = tzoffprev1;
25288 }
25289 break;
25290 }
25291 }
25292 DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
25293 d -= tzoff * 1000L;
25294 }
25295
25296 /* TimeClip(), which also handles Infinity -> NaN conversion */
25297 d = duk__timeclip(d);
25298
25299 return d;
25300}
25301
25302/*
25303 * API oriented helpers
25304 */
25305
25306/* Push 'this' binding, check that it is a Date object; then push the
25307 * internal time value. At the end, stack is: [ ... this timeval ].
25308 * Returns the time value. Local time adjustment is done if requested.
25309 */
25311 duk_hthread *thr = (duk_hthread *) ctx;
25312 duk_hobject *h;
25313 duk_double_t d;
25314 duk_int_t tzoffset = 0;
25315
25316 duk_push_this(ctx);
25317 h = duk_get_hobject(ctx, -1); /* XXX: getter with class check, useful in built-ins */
25319 DUK_ERROR_TYPE(thr, "expected Date");
25320 }
25321
25323 d = duk_to_number(ctx, -1);
25324 duk_pop(ctx);
25325
25326 if (DUK_ISNAN(d)) {
25327 if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
25328 d = 0.0;
25329 }
25331 DUK_ERROR_RANGE(thr, "Invalid Date");
25332 }
25333 }
25334 /* if no NaN handling flag, may still be NaN here, but not Inf */
25336
25337 if (flags & DUK_DATE_FLAG_LOCALTIME) {
25338 /* Note: DST adjustment is determined using UTC time.
25339 * If 'd' is NaN, tzoffset will be 0.
25340 */
25341 tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */
25342 d += tzoffset * 1000L;
25344 if (out_tzoffset) {
25345 *out_tzoffset = tzoffset;
25346 }
25347
25348 /* [ ... this ] */
25349 return d;
25350}
25351
25353 return duk__push_this_get_timeval_tzoffset(ctx, flags, NULL);
25354}
25355
25356/* Set timeval to 'this' from dparts, push the new time value onto the
25357 * value stack and return 1 (caller can then tail call us). Expects
25358 * the value stack to contain 'this' on the stack top.
25359 */
25361 duk_double_t d;
25362
25363 /* [ ... this ] */
25364
25365 d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
25366 duk_push_number(ctx, d); /* -> [ ... this timeval_new ] */
25367 duk_dup_top(ctx); /* -> [ ... this timeval_new timeval_new ] */
25369
25370 /* stack top: new time value, return 1 to allow tail calls */
25371 return 1;
25372}
25373
25374/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
25375DUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {
25376 char yearstr[8]; /* "-123456\0" */
25377 char tzstr[8]; /* "+11:22\0" */
25378 char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
25379
25380 DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
25381 DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
25382 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
25383
25384 /* Note: %06d for positive value, %07d for negative value to include
25385 * sign and 6 digits.
25386 */
25387 DUK_SNPRINTF(yearstr,
25388 sizeof(yearstr),
25389 (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
25390 ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
25391 (long) parts[DUK_DATE_IDX_YEAR]);
25392 yearstr[sizeof(yearstr) - 1] = (char) 0;
25393
25394 if (flags & DUK_DATE_FLAG_LOCALTIME) {
25395 /* tzoffset seconds are dropped; 16 bits suffice for
25396 * time offset in minutes
25397 */
25398 if (tzoffset >= 0) {
25399 duk_small_int_t tmp = tzoffset / 60;
25400 DUK_SNPRINTF(tzstr, sizeof(tzstr), "+%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
25401 } else {
25402 duk_small_int_t tmp = -tzoffset / 60;
25403 DUK_SNPRINTF(tzstr, sizeof(tzstr), "-%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
25404 }
25405 tzstr[sizeof(tzstr) - 1] = (char) 0;
25406 } else {
25407 tzstr[0] = DUK_ASC_UC_Z;
25408 tzstr[1] = (char) 0;
25409 }
25410
25411 /* Unlike year, the other parts fit into 16 bits so %d format
25412 * is portable.
25413 */
25414 if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
25415 DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
25416 (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
25417 (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
25418 (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
25419 } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
25420 DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
25421 (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
25422 } else {
25424 DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
25425 (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
25426 (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
25427 (const char *) tzstr);
25428 }
25429}
25430
25431/* Helper for string conversion calls: check 'this' binding, get the
25432 * internal time value, and format date and/or time in a few formats.
25433 * Return value allows tail calls.
25434 */
25436 duk_double_t d;
25438 duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */
25439 duk_bool_t rc;
25440 duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
25441
25442 DUK_UNREF(rc); /* unreferenced with some options */
25443
25444 d = duk__push_this_get_timeval_tzoffset(ctx, flags, &tzoffset);
25445 if (DUK_ISNAN(d)) {
25447 return 1;
25448 }
25450
25451 /* formatters always get one-based month/day-of-month */
25453 DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
25454 DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
25455
25456 if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
25457 /* try locale specific formatter; if it refuses to format the
25458 * string, fall back to an ISO 8601 formatted value in local
25459 * time.
25460 */
25461#if defined(DUK_USE_DATE_FORMAT_STRING)
25462 /* Contract, either:
25463 * - Push string to value stack and return 1
25464 * - Don't push anything and return 0
25465 */
25466
25467 rc = DUK_USE_DATE_FORMAT_STRING(ctx, parts, tzoffset, flags);
25468 if (rc != 0) {
25469 return 1;
25470 }
25471#else
25472 /* No locale specific formatter; this is OK, we fall back
25473 * to ISO 8601.
25475#endif
25476 }
25477
25478 /* Different calling convention than above used because the helper
25479 * is shared.
25480 */
25481 duk__format_parts_iso8601(parts, tzoffset, flags, buf);
25482 duk_push_string(ctx, (const char *) buf);
25483 return 1;
25484}
25485
25486/* Helper for component getter calls: check 'this' binding, get the
25487 * internal time value, split it into parts (either as UTC time or
25488 * local time), push a specified component as a return value to the
25489 * value stack and return 1 (caller can then tail call us).
25490 */
25492 duk_double_t d;
25494 duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
25495
25496 DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */
25498
25499 d = duk__push_this_get_timeval(ctx, flags_and_idx);
25500 if (DUK_ISNAN(d)) {
25501 duk_push_nan(ctx);
25502 return 1;
25503 }
25505
25506 duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */
25507
25508 /* Setter APIs detect special year numbers (0...99) and apply a +1900
25509 * only in certain cases. The legacy getYear() getter applies -1900
25510 * unconditionally.
25511 */
25512 duk_push_int(ctx, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
25513 return 1;
25514}
25515
25516/* Helper for component setter calls: check 'this' binding, get the
25517 * internal time value, split it into parts (either as UTC time or
25518 * local time), modify one or more components as specified, recompute
25519 * the time value, set it as the internal value. Finally, push the
25520 * new time value as a return value to the value stack and return 1
25521 * (caller can then tail call us).
25522 */
25524 duk_double_t d;
25527 duk_idx_t nargs;
25528 duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
25529 duk_small_uint_t idx_first, idx;
25531
25532 nargs = duk_get_top(ctx);
25533 d = duk__push_this_get_timeval(ctx, flags_and_maxnargs);
25535
25536 if (DUK_ISFINITE(d)) {
25537 duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
25538 } else {
25539 /* NaN timevalue: we need to coerce the arguments, but
25540 * the resulting internal timestamp needs to remain NaN.
25541 * This works but is not pretty: parts and dparts will
25542 * be partially uninitialized, but we only write to them.
25543 */
25544 }
25545
25546 /*
25547 * Determining which datetime components to overwrite based on
25548 * stack arguments is a bit complicated, but important to factor
25549 * out from setters themselves for compactness.
25550 *
25551 * If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
25552 *
25553 * 1 -> millisecond
25554 * 2 -> second, [millisecond]
25555 * 3 -> minute, [second], [millisecond]
25556 * 4 -> hour, [minute], [second], [millisecond]
25557 *
25558 * Else:
25559 *
25560 * 1 -> date
25561 * 2 -> month, [date]
25562 * 3 -> year, [month], [date]
25563 *
25564 * By comparing nargs and maxnargs (and flags) we know which
25565 * components to override. We rely on part index ordering.
25566 */
25567
25568 if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
25569 DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
25570 idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
25571 } else {
25572 DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
25573 idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
25574 }
25575 DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */
25577
25578 for (i = 0; i < maxnargs; i++) {
25579 if ((duk_idx_t) i >= nargs) {
25580 /* no argument given -> leave components untouched */
25581 break;
25582 }
25583 idx = idx_first + i;
25584 DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
25586
25587 if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
25589 }
25590
25591 dparts[idx] = duk_to_number(ctx, i);
25592
25593 if (idx == DUK_DATE_IDX_DAY) {
25594 /* Day-of-month is one-based in the API, but zero-based
25595 * internally, so fix here. Note that month is zero-based
25596 * both in the API and internally.
25597 */
25598 /* SCANBUILD: complains about use of uninitialized values.
25599 * The complaint is correct, but operating in undefined
25600 * values here is intentional in some cases and the caller
25601 * ignores the results.
25602 */
25603 dparts[idx] -= 1.0;
25604 }
25606
25607 /* Leaves new timevalue on stack top and returns 1, which is correct
25608 * for part setters.
25609 */
25610 if (DUK_ISFINITE(d)) {
25611 return duk__set_this_timeval_from_dparts(ctx, dparts, flags_and_maxnargs);
25612 } else {
25613 /* Internal timevalue is already NaN, so don't touch it. */
25614 duk_push_nan(ctx);
25615 return 1;
25616 }
25617}
25618
25619/* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
25620 * 1900 and replace value at idx_val.
25621 */
25623 duk_double_t d;
25624
25625 /* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
25626 * might not generate better code due to casting.
25627 */
25628
25629 /* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
25630 duk_to_number(ctx, idx_val);
25631 if (duk_is_nan(ctx, idx_val)) {
25632 return;
25633 }
25634 duk_dup(ctx, idx_val);
25635 duk_to_int(ctx, -1);
25636 d = duk_get_number(ctx, -1); /* get as double to handle huge numbers correctly */
25637 if (d >= 0.0 && d <= 99.0) {
25638 d += 1900.0;
25639 duk_push_number(ctx, d);
25640 duk_replace(ctx, idx_val);
25641 }
25642 duk_pop(ctx);
25643}
25644
25645/* Set datetime parts from stack arguments, defaulting any missing values.
25646 * Day-of-week is not set; it is not required when setting the time value.
25647 */
25649 duk_double_t d;
25651 duk_small_uint_t idx;
25652
25653 /* Causes a ToNumber() coercion, but doesn't break coercion order since
25654 * year is coerced first anyway.
25655 */
25657
25658 /* There are at most 7 args, but we use 8 here so that also
25659 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
25660 * for any Valgrind gripes later.
25661 */
25662 for (i = 0; i < 8; i++) {
25663 /* Note: rely on index ordering */
25664 idx = DUK_DATE_IDX_YEAR + i;
25665 if ((duk_idx_t) i < nargs) {
25666 d = duk_to_number(ctx, (duk_idx_t) i);
25667 if (idx == DUK_DATE_IDX_DAY) {
25668 /* Convert day from one-based to zero-based (internal). This may
25669 * cause the day part to be negative, which is OK.
25670 */
25671 d -= 1.0;
25672 }
25673 } else {
25674 /* All components default to 0 except day-of-month which defaults
25675 * to 1. However, because our internal day-of-month is zero-based,
25676 * it also defaults to zero here.
25677 */
25678 d = 0.0;
25679 }
25680 dparts[idx] = d;
25681 }
25682
25683 DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
25684 (double) dparts[0], (double) dparts[1],
25685 (double) dparts[2], (double) dparts[3],
25686 (double) dparts[4], (double) dparts[5],
25687 (double) dparts[6], (double) dparts[7]));
25688}
25689
25690/*
25691 * Helper to format a time value into caller buffer, used by logging.
25692 * 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long.
25693 */
25694
25695DUK_INTERNAL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf) {
25697
25699 parts,
25700 NULL,
25702
25704 0 /*tzoffset*/,
25707 DUK_DATE_FLAG_SEP_T /*flags*/,
25708 out_buf);
25709}
25710
25711/*
25712 * Indirect magic value lookup for Date methods.
25713 *
25714 * Date methods don't put their control flags into the function magic value
25715 * because they wouldn't fit into a LIGHTFUNC's magic field. Instead, the
25716 * magic value is set to an index pointing to the array of control flags
25717 * below.
25718 *
25719 * This must be kept in strict sync with genbuiltins.py!
25720 */
25721
25722static duk_uint16_t duk__date_magics[] = {
25723 /* 0: toString */
25725
25726 /* 1: toDateString */
25728
25729 /* 2: toTimeString */
25731
25732 /* 3: toLocaleString */
25734
25735 /* 4: toLocaleDateString */
25737
25738 /* 5: toLocaleTimeString */
25740
25741 /* 6: toUTCString */
25743
25744 /* 7: toISOString */
25746
25747 /* 8: getFullYear */
25749
25750 /* 9: getUTCFullYear */
25752
25753 /* 10: getMonth */
25755
25756 /* 11: getUTCMonth */
25758
25759 /* 12: getDate */
25761
25762 /* 13: getUTCDate */
25764
25765 /* 14: getDay */
25767
25768 /* 15: getUTCDay */
25770
25771 /* 16: getHours */
25773
25774 /* 17: getUTCHours */
25776
25777 /* 18: getMinutes */
25779
25780 /* 19: getUTCMinutes */
25782
25783 /* 20: getSeconds */
25785
25786 /* 21: getUTCSeconds */
25788
25789 /* 22: getMilliseconds */
25791
25792 /* 23: getUTCMilliseconds */
25794
25795 /* 24: setMilliseconds */
25797
25798 /* 25: setUTCMilliseconds */
25800
25801 /* 26: setSeconds */
25803
25804 /* 27: setUTCSeconds */
25806
25807 /* 28: setMinutes */
25809
25810 /* 29: setUTCMinutes */
25812
25813 /* 30: setHours */
25815
25816 /* 31: setUTCHours */
25818
25819 /* 32: setDate */
25821
25822 /* 33: setUTCDate */
25823 0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
25824
25825 /* 34: setMonth */
25828 /* 35: setUTCMonth */
25829 0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
25830
25831 /* 36: setFullYear */
25833
25834 /* 37: setUTCFullYear */
25836
25837 /* 38: getYear */
25839
25840 /* 39: setYear */
25842};
25843
25846 DUK_ASSERT(magicidx >= 0 && magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
25847 return (duk_small_uint_t) duk__date_magics[magicidx];
25848}
25849
25850/*
25851 * Constructor calls
25852 */
25853
25855 duk_idx_t nargs = duk_get_top(ctx);
25856 duk_bool_t is_cons = duk_is_constructor_call(ctx);
25858 duk_double_t d;
25859
25860 DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
25861
25866
25867 /* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
25868 * is mutable.
25869 */
25870
25871 if (nargs == 0 || !is_cons) {
25872 d = duk__timeclip(DUK_USE_DATE_GET_NOW(ctx));
25873 duk_push_number(ctx, d);
25875 if (!is_cons) {
25876 /* called as a normal function: return new Date().toString() */
25877 duk_to_string(ctx, -1);
25878 }
25879 return 1;
25880 } else if (nargs == 1) {
25882 if (duk_is_string(ctx, 0)) {
25883 duk__parse_string(ctx, duk_to_string(ctx, 0));
25884 duk_replace(ctx, 0); /* may be NaN */
25885 }
25886 d = duk__timeclip(duk_to_number(ctx, 0));
25887 duk_push_number(ctx, d);
25889 return 1;
25890 }
25891
25892 duk__set_parts_from_args(ctx, dparts, nargs);
25893
25894 /* Parts are in local time, convert when setting. */
25895
25896 (void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */
25897 duk_pop(ctx); /* -> [ ... this ] */
25898 return 1;
25899}
25900
25902 return duk__parse_string(ctx, duk_to_string(ctx, 0));
25903}
25904
25906 duk_idx_t nargs = duk_get_top(ctx);
25908 duk_double_t d;
25909
25910 /* Behavior for nargs < 2 is implementation dependent: currently we'll
25911 * set a NaN time value (matching V8 behavior) in this case.
25912 */
25913
25914 if (nargs < 2) {
25915 duk_push_nan(ctx);
25916 } else {
25917 duk__set_parts_from_args(ctx, dparts, nargs);
25918 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
25919 duk_push_number(ctx, d);
25920 }
25921 return 1;
25922}
25923
25925 duk_double_t d;
25926
25927 d = DUK_USE_DATE_GET_NOW(ctx);
25928 DUK_ASSERT(duk__timeclip(d) == d); /* TimeClip() should never be necessary */
25929 duk_push_number(ctx, d);
25930 return 1;
25931}
25932
25933/*
25934 * String/JSON conversions
25935 *
25936 * Human readable conversions are now basically ISO 8601 with a space
25937 * (instead of 'T') as the date/time separator. This is a good baseline
25938 * and is platform independent.
25939 *
25940 * A shared native helper to provide many conversions. Magic value contains
25941 * a set of flags. The helper provides:
25942 *
25943 * toString()
25944 * toDateString()
25945 * toTimeString()
25946 * toLocaleString()
25947 * toLocaleDateString()
25948 * toLocaleTimeString()
25949 * toUTCString()
25950 * toISOString()
25951 *
25952 * Notes:
25953 *
25954 * - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
25955 * required to be the same Ecmascript function object (!), so it is
25956 * omitted from here.
25957 *
25958 * - Date.prototype.toUTCString(): E5.1 specification does not require a
25959 * specific format, but result should be human readable. The
25960 * specification suggests using ISO 8601 format with a space (instead
25961 * of 'T') separator if a more human readable format is not available.
25962 *
25963 * - Date.prototype.toISOString(): unlike other conversion functions,
25964 * toISOString() requires a RangeError for invalid date values.
25965 */
25969 return duk__to_string_helper(ctx, flags);
25970}
25971
25973 /* This native function is also used for Date.prototype.getTime()
25974 * as their behavior is identical.
25975 */
25976
25977 duk_double_t d = duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ this ] */
25979 duk_push_number(ctx, d);
25980 return 1;
25981}
25982
25984 /* Note: toJSON() is a generic function which works even if 'this'
25985 * is not a Date. The sole argument is ignored.
25986 */
25987
25988 duk_push_this(ctx);
25989 duk_to_object(ctx, -1);
25990
25991 duk_dup_top(ctx);
25993 if (duk_is_number(ctx, -1)) {
25994 duk_double_t d = duk_get_number(ctx, -1);
25995 if (!DUK_ISFINITE(d)) {
25996 duk_push_null(ctx);
25997 return 1;
25998 }
25999 }
26000 duk_pop(ctx);
26001
26003 duk_dup(ctx, -2); /* -> [ O toIsoString O ] */
26004 duk_call_method(ctx, 0);
26005 return 1;
26006}
26007
26008/*
26009 * Getters.
26010 *
26011 * Implementing getters is quite easy. The internal time value is either
26012 * NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
26013 * The internal time value can be converted to integer parts, and each
26014 * part will be normalized and will fit into a 32-bit signed integer.
26015 *
26016 * A shared native helper to provide all getters. Magic value contains
26017 * a set of flags and also packs the date component index argument. The
26018 * helper provides:
26019 *
26020 * getFullYear()
26021 * getUTCFullYear()
26022 * getMonth()
26023 * getUTCMonth()
26024 * getDate()
26025 * getUTCDate()
26026 * getDay()
26027 * getUTCDay()
26028 * getHours()
26029 * getUTCHours()
26030 * getMinutes()
26031 * getUTCMinutes()
26032 * getSeconds()
26033 * getUTCSeconds()
26034 * getMilliseconds()
26035 * getUTCMilliseconds()
26036 * getYear()
26038 * Notes:
26039 *
26040 * - Date.prototype.getDate(): 'date' means day-of-month, and is
26041 * zero-based in internal calculations but public API expects it to
26042 * be one-based.
26043 *
26044 * - Date.prototype.getTime() and Date.prototype.valueOf() have identical
26045 * behavior. They have separate function objects, but share the same C
26046 * function (duk_bi_date_prototype_value_of).
26047 */
26048
26051 return duk__get_part_helper(ctx, flags_and_idx);
26052}
26053
26055 /*
26056 * Return (t - LocalTime(t)) in minutes:
26057 *
26058 * t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
26059 * = -(LocalTZA + DaylightSavingTA(t))
26060 *
26061 * where DaylightSavingTA() is checked for time 't'.
26062 *
26063 * Note that the sign of the result is opposite to common usage,
26064 * e.g. for EE(S)T which normally is +2h or +3h from UTC, this
26065 * function returns -120 or -180.
26066 *
26067 */
26068
26069 duk_double_t d;
26070 duk_int_t tzoffset;
26071
26072 /* Note: DST adjustment is determined using UTC time. */
26073 d = duk__push_this_get_timeval(ctx, 0 /*flags*/);
26075 if (DUK_ISNAN(d)) {
26076 duk_push_nan(ctx);
26077 } else {
26079 tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
26080 duk_push_int(ctx, -tzoffset / 60);
26081 }
26082 return 1;
26083}
26084
26085/*
26086 * Setters.
26087 *
26088 * Setters are a bit more complicated than getters. Component setters
26089 * break down the current time value into its (normalized) component
26090 * parts, replace one or more components with -unnormalized- new values,
26091 * and the components are then converted back into a time value. As an
26092 * example of using unnormalized values:
26093 *
26094 * var d = new Date(1234567890);
26095 *
26096 * is equivalent to:
26097 *
26098 * var d = new Date(0);
26099 * d.setUTCMilliseconds(1234567890);
26100 *
26101 * A shared native helper to provide almost all setters. Magic value
26102 * contains a set of flags and also packs the "maxnargs" argument. The
26103 * helper provides:
26104 *
26105 * setMilliseconds()
26106 * setUTCMilliseconds()
26107 * setSeconds()
26108 * setUTCSeconds()
26109 * setMinutes()
26110 * setUTCMinutes()
26111 * setHours()
26112 * setUTCHours()
26113 * setDate()
26114 * setUTCDate()
26115 * setMonth()
26116 * setUTCMonth()
26117 * setFullYear()
26118 * setUTCFullYear()
26119 * setYear()
26120 *
26121 * Notes:
26123 * - Date.prototype.setYear() (Section B addition): special year check
26124 * is omitted. NaN / Infinity will just flow through and ultimately
26125 * result in a NaN internal time value.
26126 *
26127 * - Date.prototype.setYear() does not have optional arguments for
26128 * setting month and day-in-month (like setFullYear()), but we indicate
26129 * 'maxnargs' to be 3 to get the year written to the correct component
26130 * index in duk__set_part_helper(). The function has nargs == 1, so only
26131 * the year will be set regardless of actual argument count.
26132 */
26133
26135 duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(ctx);
26136 return duk__set_part_helper(ctx, flags_and_maxnargs);
26137}
26138
26140 duk_double_t d;
26141
26142 (void) duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ timeval this ] */
26143 d = duk__timeclip(duk_to_number(ctx, 0));
26144 duk_push_number(ctx, d);
26145 duk_dup_top(ctx);
26146 duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
26148 return 1;
26149}
26150#line 1 "duk_bi_date_unix.c"
26151/*
26152 * Unix-like Date providers
26153 *
26154 * Generally useful Unix / POSIX / ANSI Date providers.
26155 */
26156
26157/* include removed: duk_internal.h */
26158
26159/* The necessary #includes are in place in duk_config.h. */
26160
26161/* Buffer sizes for some UNIX calls. Larger than strictly necessary
26162 * to avoid Valgrind errors.
26163 */
26164#define DUK__STRPTIME_BUF_SIZE 64
26165#define DUK__STRFTIME_BUF_SIZE 64
26166
26167#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
26168/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */
26169DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) {
26170 duk_hthread *thr = (duk_hthread *) ctx;
26171 struct timeval tv;
26172 duk_double_t d;
26173
26174 if (gettimeofday(&tv, NULL) != 0) {
26176 }
26177
26178 d = ((duk_double_t) tv.tv_sec) * 1000.0 +
26179 ((duk_double_t) (tv.tv_usec / 1000));
26180 DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions */
26181
26182 return d;
26183}
26184#endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
26185
26186#if defined(DUK_USE_DATE_NOW_TIME)
26187/* Not a very good provider: only full seconds are available. */
26189 time_t t;
26190
26191 DUK_UNREF(ctx);
26192 t = time(NULL);
26193 return ((duk_double_t) t) * 1000.0;
26194}
26195#endif /* DUK_USE_DATE_NOW_TIME */
26196
26197#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R)
26198/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
26200 time_t t, t1, t2;
26203 struct tm tms[2];
26204#ifdef DUK_USE_DATE_TZO_GMTIME
26205 struct tm *tm_ptr;
26206#endif
26207
26208 /* For NaN/inf, the return value doesn't matter. */
26209 if (!DUK_ISFINITE(d)) {
26210 return 0;
26211 }
26212
26213 /* If not within Ecmascript range, some integer time calculations
26214 * won't work correctly (and some asserts will fail), so bail out
26215 * if so. This fixes test-bug-date-insane-setyear.js. There is
26216 * a +/- 24h leeway in this range check to avoid a test262 corner
26217 * case documented in test-bug-date-timeval-edges.js.
26218 */
26220 DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
26221 return 0;
26222 }
26223
26224 /*
26225 * This is a bit tricky to implement portably. The result depends
26226 * on the timestamp (specifically, DST depends on the timestamp).
26227 * If e.g. UNIX APIs are used, they'll have portability issues with
26228 * very small and very large years.
26229 *
26230 * Current approach:
26231 *
26232 * - Stay within portable UNIX limits by using equivalent year mapping.
26233 * Avoid year 1970 and 2038 as some conversions start to fail, at
26234 * least on some platforms. Avoiding 1970 means that there are
26235 * currently DST discrepancies for 1970.
26236 *
26237 * - Create a UTC and local time breakdowns from 't'. Then create
26238 * a time_t using gmtime() and localtime() and compute the time
26239 * difference between the two.
26240 *
26241 * Equivalent year mapping (E5 Section 15.9.1.8):
26242 *
26243 * If the host environment provides functionality for determining
26244 * daylight saving time, the implementation of ECMAScript is free
26245 * to map the year in question to an equivalent year (same
26246 * leap-year-ness and same starting week day for the year) for which
26247 * the host environment provides daylight saving time information.
26248 * The only restriction is that all equivalent years should produce
26249 * the same result.
26250 *
26251 * This approach is quite reasonable but not entirely correct, e.g.
26252 * the specification also states (E5 Section 15.9.1.8):
26253 *
26254 * The implementation of ECMAScript should not try to determine
26255 * whether the exact time was subject to daylight saving time, but
26256 * just whether daylight saving time would have been in effect if
26257 * the _current daylight saving time algorithm_ had been used at the
26258 * time. This avoids complications such as taking into account the
26259 * years that the locale observed daylight saving time year round.
26260 *
26261 * Since we rely on the platform APIs for conversions between local
26262 * time and UTC, we can't guarantee the above. Rather, if the platform
26263 * has historical DST rules they will be applied. This seems to be the
26264 * general preferred direction in Ecmascript standardization (or at least
26265 * implementations) anyway, and even the equivalent year mapping should
26266 * be disabled if the platform is known to handle DST properly for the
26267 * full Ecmascript range.
26268 *
26269 * The following has useful discussion and links:
26270 *
26271 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
26272 */
26273
26274 duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
26275 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
26276
26277 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
26278 DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
26279 t = (time_t) (d / 1000.0);
26280 DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
26281
26282 DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
26283
26284#if defined(DUK_USE_DATE_TZO_GMTIME_R)
26285 (void) gmtime_r(&t, &tms[0]);
26286 (void) localtime_r(&t, &tms[1]);
26287#elif defined(DUK_USE_DATE_TZO_GMTIME)
26288 tm_ptr = gmtime(&t);
26289 DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
26290 tm_ptr = localtime(&t);
26291 DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));
26292#else
26293#error internal error
26294#endif
26295 DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26296 "wday:%ld,yday:%ld,isdst:%ld}",
26297 (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
26298 (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
26299 (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
26300 DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26301 "wday:%ld,yday:%ld,isdst:%ld}",
26302 (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
26303 (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
26304 (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
26305
26306 /* tm_isdst is both an input and an output to mktime(), use 0 to
26307 * avoid DST handling in mktime():
26308 * - https://github.com/svaarala/duktape/issues/406
26309 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
26310 */
26311 tms[0].tm_isdst = 0;
26312 tms[1].tm_isdst = 0;
26313 t1 = mktime(&tms[0]); /* UTC */
26314 t2 = mktime(&tms[1]); /* local */
26315 if (t1 == (time_t) -1 || t2 == (time_t) -1) {
26316 /* This check used to be for (t < 0) but on some platforms
26317 * time_t is unsigned and apparently the proper way to detect
26318 * an mktime() error return is the cast above. See e.g.:
26319 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
26320 */
26321 goto error;
26322 }
26323 DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
26324
26325 /* Compute final offset in seconds, positive if local time ahead of
26326 * UTC (returned value is UTC-to-local offset).
26327 *
26328 * difftime() returns a double, so coercion to int generates quite
26329 * a lot of code. Direct subtraction is not portable, however.
26330 * XXX: allow direct subtraction on known platforms.
26331 */
26332#if 0
26333 return (duk_int_t) (t2 - t1);
26334#endif
26335 return (duk_int_t) difftime(t2, t1);
26336
26337 error:
26338 /* XXX: return something more useful, so that caller can throw? */
26339 DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
26340 return 0;
26341}
26342#endif /* DUK_USE_DATE_TZO_GMTIME */
26343
26344#if defined(DUK_USE_DATE_PRS_STRPTIME)
26345DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str) {
26346 struct tm tm;
26347 time_t t;
26348 char buf[DUK__STRPTIME_BUF_SIZE];
26349
26350 /* copy to buffer with spare to avoid Valgrind gripes from strptime */
26351 DUK_ASSERT(str != NULL);
26352 DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */
26353 DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
26354 buf[sizeof(buf) - 1] = (char) 0;
26355
26356 DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
26357
26358 DUK_MEMZERO(&tm, sizeof(tm));
26359 if (strptime((const char *) buf, "%c", &tm) != NULL) {
26360 DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26361 "wday:%ld,yday:%ld,isdst:%ld}",
26362 (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
26363 (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
26364 (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
26365 tm.tm_isdst = -1; /* negative: dst info not available */
26366
26367 t = mktime(&tm);
26368 DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
26369 if (t >= 0) {
26370 duk_push_number(ctx, ((duk_double_t) t) * 1000.0);
26371 return 1;
26372 }
26373 }
26374
26375 return 0;
26376}
26377#endif /* DUK_USE_DATE_PRS_STRPTIME */
26378
26379#if defined(DUK_USE_DATE_PRS_GETDATE)
26380DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str) {
26381 struct tm tm;
26382 duk_small_int_t rc;
26383 time_t t;
26384
26385 /* For this to work, DATEMSK must be set, so this is not very
26386 * convenient for an embeddable interpreter.
26387 */
26388
26389 DUK_MEMZERO(&tm, sizeof(struct tm));
26390 rc = (duk_small_int_t) getdate_r(str, &tm);
26391 DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
26392
26393 if (rc == 0) {
26394 t = mktime(&tm);
26395 DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
26396 if (t >= 0) {
26397 duk_push_number(ctx, (duk_double_t) t);
26398 return 1;
26399 }
26400 }
26401
26402 return 0;
26403}
26404#endif /* DUK_USE_DATE_PRS_GETDATE */
26405
26406#if defined(DUK_USE_DATE_FMT_STRFTIME)
26407DUK_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) {
26408 char buf[DUK__STRFTIME_BUF_SIZE];
26409 struct tm tm;
26410 const char *fmt;
26411
26412 DUK_UNREF(tzoffset);
26413
26414 /* If the platform doesn't support the entire Ecmascript range, we need
26415 * to return 0 so that the caller can fall back to the default formatter.
26416 *
26417 * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript
26418 * range is supported. For smaller time_t values (4 bytes in practice),
26419 * assumes that the signed 32-bit range is supported.
26420 *
26421 * XXX: detect this more correctly per platform. The size of time_t is
26422 * probably not an accurate guarantee of strftime() supporting or not
26423 * supporting a large time range (the full Ecmascript range).
26424 */
26425 if (sizeof(time_t) < 8 &&
26426 (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
26427 /* be paranoid for 32-bit time values (even avoiding negative ones) */
26428 return 0;
26429 }
26430
26431 DUK_MEMZERO(&tm, sizeof(tm));
26432 tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
26433 tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
26434 tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
26435 tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */
26436 tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */
26437 tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
26438 tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
26439 tm.tm_isdst = 0;
26440
26441 DUK_MEMZERO(buf, sizeof(buf));
26442 if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
26443 fmt = "%c";
26444 } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
26445 fmt = "%x";
26446 } else {
26448 fmt = "%X";
26449 }
26450 (void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
26451 DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
26452
26453 duk_push_string(ctx, buf);
26454 return 1;
26455}
26456#endif /* DUK_USE_DATE_FMT_STRFTIME */
26457
26458#undef DUK__STRPTIME_BUF_SIZE
26459#undef DUK__STRFTIME_BUF_SIZE
26460#line 1 "duk_bi_date_windows.c"
26461/*
26462 * Windows Date providers
26463 *
26464 * Platform specific links:
26465 *
26466 * - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
26467 */
26468
26469/* include removed: duk_internal.h */
26470
26471/* The necessary #includes are in place in duk_config.h. */
26472
26473#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
26474/* Shared Windows helpers. */
26475DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
26476 FILETIME ft;
26477 if (SystemTimeToFileTime(st, &ft) == 0) {
26478 DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
26479 res->QuadPart = 0;
26480 } else {
26481 res->LowPart = ft.dwLowDateTime;
26482 res->HighPart = ft.dwHighDateTime;
26483 }
26484}
26485DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
26486 DUK_MEMZERO((void *) st, sizeof(*st));
26487 st->wYear = 1970;
26488 st->wMonth = 1;
26489 st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */
26490 st->wDay = 1;
26491 DUK_ASSERT(st->wHour == 0);
26492 DUK_ASSERT(st->wMinute == 0);
26493 DUK_ASSERT(st->wSecond == 0);
26494 DUK_ASSERT(st->wMilliseconds == 0);
26495}
26496#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
26497
26498#ifdef DUK_USE_DATE_NOW_WINDOWS
26499DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) {
26500 /* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
26501 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
26502 */
26503 SYSTEMTIME st1, st2;
26504 ULARGE_INTEGER tmp1, tmp2;
26505
26506 DUK_UNREF(ctx);
26507
26508 GetSystemTime(&st1);
26509 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
26510
26511 duk__set_systime_jan1970(&st2);
26512 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
26513
26514 /* Difference is in 100ns units, convert to milliseconds w/o fractions */
26515 return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL);
26516}
26517#endif /* DUK_USE_DATE_NOW_WINDOWS */
26518
26519
26520#if defined(DUK_USE_DATE_TZO_WINDOWS)
26521DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
26522 SYSTEMTIME st1;
26523 SYSTEMTIME st2;
26524 SYSTEMTIME st3;
26525 ULARGE_INTEGER tmp1;
26526 ULARGE_INTEGER tmp2;
26527 ULARGE_INTEGER tmp3;
26528 FILETIME ft1;
26529
26530 /* XXX: handling of timestamps outside Windows supported range.
26531 * How does Windows deal with dates before 1600? Does windows
26532 * support all Ecmascript years (like -200000 and +200000)?
26533 * Should equivalent year mapping be used here too? If so, use
26534 * a shared helper (currently integrated into timeval-to-parts).
26535 */
26536
26537 /* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
26538 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
26539 */
26540
26541 duk__set_systime_jan1970(&st1);
26542 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
26543 tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */
26544 tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */
26545
26546 ft1.dwLowDateTime = tmp2.LowPart;
26547 ft1.dwHighDateTime = tmp2.HighPart;
26548 FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
26549 if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
26550 DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
26551 return 0;
26552 }
26553 duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
26554
26555 /* Positive if local time ahead of UTC. */
26556 return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL); /* seconds */
26557}
26558#endif /* DUK_USE_DATE_TZO_WINDOWS */
26559#line 1 "duk_bi_duktape.c"
26560/*
26561 * Duktape built-ins
26563 * Size optimization note: it might seem that vararg multipurpose functions
26564 * like fin(), enc(), and dec() are not very size optimal, but using a single
26565 * user-visible Ecmascript function saves a lot of run-time footprint; each
26566 * Function instance takes >100 bytes. Using a shared native helper and a
26567 * 'magic' value won't save much if there are multiple Function instances
26568 * anyway.
26569 */
26570
26571/* include removed: duk_internal.h */
26572
26573/* Raw helper to extract internal information / statistics about a value.
26574 * The return values are version specific and must not expose anything
26575 * that would lead to security issues (e.g. exposing compiled function
26576 * 'data' buffer might be an issue). Currently only counts and sizes and
26577 * such are given so there should not be a security impact.
26578 */
26580 duk_hthread *thr = (duk_hthread *) ctx;
26581 duk_tval *tv;
26582 duk_heaphdr *h;
26583 duk_int_t i, n;
26584
26585 DUK_UNREF(thr);
26586
26587 /* result array */
26588 duk_push_array(ctx); /* -> [ val arr ] */
26589
26590 /* type tag (public) */
26591 duk_push_int(ctx, duk_get_type(ctx, 0));
26592
26593 /* address */
26594 tv = duk_get_tval(ctx, 0);
26595 DUK_ASSERT(tv != NULL); /* because arg count is 1 */
26597 h = DUK_TVAL_GET_HEAPHDR(tv);
26598 duk_push_pointer(ctx, (void *) h);
26599 } else {
26600 /* internal type tag */
26602 goto done;
26603 }
26604 DUK_ASSERT(h != NULL);
26605
26606 /* refcount */
26607#ifdef DUK_USE_REFERENCE_COUNTING
26609#else
26610 duk_push_undefined(ctx);
26611#endif
26612
26613 /* heaphdr size and additional allocation size, followed by
26614 * type specific stuff (with varying value count)
26615 */
26617 case DUK_HTYPE_STRING: {
26618 duk_hstring *h_str = (duk_hstring *) h;
26619 duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1));
26620 break;
26621 }
26622 case DUK_HTYPE_OBJECT: {
26623 duk_hobject *h_obj = (duk_hobject *) h;
26624 duk_small_uint_t hdr_size;
26626 hdr_size = (duk_small_uint_t) sizeof(duk_hcompiledfunction);
26627 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
26628 hdr_size = (duk_small_uint_t) sizeof(duk_hnativefunction);
26629 } else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
26630 hdr_size = (duk_small_uint_t) sizeof(duk_hthread);
26631#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26632 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
26633 hdr_size = (duk_small_uint_t) sizeof(duk_hbufferobject);
26634#endif
26635 } else {
26636 hdr_size = (duk_small_uint_t) sizeof(duk_hobject);
26637 }
26638 duk_push_uint(ctx, (duk_uint_t) hdr_size);
26641 /* Note: e_next indicates the number of gc-reachable entries
26642 * in the entry part, and also indicates the index where the
26643 * next new property would be inserted. It does *not* indicate
26644 * the number of non-NULL keys present in the object. That
26645 * value could be counted separately but requires a pass through
26646 * the key list.
26647 */
26653 if (h_data) {
26655 } else {
26656 duk_push_uint(ctx, 0);
26657 }
26658 }
26659 break;
26660 }
26661 case DUK_HTYPE_BUFFER: {
26662 duk_hbuffer *h_buf = (duk_hbuffer *) h;
26663 if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
26664 if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
26666 } else {
26667 /* When alloc_size == 0 the second allocation may not
26668 * actually exist.
26669 */
26671 }
26673 } else {
26674 duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1));
26675 }
26676 break;
26677
26678 }
26679 }
26680
26681 done:
26682 /* set values into ret array */
26683 /* XXX: primitive to make array from valstack slice */
26684 n = duk_get_top(ctx);
26685 for (i = 2; i < n; i++) {
26686 duk_dup(ctx, i);
26687 duk_put_prop_index(ctx, 1, i - 2);
26688 }
26689 duk_dup(ctx, 1);
26690 return 1;
26691}
26692
26694 duk_hthread *thr = (duk_hthread *) ctx;
26695 duk_activation *act;
26697 duk_uint_fast32_t line;
26698 duk_int_t level;
26699
26700 /* -1 = top callstack entry, callstack[callstack_top - 1]
26701 * -callstack_top = bottom callstack entry, callstack[0]
26702 */
26703 level = duk_to_int(ctx, 0);
26704 if (level >= 0 || -level > (duk_int_t) thr->callstack_top) {
26705 return 0;
26706 }
26707 DUK_ASSERT(level >= -((duk_int_t) thr->callstack_top) && level <= -1);
26708 act = thr->callstack + thr->callstack_top + level;
26709
26710 duk_push_object(ctx);
26711
26712 duk_push_tval(ctx, &act->tv_func);
26713
26714 /* Relevant PC is just before current one because PC is
26715 * post-incremented. This should match what error augment
26716 * code does.
26717 */
26718 pc = duk_hthread_get_act_prev_pc(thr, act);
26719 duk_push_uint(ctx, (duk_uint_t) pc);
26720
26721#if defined(DUK_USE_PC2LINE)
26722 line = duk_hobject_pc2line_query(ctx, -2, pc);
26723#else
26724 line = 0;
26725#endif
26727
26728 /* Providing access to e.g. act->lex_env would be dangerous: these
26729 * internal structures must never be accessible to the application.
26730 * Duktape relies on them having consistent data, and this consistency
26731 * is only asserted for, not checked for.
26732 */
26733
26734 /* [ level obj func pc line ] */
26735
26736 /* XXX: version specific array format instead? */
26740 return 1;
26741}
26742
26744#ifdef DUK_USE_MARK_AND_SWEEP
26745 duk_hthread *thr = (duk_hthread *) ctx;
26747 duk_bool_t rc;
26748
26749 flags = (duk_small_uint_t) duk_get_uint(ctx, 0);
26750 rc = duk_heap_mark_and_sweep(thr->heap, flags);
26751
26752 /* XXX: Not sure what the best return value would be in the API.
26753 * Return a boolean for now. Note that rc == 0 is success (true).
26754 */
26755 duk_push_boolean(ctx, !rc);
26756 return 1;
26757#else
26758 DUK_UNREF(ctx);
26759 return 0;
26760#endif
26761}
26762
26764 (void) duk_require_hobject(ctx, 0);
26765 if (duk_get_top(ctx) >= 2) {
26766 /* Set: currently a finalizer is disabled by setting it to
26767 * undefined; this does not remove the property at the moment.
26768 * The value could be type checked to be either a function
26769 * or something else; if something else, the property could
26770 * be deleted.
26771 */
26772 duk_set_top(ctx, 2);
26774 return 0;
26775 } else {
26776 /* Get. */
26777 DUK_ASSERT(duk_get_top(ctx) == 1);
26779 return 1;
26780 }
26781}
26782
26784 duk_hthread *thr = (duk_hthread *) ctx;
26785 duk_hstring *h_str;
26786
26787 DUK_UNREF(thr);
26788
26789 /* Vararg function: must be careful to check/require arguments.
26790 * The JSON helpers accept invalid indices and treat them like
26791 * non-existent optional parameters.
26792 */
26793
26794 h_str = duk_require_hstring(ctx, 0);
26796
26797 if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
26798 duk_set_top(ctx, 2);
26799 duk_hex_encode(ctx, 1);
26800 DUK_ASSERT_TOP(ctx, 2);
26801 } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
26802 duk_set_top(ctx, 2);
26803 duk_base64_encode(ctx, 1);
26804 DUK_ASSERT_TOP(ctx, 2);
26805#ifdef DUK_USE_JX
26806 } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
26808 1 /*idx_value*/,
26809 2 /*idx_replacer*/,
26810 3 /*idx_space*/,
26814#endif
26815#ifdef DUK_USE_JC
26816 } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
26818 1 /*idx_value*/,
26819 2 /*idx_replacer*/,
26820 3 /*idx_space*/,
26822 DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
26823#endif
26824 } else {
26825 return DUK_RET_TYPE_ERROR;
26826 }
26827 return 1;
26828}
26829
26831 duk_hthread *thr = (duk_hthread *) ctx;
26832 duk_hstring *h_str;
26833
26834 DUK_UNREF(thr);
26835
26836 /* Vararg function: must be careful to check/require arguments.
26837 * The JSON helpers accept invalid indices and treat them like
26838 * non-existent optional parameters.
26839 */
26840
26841 h_str = duk_require_hstring(ctx, 0);
26843
26844 if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
26845 duk_set_top(ctx, 2);
26846 duk_hex_decode(ctx, 1);
26847 DUK_ASSERT_TOP(ctx, 2);
26848 } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
26849 duk_set_top(ctx, 2);
26850 duk_base64_decode(ctx, 1);
26851 DUK_ASSERT_TOP(ctx, 2);
26852#ifdef DUK_USE_JX
26853 } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
26855 1 /*idx_value*/,
26856 2 /*idx_replacer*/,
26857 DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
26858#endif
26859#ifdef DUK_USE_JC
26860 } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
26862 1 /*idx_value*/,
26863 2 /*idx_replacer*/,
26865#endif
26866 } else {
26867 return DUK_RET_TYPE_ERROR;
26868 }
26869 return 1;
26870}
26872/*
26873 * Compact an object
26874 */
26875
26877 DUK_ASSERT_TOP(ctx, 1);
26878 duk_compact(ctx, 0);
26879 return 1; /* return the argument object */
26880}
26881#line 1 "duk_bi_error.c"
26882/*
26883 * Error built-ins
26884 */
26885
26886/* include removed: duk_internal.h */
26887
26889 /* Behavior for constructor and non-constructor call is
26890 * the same except for augmenting the created error. When
26891 * called as a constructor, the caller (duk_new()) will handle
26892 * augmentation; when called as normal function, we need to do
26893 * it here.
26894 */
26895
26896 duk_hthread *thr = (duk_hthread *) ctx;
26897 duk_small_int_t bidx_prototype = duk_get_current_magic(ctx);
26898
26899 /* same for both error and each subclass like TypeError */
26900 duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
26902
26903 DUK_UNREF(thr);
26904
26905 duk_push_object_helper(ctx, flags_and_class, bidx_prototype);
26906
26907 /* If message is undefined, the own property 'message' is not set at
26908 * all to save property space. An empty message is inherited anyway.
26909 */
26910 if (!duk_is_undefined(ctx, 0)) {
26911 duk_to_string(ctx, 0);
26912 duk_dup(ctx, 0); /* [ message error message ] */
26914 }
26915
26916 /* Augment the error if called as a normal function. __FILE__ and __LINE__
26917 * are not desirable in this case.
26918 */
26919
26920#ifdef DUK_USE_AUGMENT_ERROR_CREATE
26921 if (!duk_is_constructor_call(ctx)) {
26922 duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
26923 }
26924#endif
26925
26926 return 1;
26927}
26928
26930 /* XXX: optimize with more direct internal access */
26931
26932 duk_push_this(ctx);
26934
26935 /* [ ... this ] */
26936
26938 if (duk_is_undefined(ctx, -1)) {
26939 duk_pop(ctx);
26940 duk_push_string(ctx, "Error");
26941 } else {
26942 duk_to_string(ctx, -1);
26943 }
26944
26945 /* [ ... this name ] */
26946
26947 /* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
26948 * accident or are they actually needed? The first ToString()
26949 * could conceivably return 'undefined'.
26950 */
26952 if (duk_is_undefined(ctx, -1)) {
26953 duk_pop(ctx);
26954 duk_push_string(ctx, "");
26955 } else {
26956 duk_to_string(ctx, -1);
26957 }
26958
26959 /* [ ... this name message ] */
26960
26961 if (duk_get_length(ctx, -2) == 0) {
26962 /* name is empty -> return message */
26963 return 1;
26964 }
26965 if (duk_get_length(ctx, -1) == 0) {
26966 /* message is empty -> return name */
26967 duk_pop(ctx);
26968 return 1;
26969 }
26970 duk_push_string(ctx, ": ");
26971 duk_insert(ctx, -2); /* ... name ': ' message */
26972 duk_concat(ctx, 3);
26973
26974 return 1;
26975}
26976
26977#if defined(DUK_USE_TRACEBACKS)
26980 * Traceback handling
26982 * The unified helper decodes the traceback and produces various requested
26983 * outputs. It should be optimized for size, and may leave garbage on stack,
26984 * only the topmost return value matters. For instance, traceback separator
26985 * and decoded strings are pushed even when looking for filename only.
26986 *
26987 * NOTE: although _Tracedata is an internal property, user code can currently
26988 * write to the array (or replace it with something other than an array).
26989 * The code below must tolerate arbitrary _Tracedata. It can throw errors
26990 * etc, but cannot cause a segfault or memory unsafe behavior.
26991 */
26992
26993/* constants arbitrary, chosen for small loads */
26994#define DUK__OUTPUT_TYPE_TRACEBACK (-1)
26995#define DUK__OUTPUT_TYPE_FILENAME 0
26996#define DUK__OUTPUT_TYPE_LINENUMBER 1
26997
26999 duk_hthread *thr = (duk_hthread *) ctx;
27000 duk_idx_t idx_td;
27001 duk_small_int_t i; /* traceback depth fits into 16 bits */
27002 duk_small_int_t t; /* stack type fits into 16 bits */
27003 duk_small_int_t count_func = 0; /* traceback depth ensures fits into 16 bits */
27004 const char *str_tailcall = " tailcall";
27005 const char *str_strict = " strict";
27006 const char *str_construct = " construct";
27007 const char *str_prevyield = " preventsyield";
27008 const char *str_directeval = " directeval";
27009 const char *str_empty = "";
27010
27011 DUK_ASSERT_TOP(ctx, 0); /* fixed arg count */
27012 DUK_UNREF(thr);
27013
27014 duk_push_this(ctx);
27016 idx_td = duk_get_top_index(ctx);
27017
27019 duk_push_this(ctx);
27020
27021 /* [ ... this tracedata sep this ] */
27022
27023 /* XXX: skip null filename? */
27024
27025 if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
27026 /* Current tracedata contains 2 entries per callstack entry. */
27027 for (i = 0; ; i += 2) {
27028 duk_int_t pc;
27029 duk_int_t line;
27030 duk_int_t flags;
27031 duk_double_t d;
27032 const char *funcname;
27033 const char *filename;
27034 duk_hobject *h_func;
27035 duk_hstring *h_name;
27036
27037 duk_require_stack(ctx, 5);
27038 duk_get_prop_index(ctx, idx_td, i);
27039 duk_get_prop_index(ctx, idx_td, i + 1);
27040 d = duk_to_number(ctx, -1);
27042 flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
27043 t = (duk_small_int_t) duk_get_type(ctx, -2);
27044
27045 if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
27046 /*
27047 * Ecmascript/native function call or lightfunc call
27048 */
27049
27050 count_func++;
27051
27052 /* [ ... v1(func) v2(pc+flags) ] */
27053
27054 h_func = duk_get_hobject(ctx, -2); /* NULL for lightfunc */
27055
27058
27059#if defined(DUK_USE_PC2LINE)
27060 line = duk_hobject_pc2line_query(ctx, -4, (duk_uint_fast32_t) pc);
27061#else
27062 line = 0;
27063#endif
27064
27065 /* [ ... v1 v2 name filename ] */
27066
27067 /* When looking for .fileName/.lineNumber, blame first
27068 * function which has a .fileName.
27069 */
27070 if (duk_is_string(ctx, -1)) {
27071 if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
27072 return 1;
27073 } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
27074 duk_push_int(ctx, line);
27075 return 1;
27076 }
27077 }
27078
27079 /* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
27080 /* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
27081 h_name = duk_get_hstring(ctx, -2); /* may be NULL */
27082 funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
27083 "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
27084 filename = duk_get_string(ctx, -1);
27085 filename = filename ? filename : "";
27087 DUK_ASSERT(filename != NULL);
27088
27089 if (h_func == NULL) {
27090 duk_push_sprintf(ctx, "at %s light%s%s%s%s%s",
27091 (const char *) funcname,
27092 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27093 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27094 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27095 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27096 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27097 } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) {
27098 duk_push_sprintf(ctx, "at %s (%s) native%s%s%s%s%s",
27099 (const char *) funcname,
27100 (const char *) filename,
27101 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27102 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27103 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27104 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27105 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27106 } else {
27107 duk_push_sprintf(ctx, "at %s (%s:%ld)%s%s%s%s%s",
27108 (const char *) funcname,
27109 (const char *) filename,
27110 (long) line,
27111 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27112 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27113 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27114 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27115 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27116 }
27117 duk_replace(ctx, -5); /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
27118 duk_pop_n(ctx, 3); /* -> [ ... str ] */
27119 } else if (t == DUK_TYPE_STRING) {
27120 /*
27121 * __FILE__ / __LINE__ entry, here 'pc' is line number directly.
27122 * Sometimes __FILE__ / __LINE__ is reported as the source for
27123 * the error (fileName, lineNumber), sometimes not.
27124 */
27125
27126 /* [ ... v1(filename) v2(line+flags) ] */
27127
27128 /* When looking for .fileName/.lineNumber, blame compilation
27129 * or C call site unless flagged not to do so.
27130 */
27131 if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
27132 if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
27133 duk_pop(ctx);
27134 return 1;
27135 } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
27136 duk_push_int(ctx, pc);
27137 return 1;
27138 }
27139 }
27140
27141 duk_push_sprintf(ctx, "at [anon] (%s:%ld) internal",
27142 (const char *) duk_get_string(ctx, -2), (long) pc);
27143 duk_replace(ctx, -3); /* [ ... v1 v2 str ] -> [ ... str v2 ] */
27144 duk_pop(ctx); /* -> [ ... str ] */
27145 } else {
27146 /* unknown, ignore */
27147 duk_pop_2(ctx);
27148 break;
27149 }
27150 }
27151
27152 if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
27153 /* Possibly truncated; there is no explicit truncation
27154 * marker so this is the best we can do.
27155 */
27156
27158 }
27159 }
27160
27161 /* [ ... this tracedata sep this str1 ... strN ] */
27163 if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
27164 return 0;
27165 } else {
27166 /* The 'this' after 'sep' will get ToString() coerced by
27167 * duk_join() automatically. We don't want to do that
27168 * coercion when providing .fileName or .lineNumber (GH-254).
27169 */
27170 duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
27171 return 1;
27172 }
27173}
27174
27175/* XXX: Output type could be encoded into native function 'magic' value to
27176 * save space. For setters the stridx could be encoded into 'magic'.
27177 */
27178
27181}
27182
27185}
27186
27189}
27190
27191#undef DUK__OUTPUT_TYPE_TRACEBACK
27192#undef DUK__OUTPUT_TYPE_FILENAME
27193#undef DUK__OUTPUT_TYPE_LINENUMBER
27194
27195#else /* DUK_USE_TRACEBACKS */
27196
27197/*
27198 * Traceback handling when tracebacks disabled.
27199 *
27200 * The fileName / lineNumber stubs are now necessary because built-in
27201 * data will include the accessor properties in Error.prototype. If those
27202 * are removed for builds without tracebacks, these can also be removed.
27203 * 'stack' should still be present and produce a ToString() equivalent:
27204 * this is useful for user code which prints a stacktrace and expects to
27205 * see something useful. A normal stacktrace also begins with a ToString()
27206 * of the error so this makes sense.
27207 */
27208
27210 /* XXX: remove this native function and map 'stack' accessor
27211 * to the toString() implementation directly.
27212 */
27214}
27215
27217 DUK_UNREF(ctx);
27218 return 0;
27219}
27220
27222 DUK_UNREF(ctx);
27223 return 0;
27224}
27225
27226#endif /* DUK_USE_TRACEBACKS */
27227
27229 /* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
27230 * user code called Object.defineProperty() to create an overriding
27231 * own property. This allows user code to overwrite .fileName etc
27232 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
27233 * See https://github.com/svaarala/duktape/issues/387.
27234 */
27235
27236 DUK_ASSERT_TOP(ctx, 1); /* fixed arg count: value */
27238 duk_push_this(ctx);
27239 duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key);
27240 duk_dup(ctx, 0);
27242 /* [ ... obj key value ] */
27243
27244 DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
27245 duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1)));
27246
27249 DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
27251 return 0;
27252}
27253
27256}
27257
27260}
27261
27264}
27265#line 1 "duk_bi_function.c"
27266/*
27267 * Function built-ins
27268 */
27269
27270/* include removed: duk_internal.h */
27271
27273 duk_hthread *thr = (duk_hthread *) ctx;
27274 duk_hstring *h_sourcecode;
27275 duk_idx_t nargs;
27276 duk_idx_t i;
27277 duk_small_uint_t comp_flags;
27279 duk_hobject *outer_lex_env;
27280 duk_hobject *outer_var_env;
27281
27282 /* normal and constructor calls have identical semantics */
27283
27284 nargs = duk_get_top(ctx);
27285 for (i = 0; i < nargs; i++) {
27286 duk_to_string(ctx, i);
27287 }
27288
27289 if (nargs == 0) {
27290 duk_push_string(ctx, "");
27291 duk_push_string(ctx, "");
27292 } else if (nargs == 1) {
27293 /* XXX: cover this with the generic >1 case? */
27294 duk_push_string(ctx, "");
27295 } else {
27296 duk_insert(ctx, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
27297 duk_push_string(ctx, ",");
27298 duk_insert(ctx, 1);
27299 duk_join(ctx, nargs - 1);
27300 }
27301
27302 /* [ body formals ], formals is comma separated list that needs to be parsed */
27303
27304 DUK_ASSERT_TOP(ctx, 2);
27305
27306 /* XXX: this placeholder is not always correct, but use for now.
27307 * It will fail in corner cases; see test-dev-func-cons-args.js.
27308 */
27309 duk_push_string(ctx, "function(");
27310 duk_dup(ctx, 1);
27311 duk_push_string(ctx, "){");
27312 duk_dup(ctx, 0);
27313 duk_push_string(ctx, "}");
27314 duk_concat(ctx, 5);
27315
27316 /* [ body formals source ] */
27317
27318 DUK_ASSERT_TOP(ctx, 3);
27319
27320 /* strictness is not inherited, intentional */
27321 comp_flags = DUK_JS_COMPILE_FLAG_FUNCEXPR;
27322
27323 duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */
27324 h_sourcecode = duk_require_hstring(ctx, -2);
27325 duk_js_compile(thr,
27326 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
27327 (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
27328 comp_flags);
27329 func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
27330 DUK_ASSERT(func != NULL);
27333 /* [ body formals source template ] */
27334
27335 /* only outer_lex_env matters, as functions always get a new
27336 * variable declaration environment.
27337 */
27339 outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
27340 outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
27341
27342 duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
27343
27344 /* [ body formals source template closure ] */
27345
27346 return 1;
27347}
27348
27350 /* ignore arguments, return undefined (E5 Section 15.3.4) */
27351 DUK_UNREF(ctx);
27352 return 0;
27353}
27354
27356 duk_tval *tv;
27357
27358 /*
27359 * E5 Section 15.3.4.2 places few requirements on the output of
27360 * this function:
27361 *
27362 * - The result is an implementation dependent representation
27363 * of the function; in particular
27364 *
27365 * - The result must follow the syntax of a FunctionDeclaration.
27366 * In particular, the function must have a name (even in the
27367 * case of an anonymous function or a function with an empty
27368 * name).
27369 *
27370 * - Note in particular that the output does NOT need to compile
27371 * into anything useful.
27372 */
27373
27374
27375 /* XXX: faster internal way to get this */
27376 duk_push_this(ctx);
27377 tv = duk_get_tval(ctx, -1);
27378 DUK_ASSERT(tv != NULL);
27379
27380 if (DUK_TVAL_IS_OBJECT(tv)) {
27382 const char *func_name;
27383
27384 /* Function name: missing/undefined is mapped to empty string,
27385 * otherwise coerce to string.
27386 */
27387 /* XXX: currently no handling for non-allowed identifier characters,
27388 * e.g. a '{' in the function name.
27389 */
27391 if (duk_is_undefined(ctx, -1)) {
27392 func_name = "";
27393 } else {
27394 func_name = duk_to_string(ctx, -1);
27395 DUK_ASSERT(func_name != NULL);
27396 }
27397
27398 /* Indicate function type in the function body using a dummy
27399 * directive.
27400 */
27402 duk_push_sprintf(ctx, "function %s() {\"ecmascript\"}", (const char *) func_name);
27403 } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
27404 duk_push_sprintf(ctx, "function %s() {\"native\"}", (const char *) func_name);
27405 } else if (DUK_HOBJECT_HAS_BOUND(obj)) {
27406 duk_push_sprintf(ctx, "function %s() {\"bound\"}", (const char *) func_name);
27407 } else {
27408 goto type_error;
27409 }
27410 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
27412 } else {
27413 goto type_error;
27414 }
27415
27416 return 1;
27417
27418 type_error:
27419 return DUK_RET_TYPE_ERROR;
27420}
27421
27423 duk_idx_t len;
27424 duk_idx_t i;
27425
27426 DUK_ASSERT_TOP(ctx, 2); /* not a vararg function */
27427
27428 duk_push_this(ctx);
27429 if (!duk_is_callable(ctx, -1)) {
27430 DUK_DDD(DUK_DDDPRINT("func is not callable"));
27431 goto type_error;
27432 }
27433 duk_insert(ctx, 0);
27434 DUK_ASSERT_TOP(ctx, 3);
27435
27436 DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT",
27437 (duk_tval *) duk_get_tval(ctx, 0),
27438 (duk_tval *) duk_get_tval(ctx, 1),
27439 (duk_tval *) duk_get_tval(ctx, 2)));
27440
27441 /* [ func thisArg argArray ] */
27442
27443 if (duk_is_null_or_undefined(ctx, 2)) {
27444 DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args"));
27445 len = 0;
27446 } else if (!duk_is_object(ctx, 2)) {
27447 goto type_error;
27448 } else {
27449 DUK_DDD(DUK_DDDPRINT("argArray is an object"));
27450
27451 /* XXX: make this an internal helper */
27453 len = (duk_idx_t) duk_to_uint32(ctx, -1); /* ToUint32() coercion required */
27454 duk_pop(ctx);
27455
27456 duk_require_stack(ctx, len);
27457
27458 DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len));
27459 for (i = 0; i < len; i++) {
27460 duk_get_prop_index(ctx, 2, i);
27461 }
27463 duk_remove(ctx, 2);
27464 DUK_ASSERT_TOP(ctx, 2 + len);
27465
27466 /* [ func thisArg arg1 ... argN ] */
27467
27468 DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld",
27469 (duk_tval *) duk_get_tval(ctx, 0),
27470 (duk_tval *) duk_get_tval(ctx, 1),
27471 (long) len));
27472 duk_call_method(ctx, len);
27473 return 1;
27474
27475 type_error:
27476 return DUK_RET_TYPE_ERROR;
27477}
27478
27480 duk_idx_t nargs;
27481
27482 /* Step 1 is not necessary because duk_call_method() will take
27483 * care of it.
27484 */
27485
27486 /* vararg function, thisArg needs special handling */
27487 nargs = duk_get_top(ctx); /* = 1 + arg count */
27488 if (nargs == 0) {
27489 duk_push_undefined(ctx);
27490 nargs++;
27491 }
27492 DUK_ASSERT(nargs >= 1);
27493
27494 /* [ thisArg arg1 ... argN ] */
27495
27496 duk_push_this(ctx); /* 'func' in the algorithm */
27497 duk_insert(ctx, 0);
27498
27499 /* [ func thisArg arg1 ... argN ] */
27500
27501 DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argcount=%ld, top=%ld",
27502 (duk_tval *) duk_get_tval(ctx, 0),
27503 (duk_tval *) duk_get_tval(ctx, 1),
27504 (long) (nargs - 1),
27505 (long) duk_get_top(ctx)));
27506 duk_call_method(ctx, nargs - 1);
27507 return 1;
27508}
27509
27510/* XXX: the implementation now assumes "chained" bound functions,
27511 * whereas "collapsed" bound functions (where there is ever only
27512 * one bound function which directly points to a non-bound, final
27513 * function) would require a "collapsing" implementation which
27514 * merges argument lists etc here.
27515 */
27517 duk_hobject *h_bound;
27518 duk_hobject *h_target;
27519 duk_idx_t nargs;
27520 duk_idx_t i;
27521
27522 /* vararg function, careful arg handling (e.g. thisArg may not be present) */
27523 nargs = duk_get_top(ctx); /* = 1 + arg count */
27524 if (nargs == 0) {
27525 duk_push_undefined(ctx);
27526 nargs++;
27527 }
27528 DUK_ASSERT(nargs >= 1);
27529
27530 duk_push_this(ctx);
27531 if (!duk_is_callable(ctx, -1)) {
27532 DUK_DDD(DUK_DDDPRINT("func is not callable"));
27533 goto type_error;
27534 }
27535
27536 /* [ thisArg arg1 ... argN func ] (thisArg+args == nargs total) */
27537 DUK_ASSERT_TOP(ctx, nargs + 1);
27538
27539 /* create bound function object */
27546 h_bound = duk_get_hobject(ctx, -1);
27547 DUK_ASSERT(h_bound != NULL);
27548
27549 /* [ thisArg arg1 ... argN func boundFunc ] */
27550 duk_dup(ctx, -2); /* func */
27552
27553 duk_dup(ctx, 0); /* thisArg */
27555
27556 duk_push_array(ctx);
27557
27558 /* [ thisArg arg1 ... argN func boundFunc argArray ] */
27559
27560 for (i = 0; i < nargs - 1; i++) {
27561 duk_dup(ctx, 1 + i);
27562 duk_put_prop_index(ctx, -2, i);
27563 }
27565
27566 /* [ thisArg arg1 ... argN func boundFunc ] */
27567
27568 /* bound function 'length' property is interesting */
27569 h_target = duk_get_hobject(ctx, -2);
27570 if (h_target == NULL || /* lightfunc */
27572 /* For lightfuncs, simply read the virtual property. */
27573 duk_int_t tmp;
27575 tmp = duk_to_int(ctx, -1) - (nargs - 1); /* step 15.a */
27576 duk_pop(ctx);
27577 duk_push_int(ctx, (tmp < 0 ? 0 : tmp));
27578 } else {
27579 duk_push_int(ctx, 0);
27580 }
27581 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); /* attrs in E5 Section 15.3.5.1 */
27582
27583 /* caller and arguments must use the same thrower, [[ThrowTypeError]] */
27586
27587 /* these non-standard properties are copied for convenience */
27588 /* XXX: 'copy properties' API call? */
27593
27594 /* The 'strict' flag is copied to get the special [[Get]] of E5.1
27595 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
27596 * function. Not sure if this is correct, because the specification
27597 * is a bit ambiguous on this point but it would make sense.
27598 */
27599 if (h_target == NULL) {
27600 /* Lightfuncs are always strict. */
27601 DUK_HOBJECT_SET_STRICT(h_bound);
27602 } else if (DUK_HOBJECT_HAS_STRICT(h_target)) {
27603 DUK_HOBJECT_SET_STRICT(h_bound);
27604 }
27605 DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
27606
27607 return 1;
27608
27609 type_error:
27610 return DUK_RET_TYPE_ERROR;
27611}
27612#line 1 "duk_bi_global.c"
27613/*
27614 * Global object built-ins
27615 */
27616
27617/* include removed: duk_internal.h */
27619/*
27620 * Encoding/decoding helpers
27622
27623/* XXX: Could add fast path (for each transform callback) with direct byte
27624 * lookups (no shifting) and no explicit check for x < 0x80 before table
27625 * lookup.
27626 */
27627
27628/* Macros for creating and checking bitmasks for character encoding.
27629 * Bit number is a bit counterintuitive, but minimizes code size.
27630 */
27631#define DUK__MKBITS(a,b,c,d,e,f,g,h) ((duk_uint8_t) ( \
27632 ((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
27633 ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
27634 ))
27635#define DUK__CHECK_BITMASK(table,cp) ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
27636
27637/* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
27638DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
27639 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27640 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27641 DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x20-0x2f */
27642 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
27643 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
27644 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
27645 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
27646 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
27647};
27648
27649/* E5.1 Section 15.1.3.4: uriUnescaped */
27651 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27652 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27653 DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0), /* 0x20-0x2f */
27654 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
27655 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
27656 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
27657 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
27658 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
27659};
27660
27661/* E5.1 Section 15.1.3.1: uriReserved + '#' */
27662DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
27663 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27664 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27665 DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1), /* 0x20-0x2f */
27666 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
27667 DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
27668 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
27669 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
27670 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
27671};
27672
27673/* E5.1 Section 15.1.3.2: empty */
27675 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27676 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27677 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x20-0x2f */
27678 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
27679 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
27680 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
27681 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
27682 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
27683};
27684
27685#ifdef DUK_USE_SECTION_B
27686/* E5.1 Section B.2.2, step 7. */
27687DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
27688 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
27689 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
27690 DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1), /* 0x20-0x2f */
27691 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
27692 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
27693 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
27694 DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
27695 DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0) /* 0x70-0x7f */
27697#endif /* DUK_USE_SECTION_B */
27698
27699#undef DUK__MKBITS
27700
27701typedef struct {
27702 duk_hthread *thr;
27703 duk_hstring *h_str;
27705 const duk_uint8_t *p;
27706 const duk_uint8_t *p_start;
27707 const duk_uint8_t *p_end;
27709
27710typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
27711
27712/* XXX: refactor and share with other code */
27714 duk_small_int_t ch;
27715 duk_small_int_t t = 0;
27716
27717 while (n > 0) {
27718 t = t * 16;
27719 ch = (duk_small_int_t) duk_hex_dectab[*p++];
27720 if (DUK_LIKELY(ch >= 0)) {
27721 t += ch;
27722 } else {
27723 return -1;
27724 }
27725 n--;
27726 }
27727 return t;
27728}
27729
27730DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, const void *udata) {
27731 duk_hthread *thr = (duk_hthread *) ctx;
27732 duk__transform_context tfm_ctx_alloc;
27733 duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
27734 duk_codepoint_t cp;
27735
27736 tfm_ctx->thr = thr;
27737
27738 tfm_ctx->h_str = duk_to_hstring(ctx, 0);
27739 DUK_ASSERT(tfm_ctx->h_str != NULL);
27740
27741 DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */
27742
27743 tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
27744 tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
27745 tfm_ctx->p = tfm_ctx->p_start;
27746
27747 while (tfm_ctx->p < tfm_ctx->p_end) {
27748 cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
27749 callback(tfm_ctx, udata, cp);
27750 }
27751
27752 DUK_BW_COMPACT(thr, &tfm_ctx->bw);
27753
27754 duk_to_string(ctx, -1);
27755 return 1;
27756}
27757
27759 duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
27760 duk_small_int_t len;
27761 duk_codepoint_t cp1, cp2;
27762 duk_small_int_t i, t;
27763 const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
27764
27765 /* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
27766 * Codepoint range is restricted so this is a slightly too large
27767 * but doesn't matter.
27768 */
27769 DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
27770
27771 if (cp < 0) {
27772 goto uri_error;
27773 } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
27774 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
27775 return;
27776 } else if (cp >= 0xdc00L && cp <= 0xdfffL) {
27777 goto uri_error;
27778 } else if (cp >= 0xd800L && cp <= 0xdbffL) {
27779 /* Needs lookahead */
27780 if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
27781 goto uri_error;
27782 }
27783 if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
27784 goto uri_error;
27785 }
27786 cp1 = cp;
27787 cp = ((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L;
27788 } else if (cp > 0x10ffffL) {
27789 /* Although we can allow non-BMP characters (they'll decode
27790 * back into surrogate pairs), we don't allow extended UTF-8
27791 * characters; they would encode to URIs which won't decode
27792 * back because of strict UTF-8 checks in URI decoding.
27793 * (However, we could just as well allow them here.)
27794 */
27795 goto uri_error;
27796 } else {
27797 /* Non-BMP characters within valid UTF-8 range: encode as is.
27798 * They'll decode back into surrogate pairs if the escaped
27799 * output is decoded.
27800 */
27801 ;
27802 }
27804 len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
27805 for (i = 0; i < len; i++) {
27806 t = (int) xutf8_buf[i];
27807 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27808 &tfm_ctx->bw,
27810 (duk_uint8_t) duk_uc_nybbles[t >> 4],
27811 (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
27812 }
27813
27814 return;
27815
27816 uri_error:
27817 DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
27818}
27819
27821 const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
27822 duk_small_uint_t utf8_blen;
27823 duk_codepoint_t min_cp;
27824 duk_small_int_t t; /* must be signed */
27826
27827 /* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
27828 * percent escape path writes max two times CESU-8 encoded BMP length.
27829 */
27830 DUK_BW_ENSURE(tfm_ctx->thr,
27831 &tfm_ctx->bw,
27834
27835 if (cp == (duk_codepoint_t) '%') {
27836 const duk_uint8_t *p = tfm_ctx->p;
27837 duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
27838
27839 DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
27840
27841 if (left < 2) {
27842 goto uri_error;
27843 }
27844
27845 t = duk__decode_hex_escape(p, 2);
27846 DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
27847 if (t < 0) {
27848 goto uri_error;
27849 }
27850
27851 if (t < 0x80) {
27852 if (DUK__CHECK_BITMASK(reserved_table, t)) {
27853 /* decode '%xx' to '%xx' if decoded char in reserved set */
27854 DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
27855 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27856 &tfm_ctx->bw,
27858 p[0],
27859 p[1]);
27860 } else {
27861 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
27862 }
27863 tfm_ctx->p += 2;
27864 return;
27865 }
27866
27867 /* Decode UTF-8 codepoint from a sequence of hex escapes. The
27868 * first byte of the sequence has been decoded to 't'.
27869 *
27870 * Note that UTF-8 validation must be strict according to the
27871 * specification: E5.1 Section 15.1.3, decode algorithm step
27872 * 4.d.vii.8. URIError from non-shortest encodings is also
27873 * specifically noted in the spec.
27874 */
27875
27876 DUK_ASSERT(t >= 0x80);
27877 if (t < 0xc0) {
27878 /* continuation byte */
27879 goto uri_error;
27880 } else if (t < 0xe0) {
27881 /* 110x xxxx; 2 bytes */
27882 utf8_blen = 2;
27883 min_cp = 0x80L;
27884 cp = t & 0x1f;
27885 } else if (t < 0xf0) {
27886 /* 1110 xxxx; 3 bytes */
27887 utf8_blen = 3;
27888 min_cp = 0x800L;
27889 cp = t & 0x0f;
27890 } else if (t < 0xf8) {
27891 /* 1111 0xxx; 4 bytes */
27892 utf8_blen = 4;
27893 min_cp = 0x10000L;
27894 cp = t & 0x07;
27895 } else {
27896 /* extended utf-8 not allowed for URIs */
27897 goto uri_error;
27898 }
27899
27900 if (left < utf8_blen * 3 - 1) {
27901 /* '%xx%xx...%xx', p points to char after first '%' */
27902 goto uri_error;
27903 }
27904
27905 p += 3;
27906 for (i = 1; i < utf8_blen; i++) {
27907 /* p points to digit part ('%xy', p points to 'x') */
27908 t = duk__decode_hex_escape(p, 2);
27909 DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
27910 (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
27911 if (t < 0) {
27912 goto uri_error;
27913 }
27914 if ((t & 0xc0) != 0x80) {
27915 goto uri_error;
27916 }
27917 cp = (cp << 6) + (t & 0x3f);
27918 p += 3;
27919 }
27920 p--; /* p overshoots */
27921 tfm_ctx->p = p;
27922
27923 DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
27924
27925 if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
27926 goto uri_error;
27927 }
27928
27929 /* The E5.1 algorithm checks whether or not a decoded codepoint
27930 * is below 0x80 and perhaps may be in the "reserved" set.
27931 * This seems pointless because the single byte UTF-8 case is
27932 * handled separately, and non-shortest encodings are rejected.
27933 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
27934 * the reserved set.
27935 */
27936
27937 /* utf-8 validation ensures these */
27938 DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
27939
27940 if (cp >= 0x10000L) {
27941 cp -= 0x10000L;
27942 DUK_ASSERT(cp < 0x100000L);
27943
27944 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
27945 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffUL) + 0xdc00L));
27946 } else {
27947 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
27948 }
27949 } else {
27950 DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
27951 }
27952 return;
27953
27954 uri_error:
27955 DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
27956}
27957
27958#ifdef DUK_USE_SECTION_B
27960 DUK_UNREF(udata);
27961
27962 DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
27963
27964 if (cp < 0) {
27965 goto esc_error;
27966 } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
27967 DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
27968 } else if (cp < 0x100L) {
27969 DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27970 &tfm_ctx->bw,
27971 (duk_uint8_t) DUK_ASC_PERCENT,
27972 (duk_uint8_t) duk_uc_nybbles[cp >> 4],
27973 (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
27974 } else if (cp < 0x10000L) {
27975 DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
27976 &tfm_ctx->bw,
27977 (duk_uint8_t) DUK_ASC_PERCENT,
27978 (duk_uint8_t) DUK_ASC_LC_U,
27979 (duk_uint8_t) duk_uc_nybbles[cp >> 12],
27980 (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
27981 (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
27982 (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
27983 } else {
27984 /* Characters outside BMP cannot be escape()'d. We could
27985 * encode them as surrogate pairs (for codepoints inside
27986 * valid UTF-8 range, but not extended UTF-8). Because
27987 * escape() and unescape() are legacy functions, we don't.
27988 */
27989 goto esc_error;
27990 }
27991
27992 return;
27993
27994 esc_error:
27995 DUK_ERROR_TYPE(tfm_ctx->thr, "invalid input");
27996}
27997
28000
28001 DUK_UNREF(udata);
28002
28003 if (cp == (duk_codepoint_t) '%') {
28004 const duk_uint8_t *p = tfm_ctx->p;
28005 duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
28006
28007 if (left >= 5 && p[0] == 'u' &&
28008 ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
28009 cp = (duk_codepoint_t) t;
28010 tfm_ctx->p += 5;
28011 } else if (left >= 2 &&
28012 ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
28013 cp = (duk_codepoint_t) t;
28014 tfm_ctx->p += 2;
28015 }
28017
28018 DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
28019}
28020#endif /* DUK_USE_SECTION_B */
28021
28022/*
28023 * Eval
28024 *
28025 * Eval needs to handle both a "direct eval" and an "indirect eval".
28026 * Direct eval handling needs access to the caller's activation so that its
28027 * lexical environment can be accessed. A direct eval is only possible from
28028 * Ecmascript code; an indirect eval call is possible also from C code.
28029 * When an indirect eval call is made from C code, there may not be a
28030 * calling activation at all which needs careful handling.
28031 */
28032
28034 duk_hthread *thr = (duk_hthread *) ctx;
28035 duk_hstring *h;
28036 duk_activation *act_caller;
28037 duk_activation *act_eval;
28038 duk_activation *act;
28040 duk_hobject *outer_lex_env;
28041 duk_hobject *outer_var_env;
28042 duk_bool_t this_to_global = 1;
28043 duk_small_uint_t comp_flags;
28044 duk_int_t level = -2;
28045
28046 DUK_ASSERT(duk_get_top(ctx) == 1 || duk_get_top(ctx) == 2); /* 2 when called by debugger */
28047 DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */
28048 DUK_ASSERT(((thr->callstack + thr->callstack_top - 1)->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
28049 (thr->callstack_top >= 2)); /* if direct eval, calling activation must exist */
28050
28051 /*
28052 * callstack_top - 1 --> this function
28053 * callstack_top - 2 --> caller (may not exist)
28054 *
28055 * If called directly from C, callstack_top might be 1. If calling
28056 * activation doesn't exist, call must be indirect.
28057 */
28058
28059 h = duk_get_hstring(ctx, 0);
28060 if (!h) {
28061 return 1; /* return arg as-is */
28062 }
28063
28064#if defined(DUK_USE_DEBUGGER_SUPPORT)
28065 /* NOTE: level is used only by the debugger and should never be present
28066 * for an Ecmascript eval().
28067 */
28068 DUK_ASSERT(level == -2); /* by default, use caller's environment */
28069 if (duk_get_top(ctx) >= 2 && duk_is_number(ctx, 1)) {
28070 level = duk_get_int(ctx, 1);
28071 }
28072 DUK_ASSERT(level <= -2); /* This is guaranteed by debugger code. */
28073#endif
28074
28075 /* [ source ] */
28076
28077 comp_flags = DUK_JS_COMPILE_FLAG_EVAL;
28078 act_eval = thr->callstack + thr->callstack_top - 1; /* this function */
28079 if (thr->callstack_top >= (duk_size_t) -level) {
28080 /* Have a calling activation, check for direct eval (otherwise
28081 * assume indirect eval.
28082 */
28083 act_caller = thr->callstack + thr->callstack_top + level; /* caller */
28084 if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
28085 (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
28086 /* Only direct eval inherits strictness from calling code
28087 * (E5.1 Section 10.1.1).
28088 */
28089 comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
28090 }
28091 } else {
28092 DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
28093 }
28094 act_caller = NULL; /* avoid dereference after potential callstack realloc */
28095 act_eval = NULL;
28096
28097 duk_push_hstring_stridx(ctx, DUK_STRIDX_INPUT); /* XXX: copy from caller? */
28098 duk_js_compile(thr,
28099 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
28101 comp_flags);
28102 func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
28103 DUK_ASSERT(func != NULL);
28105
28106 /* [ source template ] */
28107
28108 /* E5 Section 10.4.2 */
28109 DUK_ASSERT(thr->callstack_top >= 1);
28110 act = thr->callstack + thr->callstack_top - 1; /* this function */
28111 if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
28112 DUK_ASSERT(thr->callstack_top >= 2);
28113 act = thr->callstack + thr->callstack_top + level; /* caller */
28114 if (act->lex_env == NULL) {
28115 DUK_ASSERT(act->var_env == NULL);
28116 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
28117
28118 /* this may have side effects, so re-lookup act */
28120 act = thr->callstack + thr->callstack_top + level;
28121 }
28122 DUK_ASSERT(act->lex_env != NULL);
28123 DUK_ASSERT(act->var_env != NULL);
28124
28125 this_to_global = 0;
28126
28127 if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
28128 duk_hobject *new_env;
28129 duk_hobject *act_lex_env;
28130
28131 DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
28132 "var_env and lex_env to a fresh env, "
28133 "this_binding to caller's this_binding"));
28134
28135 act = thr->callstack + thr->callstack_top + level; /* caller */
28136 act_lex_env = act->lex_env;
28137 act = NULL; /* invalidated */
28138
28142 act_lex_env);
28143 new_env = duk_require_hobject(ctx, -1);
28144 DUK_ASSERT(new_env != NULL);
28145 DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO",
28146 (duk_heaphdr *) new_env));
28147
28148 outer_lex_env = new_env;
28149 outer_var_env = new_env;
28150
28151 duk_insert(ctx, 0); /* stash to bottom of value stack to keep new_env reachable for duration of eval */
28152
28153 /* compiler's responsibility */
28155 } else {
28156 DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
28157 "var_env and lex_env to caller's envs, "
28158 "this_binding to caller's this_binding"));
28159
28160 outer_lex_env = act->lex_env;
28161 outer_var_env = act->var_env;
28162
28163 /* compiler's responsibility */
28165 }
28166 } else {
28167 DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
28168 "global object, this_binding to global object"));
28169
28170 this_to_global = 1;
28171 outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
28172 outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
28173 }
28174 act = NULL;
28175
28176 /* Eval code doesn't need an automatic .prototype object. */
28177 duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
28178
28179 /* [ source template closure ] */
28180
28181 if (this_to_global) {
28184 } else {
28185 duk_tval *tv;
28186 DUK_ASSERT(thr->callstack_top >= 2);
28187 act = thr->callstack + thr->callstack_top + level; /* caller */
28188 tv = thr->valstack + act->idx_bottom - 1; /* this is just beneath bottom */
28189 DUK_ASSERT(tv >= thr->valstack);
28190 duk_push_tval(ctx, tv);
28191 }
28192
28193 DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
28194 (duk_heaphdr *) outer_lex_env,
28195 (duk_heaphdr *) outer_var_env,
28196 duk_get_tval(ctx, -1)));
28197
28198 /* [ source template closure this ] */
28199
28200 duk_call_method(ctx, 0);
28201
28202 /* [ source template result ] */
28203
28204 return 1;
28205}
28206
28207/*
28208 * Parsing of ints and floats
28209 */
28210
28212 duk_int32_t radix;
28213 duk_small_uint_t s2n_flags;
28214
28215 DUK_ASSERT_TOP(ctx, 2);
28216 duk_to_string(ctx, 0);
28217
28218 radix = duk_to_int32(ctx, 1);
28219
28220 s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
28226
28227 /* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
28228 *
28229 * Don't autodetect octals (from leading zeroes), require user code to
28230 * provide an explicit radix 8 for parsing octal. See write-up from Mozilla:
28231 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
28232 */
28233
28234 if (radix != 0) {
28235 if (radix < 2 || radix > 36) {
28236 goto ret_nan;
28238 if (radix != 16) {
28239 s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
28240 }
28241 } else {
28242 radix = 10;
28243 }
28244
28245 duk_dup(ctx, 0);
28246 duk_numconv_parse(ctx, radix, s2n_flags);
28247 return 1;
28248
28249 ret_nan:
28250 duk_push_nan(ctx);
28251 return 1;
28252}
28253
28255 duk_small_uint_t s2n_flags;
28256 duk_int32_t radix;
28257
28258 DUK_ASSERT_TOP(ctx, 1);
28259 duk_to_string(ctx, 0);
28260
28261 radix = 10;
28262
28263 /* XXX: check flags */
28264 s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
28274
28275 duk_numconv_parse(ctx, radix, s2n_flags);
28276 return 1;
28277}
28278
28279/*
28280 * Number checkers
28281 */
28285 duk_push_boolean(ctx, DUK_ISNAN(d));
28286 return 1;
28287}
28288
28292 return 1;
28293}
28295/*
28296 * URI handling
28297 */
28298
28302
28306
28309}
28310
28313}
28314
28315#ifdef DUK_USE_SECTION_B
28317 return duk__transform_helper(ctx, duk__transform_callback_escape, (const void *) NULL);
28318}
28321 return duk__transform_helper(ctx, duk__transform_callback_unescape, (const void *) NULL);
28322}
28323#else /* DUK_USE_SECTION_B */
28325 DUK_UNREF(ctx);
28327}
28328
28330 DUK_UNREF(ctx);
28332}
28333#endif /* DUK_USE_SECTION_B */
28334
28335#if defined(DUK_USE_BROWSER_LIKE) && (defined(DUK_USE_FILE_IO) || defined(DUK_USE_DEBUGGER_SUPPORT))
28337 duk_hthread *thr = (duk_hthread *) ctx;
28338 duk_int_t magic;
28339 duk_idx_t nargs;
28340 const duk_uint8_t *buf;
28341 duk_size_t sz_buf;
28342 const char nl = (const char) DUK_ASC_LF;
28343#ifndef DUK_USE_PREFER_SIZE
28344 duk_uint8_t buf_stack[256];
28345#endif
28346#ifdef DUK_USE_FILE_IO
28347 duk_file *f_out;
28348#endif
28349
28350 DUK_UNREF(thr);
28351
28352 magic = duk_get_current_magic(ctx);
28353 DUK_UNREF(magic);
28354
28355 nargs = duk_get_top(ctx);
28356
28357 /* If argument count is 1 and first argument is a buffer, write the buffer
28358 * as raw data into the file without a newline; this allows exact control
28359 * over stdout/stderr without an additional entrypoint (useful for now).
28360 *
28361 * Otherwise current print/alert semantics are to ToString() coerce
28362 * arguments, join them with a single space, and append a newline.
28363 */
28364
28365 if (nargs == 1 && duk_is_buffer(ctx, 0)) {
28366 buf = (const duk_uint8_t *) duk_get_buffer(ctx, 0, &sz_buf);
28367 DUK_ASSERT(buf != NULL);
28368 } else if (nargs > 0) {
28369#ifdef DUK_USE_PREFER_SIZE
28370 /* Compact but lots of churn. */
28372 duk_insert(ctx, 0);
28373 duk_join(ctx, nargs);
28374 duk_push_string(thr, "\n");
28375 duk_concat(ctx, 2);
28376 buf = (const duk_uint8_t *) duk_get_lstring(ctx, -1, &sz_buf);
28377 DUK_ASSERT(buf != NULL);
28378#else /* DUK_USE_PREFER_SIZE */
28379 /* Higher footprint, less churn. */
28380 duk_idx_t i;
28381 duk_size_t sz_str;
28382 const duk_uint8_t *p_str;
28383 duk_uint8_t *p;
28384
28385 sz_buf = (duk_size_t) nargs; /* spaces (nargs - 1) + newline */
28386 for (i = 0; i < nargs; i++) {
28387 (void) duk_to_lstring(ctx, i, &sz_str);
28388 sz_buf += sz_str;
28389 }
28390
28391 if (sz_buf <= sizeof(buf_stack)) {
28392 p = (duk_uint8_t *) buf_stack;
28393 } else {
28394 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sz_buf);
28395 DUK_ASSERT(p != NULL);
28396 }
28397
28398 buf = (const duk_uint8_t *) p;
28399 for (i = 0; i < nargs; i++) {
28400 p_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &sz_str);
28401 DUK_ASSERT(p_str != NULL);
28402 DUK_MEMCPY((void *) p, (const void *) p_str, sz_str);
28403 p += sz_str;
28404 *p++ = (duk_uint8_t) (i == nargs - 1 ? DUK_ASC_LF : DUK_ASC_SPACE);
28405 }
28406 DUK_ASSERT((const duk_uint8_t *) p == buf + sz_buf);
28407#endif /* DUK_USE_PREFER_SIZE */
28408 } else {
28409 buf = (const duk_uint8_t *) &nl;
28410 sz_buf = 1;
28411 }
28412
28413 /* 'buf' contains the string to write, 'sz_buf' contains the length
28414 * (which may be zero).
28415 */
28416 DUK_ASSERT(buf != NULL);
28417
28418 if (sz_buf == 0) {
28419 return 0;
28420 }
28421
28422#ifdef DUK_USE_FILE_IO
28423 f_out = (magic ? DUK_STDERR : DUK_STDOUT);
28424 DUK_FWRITE((const void *) buf, 1, (size_t) sz_buf, f_out);
28425 DUK_FFLUSH(f_out);
28426#endif
28427
28428#if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_PRINTALERT)
28429 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
28430 duk_debug_write_notify(thr, magic ? DUK_DBG_CMD_ALERT : DUK_DBG_CMD_PRINT);
28431 duk_debug_write_string(thr, (const char *) buf, sz_buf);
28432 duk_debug_write_eom(thr);
28433 }
28434#endif
28435 return 0;
28436}
28437#elif defined(DUK_USE_BROWSER_LIKE) /* print provider */
28439 DUK_UNREF(ctx);
28440 return 0;
28441}
28442#else /* print provider */
28444 DUK_UNREF(ctx);
28446}
28447#endif /* print provider */
28448
28449/*
28450 * CommonJS require() and modules support
28451 */
28452
28453#if defined(DUK_USE_COMMONJS_MODULES)
28454DUK_LOCAL void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) {
28455 duk_hthread *thr = (duk_hthread *) ctx;
28456 duk_uint8_t buf[DUK_BI_COMMONJS_MODULE_ID_LIMIT];
28457 duk_uint8_t *p;
28458 duk_uint8_t *q;
28459 duk_uint8_t *q_last; /* last component */
28460 duk_int_t int_rc;
28461
28462 DUK_ASSERT(req_id != NULL);
28463 /* mod_id may be NULL */
28464
28465 /*
28466 * A few notes on the algorithm:
28467 *
28468 * - Terms are not allowed to begin with a period unless the term
28469 * is either '.' or '..'. This simplifies implementation (and
28470 * is within CommonJS modules specification).
28471 *
28472 * - There are few output bound checks here. This is on purpose:
28473 * the resolution input is length checked and the output is never
28474 * longer than the input. The resolved output is written directly
28475 * over the input because it's never longer than the input at any
28476 * point in the algorithm.
28477 *
28478 * - Non-ASCII characters are processed as individual bytes and
28479 * need no special treatment. However, U+0000 terminates the
28480 * algorithm; this is not an issue because U+0000 is not a
28481 * desirable term character anyway.
28482 */
28483
28484 /*
28485 * Set up the resolution input which is the requested ID directly
28486 * (if absolute or no current module path) or with current module
28487 * ID prepended (if relative and current module path exists).
28488 *
28489 * Suppose current module is 'foo/bar' and relative path is './quux'.
28490 * The 'bar' component must be replaced so the initial input here is
28491 * 'foo/bar/.././quux'.
28492 */
28493
28494 if (mod_id != NULL && req_id[0] == '.') {
28495 int_rc = DUK_SNPRINTF((char *) buf, sizeof(buf), "%s/../%s", mod_id, req_id);
28496 } else {
28497 int_rc = DUK_SNPRINTF((char *) buf, sizeof(buf), "%s", req_id);
28498 }
28499 if (int_rc >= (duk_int_t) sizeof(buf) || int_rc < 0) {
28500 /* Potentially truncated, NUL not guaranteed in any case.
28501 * The (int_rc < 0) case should not occur in practice.
28502 */
28503 DUK_DD(DUK_DDPRINT("resolve error: temporary working module ID doesn't fit into resolve buffer"));
28504 goto resolve_error;
28505 }
28506 DUK_ASSERT(DUK_STRLEN((const char *) buf) < sizeof(buf)); /* at most sizeof(buf) - 1 */
28507
28508 DUK_DDD(DUK_DDDPRINT("input module id: '%s'", (const char *) buf));
28509
28510 /*
28511 * Resolution loop. At the top of the loop we're expecting a valid
28512 * term: '.', '..', or a non-empty identifier not starting with a period.
28513 */
28514
28515 p = buf;
28516 q = buf;
28517 for (;;) {
28519
28520 /* Here 'p' always points to the start of a term.
28521 *
28522 * We can also unconditionally reset q_last here: if this is
28523 * the last (non-empty) term q_last will have the right value
28524 * on loop exit.
28525 */
28526
28527 DUK_ASSERT(p >= q); /* output is never longer than input during resolution */
28528
28529 DUK_DDD(DUK_DDDPRINT("resolve loop top: p -> '%s', q=%p, buf=%p",
28530 (const char *) p, (void *) q, (void *) buf));
28531
28532 q_last = q;
28533
28534 c = *p++;
28535 if (DUK_UNLIKELY(c == 0)) {
28536 DUK_DD(DUK_DDPRINT("resolve error: requested ID must end with a non-empty term"));
28537 goto resolve_error;
28538 } else if (DUK_UNLIKELY(c == '.')) {
28539 c = *p++;
28540 if (c == '/') {
28541 /* Term was '.' and is eaten entirely (including dup slashes). */
28542 goto eat_dup_slashes;
28543 }
28544 if (c == '.' && *p == '/') {
28545 /* Term was '..', backtrack resolved name by one component.
28546 * q[-1] = previous slash (or beyond start of buffer)
28547 * q[-2] = last char of previous component (or beyond start of buffer)
28548 */
28549 p++; /* eat (first) input slash */
28550 DUK_ASSERT(q >= buf);
28551 if (q == buf) {
28552 DUK_DD(DUK_DDPRINT("resolve error: term was '..' but nothing to backtrack"));
28553 goto resolve_error;
28554 }
28555 DUK_ASSERT(*(q - 1) == '/');
28556 q--; /* backtrack to last output slash (dups already eliminated) */
28557 for (;;) {
28558 /* Backtrack to previous slash or start of buffer. */
28559 DUK_ASSERT(q >= buf);
28560 if (q == buf) {
28561 break;
28562 }
28563 if (*(q - 1) == '/') {
28564 break;
28565 }
28566 q--;
28567 }
28568 goto eat_dup_slashes;
28569 }
28570 DUK_DD(DUK_DDPRINT("resolve error: term begins with '.' but is not '.' or '..' (not allowed now)"));
28571 goto resolve_error;
28572 } else if (DUK_UNLIKELY(c == '/')) {
28573 /* e.g. require('/foo'), empty terms not allowed */
28574 DUK_DD(DUK_DDPRINT("resolve error: empty term (not allowed now)"));
28575 goto resolve_error;
28576 } else {
28577 for (;;) {
28578 /* Copy term name until end or '/'. */
28579 *q++ = c;
28580 c = *p++;
28581 if (DUK_UNLIKELY(c == 0)) {
28582 /* This was the last term, and q_last was
28583 * updated to match this term at loop top.
28584 */
28585 goto loop_done;
28586 } else if (DUK_UNLIKELY(c == '/')) {
28587 *q++ = '/';
28588 break;
28589 } else {
28590 /* write on next loop */
28591 }
28592 }
28593 }
28594
28595 eat_dup_slashes:
28596 for (;;) {
28597 /* eat dup slashes */
28598 c = *p;
28599 if (DUK_LIKELY(c != '/')) {
28600 break;
28601 }
28602 p++;
28603 }
28604 }
28605 loop_done:
28606 /* Output #1: resolved absolute name */
28607 DUK_ASSERT(q >= buf);
28608 duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
28610 /* Output #2: last component name */
28611 DUK_ASSERT(q >= q_last);
28612 DUK_ASSERT(q_last >= buf);
28613 duk_push_lstring(ctx, (const char *) q_last, (size_t) (q - q_last));
28615 DUK_DD(DUK_DDPRINT("after resolving module name: buf=%p, q_last=%p, q=%p",
28616 (void *) buf, (void *) q_last, (void *) q));
28617 return;
28619 resolve_error:
28620 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "cannot resolve module id: %s", (const char *) req_id);
28622#endif /* DUK_USE_COMMONJS_MODULES */
28623
28624#if defined(DUK_USE_COMMONJS_MODULES)
28625/* Stack indices for better readability */
28626#define DUK__IDX_REQUESTED_ID 0 /* Module id requested */
28627#define DUK__IDX_REQUIRE 1 /* Current require() function */
28628#define DUK__IDX_REQUIRE_ID 2 /* The base ID of the current require() function, resolution base */
28629#define DUK__IDX_RESOLVED_ID 3 /* Resolved, normalized absolute module ID */
28630#define DUK__IDX_LASTCOMP 4 /* Last component name in resolved path */
28631#define DUK__IDX_DUKTAPE 5 /* Duktape object */
28632#define DUK__IDX_MODLOADED 6 /* Duktape.modLoaded[] module cache */
28633#define DUK__IDX_UNDEFINED 7 /* 'undefined', artifact of lookup */
28634#define DUK__IDX_FRESH_REQUIRE 8 /* New require() function for module, updated resolution base */
28635#define DUK__IDX_EXPORTS 9 /* Default exports table */
28636#define DUK__IDX_MODULE 10 /* Module object containing module.exports, etc */
28637
28639 const char *str_req_id; /* requested identifier */
28640 const char *str_mod_id; /* require.id of current module */
28641 duk_int_t pcall_rc;
28642
28643 /* NOTE: we try to minimize code size by avoiding unnecessary pops,
28644 * so the stack looks a bit cluttered in this function. DUK_ASSERT_TOP()
28645 * assertions are used to ensure stack configuration is correct at each
28646 * step.
28647 */
28648
28649 /*
28650 * Resolve module identifier into canonical absolute form.
28651 */
28652
28653 str_req_id = duk_require_string(ctx, DUK__IDX_REQUESTED_ID);
28656 str_mod_id = duk_get_string(ctx, DUK__IDX_REQUIRE_ID); /* ignore non-strings */
28657 DUK_DDD(DUK_DDDPRINT("resolve module id: requested=%!T, currentmodule=%!T",
28660 duk__bi_global_resolve_module_id(ctx, str_req_id, str_mod_id);
28661 str_req_id = NULL;
28662 str_mod_id = NULL;
28663 DUK_DDD(DUK_DDDPRINT("resolved module id: requested=%!T, currentmodule=%!T, result=%!T, lastcomp=%!T",
28668
28669 /* [ requested_id require require.id resolved_id last_comp ] */
28671
28672 /*
28673 * Cached module check.
28674 *
28675 * If module has been loaded or its loading has already begun without
28676 * finishing, return the same cached value ('exports'). The value is
28677 * registered when module load starts so that circular references can
28678 * be supported to some extent.
28679 */
28680
28682 duk_get_prop_stridx(ctx, DUK__IDX_DUKTAPE, DUK_STRIDX_MOD_LOADED); /* Duktape.modLoaded */
28685
28687 if (duk_get_prop(ctx, DUK__IDX_MODLOADED)) {
28688 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */
28689 DUK_DD(DUK_DDPRINT("module already loaded: %!T",
28691 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_EXPORTS); /* return module.exports */
28692 return 1;
28693 }
28695
28696 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined ] */
28697
28698 /*
28699 * Module not loaded (and loading not started previously).
28700 *
28701 * Create a new require() function with 'id' set to resolved ID
28702 * of module being loaded. Also create 'exports' and 'module'
28703 * tables but don't register exports to the loaded table yet.
28704 * We don't want to do that unless the user module search callbacks
28705 * succeeds in finding the module.
28706 */
28707
28708 DUK_D(DUK_DPRINT("loading module %!T, resolution base %!T, requested ID %!T -> resolved ID %!T, last component %!T",
28714
28715 /* Fresh require: require.id is left configurable (but not writable)
28716 * so that is not easy to accidentally tweak it, but it can still be
28717 * done with Object.defineProperty().
28718 *
28719 * XXX: require.id could also be just made non-configurable, as there
28720 * is no practical reason to touch it.
28721 */
28726 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 */
28727
28728 /* Module table:
28729 * - module.exports: initial exports table (may be replaced by user)
28730 * - module.id is non-writable and non-configurable, as the CommonJS
28731 * spec suggests this if possible
28732 * - module.filename: not set, defaults to resolved ID if not explicitly
28733 * set by modSearch() (note capitalization, not .fileName, matches Node.js)
28734 * - module.name: not set, defaults to last component of resolved ID if
28735 * not explicitly set by modSearch()
28736 */
28737 duk_push_object(ctx); /* exports */
28738 duk_push_object(ctx); /* module */
28741 duk_dup(ctx, DUK__IDX_RESOLVED_ID); /* resolved id: require(id) must return this same module */
28742 duk_xdef_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE); /* module.id = resolved_id */
28743 duk_compact(ctx, DUK__IDX_MODULE); /* module table remains registered to modLoaded, minimize its size */
28745
28746 DUK_DD(DUK_DDPRINT("module table created: %!T", duk_get_tval(ctx, DUK__IDX_MODULE)));
28747
28748 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module ] */
28749
28750 /* Register the module table early to modLoaded[] so that we can
28751 * support circular references even in modSearch(). If an error
28752 * is thrown, we'll delete the reference.
28753 */
28756 duk_put_prop(ctx, DUK__IDX_MODLOADED); /* Duktape.modLoaded[resolved_id] = module */
28757
28758 /*
28759 * Call user provided module search function and build the wrapped
28760 * module source code (if necessary). The module search function
28761 * can be used to implement pure Ecmacsript, pure C, and mixed
28762 * Ecmascript/C modules.
28763 *
28764 * The module search function can operate on the exports table directly
28765 * (e.g. DLL code can register values to it). It can also return a
28766 * string which is interpreted as module source code (if a non-string
28767 * is returned the module is assumed to be a pure C one). If a module
28768 * cannot be found, an error must be thrown by the user callback.
28769 *
28770 * Because Duktape.modLoaded[] already contains the module being
28771 * loaded, circular references for C modules should also work
28772 * (although expected to be quite rare).
28773 */
28774
28775 duk_push_string(ctx, "(function(require,exports,module){");
28776
28777 /* Duktape.modSearch(resolved_id, fresh_require, exports, module). */
28778 duk_get_prop_stridx(ctx, DUK__IDX_DUKTAPE, DUK_STRIDX_MOD_SEARCH); /* Duktape.modSearch */
28782 duk_dup(ctx, DUK__IDX_MODULE); /* [ ... Duktape.modSearch resolved_id last_comp fresh_require exports module ] */
28783 pcall_rc = duk_pcall(ctx, 4 /*nargs*/); /* -> [ ... source ] */
28785
28786 if (pcall_rc != DUK_EXEC_SUCCESS) {
28787 /* Delete entry in Duktape.modLoaded[] and rethrow. */
28788 goto delete_rethrow;
28789 }
28790
28791 /* If user callback did not return source code, module loading
28792 * is finished (user callback initialized exports table directly).
28793 */
28794 if (!duk_is_string(ctx, -1)) {
28795 /* User callback did not return source code, so module loading
28796 * is finished: just update modLoaded with final module.exports
28797 * and we're done.
28798 */
28799 goto return_exports;
28800 }
28801
28802 /* Finish the wrapped module source. Force module.filename as the
28803 * function .fileName so it gets set for functions defined within a
28804 * module. This also ensures loggers created within the module get
28805 * the module ID (or overridden filename) as their default logger name.
28806 * (Note capitalization: .filename matches Node.js while .fileName is
28807 * used elsewhere in Duktape.)
28808 */
28809 duk_push_string(ctx, "})");
28810 duk_concat(ctx, 3);
28812 /* module.filename for .fileName, default to resolved ID if
28813 * not present.
28814 */
28815 duk_pop(ctx);
28817 }
28819
28820 /* Module has now evaluated to a wrapped module function. Force its
28821 * .name to match module.name (defaults to last component of resolved
28822 * ID) so that it is shown in stack traces too. Note that we must not
28823 * introduce an actual name binding into the function scope (which is
28824 * usually the case with a named function) because it would affect the
28825 * scope seen by the module and shadow accesses to globals of the same name.
28826 * This is now done by compiling the function as anonymous and then forcing
28827 * its .name without setting a "has name binding" flag.
28828 */
28829
28832 /* module.name for .name, default to last component if
28833 * not present.
28834 */
28835 duk_pop(ctx);
28837 }
28839
28840 /*
28841 * Call the wrapped module function.
28842 *
28843 * Use a protected call so that we can update Duktape.modLoaded[resolved_id]
28844 * even if the module throws an error.
28845 */
28846
28847 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */
28849
28850 duk_dup(ctx, DUK__IDX_EXPORTS); /* exports (this binding) */
28851 duk_dup(ctx, DUK__IDX_FRESH_REQUIRE); /* fresh require (argument) */
28852 duk_get_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_EXPORTS); /* relookup exports from module.exports in case it was changed by modSearch */
28853 duk_dup(ctx, DUK__IDX_MODULE); /* module (argument) */
28855
28856 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */
28857
28858 pcall_rc = duk_pcall_method(ctx, 3 /*nargs*/);
28859 if (pcall_rc != DUK_EXEC_SUCCESS) {
28860 /* Module loading failed. Node.js will forget the module
28861 * registration so that another require() will try to load
28862 * the module again. Mimic that behavior.
28863 */
28864 goto delete_rethrow;
28865 }
28866
28867 /* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */
28869
28870 /* fall through */
28871
28872 return_exports:
28874 duk_compact(ctx, -1); /* compact the exports table */
28875 return 1; /* return module.exports */
28876
28877 delete_rethrow:
28879 duk_del_prop(ctx, DUK__IDX_MODLOADED); /* delete Duktape.modLoaded[resolved_id] */
28880 duk_throw(ctx); /* rethrow original error */
28881 return 0; /* not reachable */
28882}
28883
28884#undef DUK__IDX_REQUESTED_ID
28885#undef DUK__IDX_REQUIRE
28886#undef DUK__IDX_REQUIRE_ID
28887#undef DUK__IDX_RESOLVED_ID
28888#undef DUK__IDX_LASTCOMP
28889#undef DUK__IDX_DUKTAPE
28890#undef DUK__IDX_MODLOADED
28891#undef DUK__IDX_UNDEFINED
28892#undef DUK__IDX_FRESH_REQUIRE
28893#undef DUK__IDX_EXPORTS
28894#undef DUK__IDX_MODULE
28895#else
28897 DUK_UNREF(ctx);
28899}
28900#endif /* DUK_USE_COMMONJS_MODULES */
28901#line 1 "duk_bi_json.c"
28902/*
28903 * JSON built-ins.
28904 *
28905 * See doc/json.rst.
28906 *
28907 * Codepoints are handled as duk_uint_fast32_t to ensure that the full
28908 * unsigned 32-bit range is supported. This matters to e.g. JX.
28910 * Input parsing doesn't do an explicit end-of-input check at all. This is
28911 * safe: input string data is always NUL-terminated (0x00) and valid JSON
28912 * inputs never contain plain NUL characters, so that as long as syntax checks
28913 * are correct, we'll never read past the NUL. This approach reduces code size
28914 * and improves parsing performance, but it's critical that syntax checks are
28915 * indeed correct!
28916 */
28917
28918/* include removed: duk_internal.h */
28919
28920/*
28921 * Local defines and forward declarations.
28922 */
28923
28924#define DUK__JSON_DECSTR_BUFSIZE 128
28925#define DUK__JSON_DECSTR_CHUNKSIZE 64
28926#define DUK__JSON_ENCSTR_CHUNKSIZE 64
28927#define DUK__JSON_STRINGIFY_BUFSIZE 128
28928#define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */
28929
28932DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
28933DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
28938#ifdef DUK_USE_JX
28942#endif
28950
28955#if defined(DUK_USE_FASTINT)
28956DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
28957#endif
28959DUK_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);
28969#if defined(DUK_USE_FASTINT)
28970DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
28971#endif
28972#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
28974DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
28976#endif
28978
28979/*
28980 * Helper tables
28981 */
28982
28983#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
28984DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
28985 /* 0x00 ... 0x7f: as is
28986 * 0x80: escape generically
28987 * 0x81: slow path
28988 * 0xa0 ... 0xff: backslash + one char
28989 */
28990
28991 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
28992 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
28993 0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
28994 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
28995 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
28996 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
28997 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
28998 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
28999 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29000 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29001 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29002 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29003 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29004 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29005 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29006 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
29007};
29008#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
29009DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
29014};
29015#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
29016
29017#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
29018DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
29019 /* 0x00: slow path
29020 * other: as is
29021 */
29022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29024 0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
29025 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
29026 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
29027 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
29028 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
29029 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
29030 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
29031 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
29032 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
29033 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
29034 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
29035 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
29036 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
29037 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
29038};
29039#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
29040
29041#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
29042DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
29043 /* 0x00: finish (non-white)
29044 * 0x01: continue
29045 */
29046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
29047 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29048 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29049 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29050 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29052 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29054 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29055 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29056 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29057 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
29062};
29063#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
29064
29065#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
29066DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
29067 /* 0x00: finish (not part of number)
29068 * 0x01: continue
29069 */
29070 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29071 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
29073 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29074 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29076 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29080 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29082 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29084 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
29086};
29087#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29088
29089/*
29090 * Parsing implementation.
29091 *
29092 * JSON lexer is now separate from duk_lexer.c because there are numerous
29093 * small differences making it difficult to share the lexer.
29095 * The parser here works with raw bytes directly; this works because all
29096 * JSON delimiters are ASCII characters. Invalid xUTF-8 encoded values
29097 * inside strings will be passed on without normalization; this is not a
29098 * compliance concern because compliant inputs will always be valid
29099 * CESU-8 encodings.
29100 */
29101
29103 /* Shared handler to minimize parser size. Cause will be
29104 * hidden, unfortunately, but we'll have an offset which
29105 * is often quite enough.
29106 */
29108 (long) (js_ctx->p - js_ctx->p_start));
29109}
29110
29112 const duk_uint8_t *p;
29113 duk_uint8_t t;
29114
29115 p = js_ctx->p;
29116 for (;;) {
29117 DUK_ASSERT(p <= js_ctx->p_end);
29118 t = *p;
29119
29120#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
29121 /* This fast path is pretty marginal in practice.
29122 * XXX: candidate for removal.
29123 */
29124 DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */
29125 if (duk__json_eatwhite_lookup[t] == 0) {
29126 break;
29127 }
29128#else /* DUK_USE_JSON_EATWHITE_FASTPATH */
29129 if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
29130 /* NUL also comes here. Comparison order matters, 0x20
29131 * is most common whitespace.
29132 */
29133 break;
29135#endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
29136 p++;
29137 }
29138 js_ctx->p = p;
29139}
29141DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
29142 DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
29143 return *js_ctx->p;
29144}
29145
29146DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
29147 DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
29148 return *js_ctx->p++;
29149}
29150
29152 duk__dec_eat_white(js_ctx);
29153 return duk__dec_get(js_ctx);
29154}
29155
29156/* For JX, expressing the whole unsigned 32-bit range matters. */
29159 duk_uint_fast32_t res = 0;
29160 duk_uint8_t x;
29162
29163 for (i = 0; i < n; i++) {
29164 /* XXX: share helper from lexer; duk_lexer.c / hexval(). */
29165
29166 x = duk__dec_get(js_ctx);
29167 DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
29168 (long) i, (long) n, (long) res, (long) x));
29169
29170 /* x == 0x00 (EOF) causes syntax_error */
29171 DUK_ASSERT(duk_hex_dectab[0] == -1);
29172 t = duk_hex_dectab[x & 0xff];
29173 if (DUK_LIKELY(t >= 0)) {
29174 res = (res * 16) + t;
29175 } else {
29176 /* catches EOF and invalid digits */
29177 goto syntax_error;
29178 }
29179 }
29180
29181 DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
29182 return res;
29183
29184 syntax_error:
29185 duk__dec_syntax_error(js_ctx);
29187 return 0;
29188}
29189
29191 duk_hstring *h;
29192 const duk_uint8_t *p;
29193 duk_uint8_t x, y;
29194
29195 /* First character has already been eaten and checked by the caller.
29196 * We can scan until a NUL in stridx string because no built-in strings
29197 * have internal NULs.
29198 */
29199
29200 DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */
29202 h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
29203 DUK_ASSERT(h != NULL);
29204
29205 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
29206 DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */
29207
29208 for (;;) {
29209 x = *p;
29210 if (x == 0) {
29211 break;
29212 }
29213 y = duk__dec_get(js_ctx);
29214 if (x != y) {
29215 /* Catches EOF of JSON input. */
29216 goto syntax_error;
29217 }
29218 p++;
29219 }
29220
29221 return;
29222
29223 syntax_error:
29224 duk__dec_syntax_error(js_ctx);
29226}
29227
29230
29231 /* EOF (-1) will be cast to an unsigned value first
29232 * and then re-cast for the switch. In any case, it
29233 * will match the default case (syntax error).
29234 */
29235 cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
29236 switch ((int) cp) {
29237 case DUK_ASC_BACKSLASH: break;
29238 case DUK_ASC_DOUBLEQUOTE: break;
29239 case DUK_ASC_SLASH: break;
29240 case DUK_ASC_LC_T: cp = 0x09; break;
29241 case DUK_ASC_LC_N: cp = 0x0a; break;
29242 case DUK_ASC_LC_R: cp = 0x0d; break;
29243 case DUK_ASC_LC_F: cp = 0x0c; break;
29244 case DUK_ASC_LC_B: cp = 0x08; break;
29245 case DUK_ASC_LC_U: {
29246 cp = duk__dec_decode_hex_escape(js_ctx, 4);
29247 break;
29248 }
29249#ifdef DUK_USE_JX
29250 case DUK_ASC_UC_U: {
29251 if (js_ctx->flag_ext_custom) {
29252 cp = duk__dec_decode_hex_escape(js_ctx, 8);
29253 } else {
29254 return 1; /* syntax error */
29255 }
29256 break;
29257 }
29258 case DUK_ASC_LC_X: {
29259 if (js_ctx->flag_ext_custom) {
29261 } else {
29262 return 1; /* syntax error */
29263 }
29264 break;
29265 }
29266#endif /* DUK_USE_JX */
29267 default:
29268 /* catches EOF (0x00) */
29269 return 1; /* syntax error */
29270 }
29271
29272 DUK_RAW_WRITE_XUTF8(*ext_p, cp);
29273
29274 return 0;
29275}
29276
29278 duk_hthread *thr = js_ctx->thr;
29279 duk_context *ctx = (duk_context *) thr;
29280 duk_bufwriter_ctx bw_alloc;
29282 duk_uint8_t *q;
29283
29284 /* '"' was eaten by caller */
29285
29286 /* Note that we currently parse -bytes-, not codepoints.
29287 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
29288 * so they'll simply pass through (valid UTF-8 or not).
29289 */
29290
29291 bw = &bw_alloc;
29293 q = DUK_BW_GET_PTR(js_ctx->thr, bw);
29294
29295#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
29296 for (;;) {
29297 duk_small_uint_t safe;
29298 duk_uint8_t b, x;
29299 const duk_uint8_t *p;
29300
29301 /* Select a safe loop count where no output checks are
29302 * needed assuming we won't encounter escapes. Input
29303 * bound checks are not necessary as a NUL (guaranteed)
29304 * will cause a SyntaxError before we read out of bounds.
29305 */
29306
29308
29309 /* Ensure space for 1:1 output plus one escape. */
29310 q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
29311
29312 p = js_ctx->p; /* temp copy, write back for next loop */
29313 for (;;) {
29314 if (safe == 0) {
29315 js_ctx->p = p;
29316 break;
29317 }
29318 safe--;
29319
29320 /* End of input (NUL) goes through slow path and causes SyntaxError. */
29322
29323 b = *p++;
29325 if (DUK_LIKELY(x != 0)) {
29326 /* Fast path, decode as is. */
29327 *q++ = b;
29328 } else if (b == DUK_ASC_DOUBLEQUOTE) {
29329 js_ctx->p = p;
29330 goto found_quote;
29331 } else if (b == DUK_ASC_BACKSLASH) {
29332 /* We've ensured space for one escaped input; then
29333 * bail out and recheck (this makes escape handling
29334 * quite slow but it's uncommon).
29335 */
29336 js_ctx->p = p;
29337 if (duk__dec_string_escape(js_ctx, &q) != 0) {
29338 goto syntax_error;
29339 }
29340 break;
29341 } else {
29342 js_ctx->p = p;
29343 goto syntax_error;
29344 }
29345 }
29346 }
29347 found_quote:
29348#else /* DUK_USE_JSON_DECSTRING_FASTPATH */
29349 for (;;) {
29350 duk_uint8_t x;
29351
29353
29354 x = duk__dec_get(js_ctx);
29355
29356 if (x == DUK_ASC_DOUBLEQUOTE) {
29357 break;
29358 } else if (x == DUK_ASC_BACKSLASH) {
29359 if (duk__dec_string_escape(js_ctx, &q) != 0) {
29360 goto syntax_error;
29361 }
29362 } else if (x < 0x20) {
29363 /* catches EOF (NUL) */
29364 goto syntax_error;
29365 } else {
29366 *q++ = (duk_uint8_t) x;
29367 }
29368 }
29369#endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
29371 DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
29372 duk_to_string(ctx, -1);
29373
29374 /* [ ... str ] */
29375
29376 return;
29377
29378 syntax_error:
29379 duk__dec_syntax_error(js_ctx);
29381}
29382
29383#ifdef DUK_USE_JX
29384/* Decode a plain string consisting entirely of identifier characters.
29385 * Used to parse plain keys (e.g. "foo: 123").
29386 */
29388 duk_hthread *thr = js_ctx->thr;
29389 duk_context *ctx = (duk_context *) thr;
29390 const duk_uint8_t *p;
29392
29393 /* Caller has already eaten the first char so backtrack one byte. */
29394
29395 js_ctx->p--; /* safe */
29396 p = js_ctx->p;
29397
29398 /* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
29399 * parsing (which is correct except if there are non-shortest encodings).
29400 * There is also no need to check explicitly for end of input buffer as
29401 * the input is NUL padded and NUL will exit the parsing loop.
29402 *
29403 * Because no unescaping takes place, we can just scan to the end of the
29404 * plain string and intern from the input buffer.
29405 */
29406
29407 for (;;) {
29408 x = *p;
29409
29410 /* There is no need to check the first character specially here
29411 * (i.e. reject digits): the caller only accepts valid initial
29412 * characters and won't call us if the first character is a digit.
29413 * This also ensures that the plain string won't be empty.
29414 */
29415
29417 break;
29418 }
29419 p++;
29420 }
29421
29422 duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
29423 js_ctx->p = p;
29424
29425 /* [ ... str ] */
29426}
29427#endif /* DUK_USE_JX */
29428
29429#ifdef DUK_USE_JX
29431 duk_hthread *thr = js_ctx->thr;
29432 duk_context *ctx = (duk_context *) thr;
29433 const duk_uint8_t *p;
29435 void *voidptr;
29436
29437 /* Caller has already eaten the first character ('(') which we don't need. */
29438
29439 p = js_ctx->p;
29440
29441 for (;;) {
29442 x = *p;
29443
29444 /* Assume that the native representation never contains a closing
29445 * parenthesis.
29446 */
29447
29448 if (x == DUK_ASC_RPAREN) {
29449 break;
29450 } else if (x <= 0) {
29451 /* NUL term or -1 (EOF), NUL check would suffice */
29452 goto syntax_error;
29453 }
29454 p++;
29455 }
29456
29457 /* There is no need to NUL delimit the sscanf() call: trailing garbage is
29458 * ignored and there is always a NUL terminator which will force an error
29459 * if no error is encountered before it. It's possible that the scan
29460 * would scan further than between [js_ctx->p,p[ though and we'd advance
29461 * by less than the scanned value.
29462 *
29463 * Because pointers are platform specific, a failure to scan a pointer
29464 * results in a null pointer which is a better placeholder than a missing
29465 * value or an error.
29466 */
29468 voidptr = NULL;
29469 (void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
29470 duk_push_pointer(ctx, voidptr);
29471 js_ctx->p = p + 1; /* skip ')' */
29472
29473 /* [ ... ptr ] */
29474
29475 return;
29476
29477 syntax_error:
29478 duk__dec_syntax_error(js_ctx);
29480}
29481#endif /* DUK_USE_JX */
29482
29483#ifdef DUK_USE_JX
29485 duk_hthread *thr = js_ctx->thr;
29486 duk_context *ctx = (duk_context *) thr;
29487 const duk_uint8_t *p;
29488 duk_uint8_t *buf;
29489 duk_size_t src_len;
29491
29492 /* Caller has already eaten the first character ('|') which we don't need. */
29493
29494 p = js_ctx->p;
29495
29496 /* XXX: Would be nice to share the fast path loop from duk_hex_decode()
29497 * and avoid creating a temporary buffer. However, there are some
29498 * differences which prevent trivial sharing:
29499 *
29500 * - Pipe char detection
29501 * - EOF detection
29502 * - Unknown length of input and output
29503 *
29504 * The best approach here would be a bufwriter and a reasonaly sized
29505 * safe inner loop (e.g. 64 output bytes at a time).
29506 */
29507
29508 for (;;) {
29509 x = *p;
29510
29511 /* This loop intentionally does not ensure characters are valid
29512 * ([0-9a-fA-F]) because the hex decode call below will do that.
29513 */
29514 if (x == DUK_ASC_PIPE) {
29515 break;
29516 } else if (x <= 0) {
29517 /* NUL term or -1 (EOF), NUL check would suffice */
29518 goto syntax_error;
29519 }
29520 p++;
29521 }
29522
29523 src_len = (duk_size_t) (p - js_ctx->p);
29524 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_len);
29526 DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);
29527 duk_hex_decode(ctx, -1);
29528
29529 js_ctx->p = p + 1; /* skip '|' */
29530
29531 /* [ ... buf ] */
29532
29533 return;
29534
29535 syntax_error:
29536 duk__dec_syntax_error(js_ctx);
29538}
29539#endif /* DUK_USE_JX */
29540
29541/* Parse a number, other than NaN or +/- Infinity */
29543 duk_context *ctx = (duk_context *) js_ctx->thr;
29544 const duk_uint8_t *p_start;
29545 const duk_uint8_t *p;
29546 duk_uint8_t x;
29547 duk_small_uint_t s2n_flags;
29548
29549 DUK_DDD(DUK_DDDPRINT("parse_number"));
29550
29551 p_start = js_ctx->p;
29552
29553 /* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
29554 * string for strict number parsing.
29555 */
29556
29557 p = js_ctx->p;
29558 for (;;) {
29559 x = *p;
29560
29561 DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
29562 (const void *) p_start, (const void *) p,
29563 (const void *) js_ctx->p_end, (long) x));
29564
29565#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
29566 /* This fast path is pretty marginal in practice.
29567 * XXX: candidate for removal.
29568 */
29569 DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */
29570 if (duk__json_decnumber_lookup[x] == 0) {
29571 break;
29572 }
29573#else /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29574 if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
29575 (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
29576 x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
29577 /* Plus sign must be accepted for positive exponents
29578 * (e.g. '1.5e+2'). This clause catches NULs.
29579 */
29580 break;
29581 }
29582#endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29583 p++; /* safe, because matched (NUL causes a break) */
29584 }
29585 js_ctx->p = p;
29586
29587 DUK_ASSERT(js_ctx->p > p_start);
29588 duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (p - p_start));
29589
29591 DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */
29593
29594 DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
29595 (duk_tval *) duk_get_tval(ctx, -1)));
29596 duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
29597 if (duk_is_nan(ctx, -1)) {
29598 duk__dec_syntax_error(js_ctx);
29599 }
29600 DUK_ASSERT(duk_is_number(ctx, -1));
29601 DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
29602 (duk_tval *) duk_get_tval(ctx, -1)));
29603
29604 /* [ ... num ] */
29605}
29606
29608 duk_context *ctx = (duk_context *) js_ctx->thr;
29610
29611 /* c recursion check */
29613 DUK_ASSERT(js_ctx->recursion_depth >= 0);
29614 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
29615 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
29617 }
29618 js_ctx->recursion_depth++;
29619}
29620
29622 /* c recursion check */
29623
29624 DUK_ASSERT(js_ctx->recursion_depth > 0);
29625 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
29626 js_ctx->recursion_depth--;
29627}
29628
29630 duk_context *ctx = (duk_context *) js_ctx->thr;
29631 duk_int_t key_count; /* XXX: a "first" flag would suffice */
29632 duk_uint8_t x;
29633
29634 DUK_DDD(DUK_DDDPRINT("parse_object"));
29635
29636 duk__dec_objarr_entry(js_ctx);
29637
29638 duk_push_object(ctx);
29639
29640 /* Initial '{' has been checked and eaten by caller. */
29641
29642 key_count = 0;
29643 for (;;) {
29644 x = duk__dec_get_nonwhite(js_ctx);
29645
29646 DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
29647 (duk_tval *) duk_get_tval(ctx, -1),
29648 (long) x, (long) key_count));
29649
29650 /* handle comma and closing brace */
29651
29652 if (x == DUK_ASC_COMMA && key_count > 0) {
29653 /* accept comma, expect new value */
29654 x = duk__dec_get_nonwhite(js_ctx);
29655 } else if (x == DUK_ASC_RCURLY) {
29656 /* eat closing brace */
29657 break;
29658 } else if (key_count == 0) {
29659 /* accept anything, expect first value (EOF will be
29660 * caught by key parsing below.
29661 */
29662 ;
29663 } else {
29664 /* catches EOF (NUL) and initial comma */
29665 goto syntax_error;
29666 }
29667
29668 /* parse key and value */
29669
29670 if (x == DUK_ASC_DOUBLEQUOTE) {
29671 duk__dec_string(js_ctx);
29672#ifdef DUK_USE_JX
29673 } else if (js_ctx->flag_ext_custom &&
29675 duk__dec_plain_string(js_ctx);
29676#endif
29677 } else {
29678 goto syntax_error;
29679 }
29680
29681 /* [ ... obj key ] */
29682
29683 x = duk__dec_get_nonwhite(js_ctx);
29684 if (x != DUK_ASC_COLON) {
29685 goto syntax_error;
29686 }
29687
29688 duk__dec_value(js_ctx);
29689
29690 /* [ ... obj key val ] */
29691
29692 duk_xdef_prop_wec(ctx, -3);
29693
29694 /* [ ... obj ] */
29696 key_count++;
29697 }
29698
29699 /* [ ... obj ] */
29700
29701 DUK_DDD(DUK_DDDPRINT("parse_object: final object 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_uarridx_t arr_idx;
29715 duk_uint8_t x;
29716
29717 DUK_DDD(DUK_DDDPRINT("parse_array"));
29718
29719 duk__dec_objarr_entry(js_ctx);
29720
29721 duk_push_array(ctx);
29722
29723 /* Initial '[' has been checked and eaten by caller. */
29724
29725 arr_idx = 0;
29726 for (;;) {
29727 x = duk__dec_get_nonwhite(js_ctx);
29728
29729 DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
29730 (duk_tval *) duk_get_tval(ctx, -1),
29731 (long) x, (long) arr_idx));
29732
29733 /* handle comma and closing bracket */
29734
29735 if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
29736 /* accept comma, expect new value */
29737 ;
29738 } else if (x == DUK_ASC_RBRACKET) {
29739 /* eat closing bracket */
29740 break;
29741 } else if (arr_idx == 0) {
29742 /* accept anything, expect first value (EOF will be
29743 * caught by duk__dec_value() below.
29744 */
29745 js_ctx->p--; /* backtrack (safe) */
29746 } else {
29747 /* catches EOF (NUL) and initial comma */
29748 goto syntax_error;
29749 }
29750
29751 /* parse value */
29752
29753 duk__dec_value(js_ctx);
29754
29755 /* [ ... arr val ] */
29756
29757 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
29758 arr_idx++;
29759 }
29760
29761 /* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
29762 * set the values.
29764
29765 duk_set_length(ctx, -1, arr_idx);
29766
29767 /* [ ... arr ] */
29768
29769 DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
29770 (duk_tval *) duk_get_tval(ctx, -1)));
29771
29772 duk__dec_objarr_exit(js_ctx);
29773 return;
29774
29775 syntax_error:
29776 duk__dec_syntax_error(js_ctx);
29778}
29779
29781 duk_context *ctx = (duk_context *) js_ctx->thr;
29782 duk_uint8_t x;
29783
29784 x = duk__dec_get_nonwhite(js_ctx);
29785
29786 DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
29787
29788 /* Note: duk__dec_req_stridx() backtracks one char */
29789
29790 if (x == DUK_ASC_DOUBLEQUOTE) {
29791 duk__dec_string(js_ctx);
29792 } else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
29793#ifdef DUK_USE_JX
29794 if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
29795 duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */
29797 } else {
29798#else
29799 { /* unconditional block */
29800#endif
29801 /* We already ate 'x', so backup one byte. */
29802 js_ctx->p--; /* safe */
29803 duk__dec_number(js_ctx);
29804 }
29805 } else if (x == DUK_ASC_LC_T) {
29807 duk_push_true(ctx);
29808 } else if (x == DUK_ASC_LC_F) {
29810 duk_push_false(ctx);
29811 } else if (x == DUK_ASC_LC_N) {
29813 duk_push_null(ctx);
29814#ifdef DUK_USE_JX
29815 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
29817 duk_push_undefined(ctx);
29818 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
29820 duk_push_nan(ctx);
29821 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
29824 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
29825 duk__dec_pointer(js_ctx);
29826 } else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
29827 duk__dec_buffer(js_ctx);
29828#endif
29829 } else if (x == DUK_ASC_LCURLY) {
29830 duk__dec_object(js_ctx);
29831 } else if (x == DUK_ASC_LBRACKET) {
29832 duk__dec_array(js_ctx);
29833 } else {
29834 /* catches EOF (NUL) */
29835 goto syntax_error;
29836 }
29837
29838 duk__dec_eat_white(js_ctx);
29839
29840 /* [ ... val ] */
29841 return;
29842
29843 syntax_error:
29844 duk__dec_syntax_error(js_ctx);
29846}
29847
29848/* Recursive value reviver, implements the Walk() algorithm. No C recursion
29849 * check is done here because the initial parsing step will already ensure
29850 * there is a reasonable limit on C recursion depth and hence object depth.
29851 */
29853 duk_context *ctx = (duk_context *) js_ctx->thr;
29854 duk_hobject *h;
29855 duk_uarridx_t i, arr_len;
29856
29857 DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
29858 (long) duk_get_top(ctx),
29859 (duk_tval *) duk_get_tval(ctx, -2),
29860 (duk_tval *) duk_get_tval(ctx, -1)));
29861
29862 duk_dup_top(ctx);
29863 duk_get_prop(ctx, -3); /* -> [ ... holder name val ] */
29864
29865 h = duk_get_hobject(ctx, -1);
29866 if (h != NULL) {
29868 arr_len = (duk_uarridx_t) duk_get_length(ctx, -1);
29869 for (i = 0; i < arr_len; i++) {
29870 /* [ ... holder name val ] */
29871
29872 DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
29873 (long) duk_get_top(ctx), (long) i, (long) arr_len,
29874 (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
29875 (duk_tval *) duk_get_tval(ctx, -1)));
29876
29877 /* XXX: push_uint_string / push_u32_string */
29878 duk_dup_top(ctx);
29879 duk_push_uint(ctx, (duk_uint_t) i);
29880 duk_to_string(ctx, -1); /* -> [ ... holder name val val ToString(i) ] */
29881 duk__dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */
29882
29883 if (duk_is_undefined(ctx, -1)) {
29884 duk_pop(ctx);
29885 duk_del_prop_index(ctx, -1, i);
29886 } else {
29887 /* XXX: duk_xdef_prop_index_wec() would be more appropriate
29888 * here but it currently makes some assumptions that might
29889 * not hold (e.g. that previous property is not an accessor).
29890 */
29891 duk_put_prop_index(ctx, -2, i);
29892 }
29893 }
29894 } else {
29895 /* [ ... holder name val ] */
29896 duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
29897 while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
29898 DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
29899 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -5),
29900 (duk_tval *) duk_get_tval(ctx, -4), (duk_tval *) duk_get_tval(ctx, -3),
29901 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
29902
29903 /* [ ... holder name val enum obj_key ] */
29904 duk_dup(ctx, -3);
29905 duk_dup(ctx, -2);
29906
29907 /* [ ... holder name val enum obj_key val obj_key ] */
29908 duk__dec_reviver_walk(js_ctx);
29909
29910 /* [ ... holder name val enum obj_key new_elem ] */
29911 if (duk_is_undefined(ctx, -1)) {
29912 duk_pop(ctx);
29913 duk_del_prop(ctx, -3);
29914 } else {
29915 /* XXX: duk_xdef_prop_index_wec() would be more appropriate
29916 * here but it currently makes some assumptions that might
29917 * not hold (e.g. that previous property is not an accessor).
29918 *
29919 * Using duk_put_prop() works incorrectly with '__proto__'
29920 * if the own property with that name has been deleted. This
29921 * does not happen normally, but a clever reviver can trigger
29922 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
29923 */
29924 duk_put_prop(ctx, -4);
29925 }
29926 }
29927 duk_pop(ctx); /* pop enum */
29931 /* [ ... holder name val ] */
29933 duk_dup(ctx, js_ctx->idx_reviver);
29934 duk_insert(ctx, -4); /* -> [ ... reviver holder name val ] */
29935 duk_call_method(ctx, 2); /* -> [ ... res ] */
29936
29937 DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
29938 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -1)));
29939}
29940
29942 * Stringify implementation.
29943 */
29944
29945#define DUK__EMIT_1(js_ctx,ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
29946#define DUK__EMIT_2(js_ctx,ch1,ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
29947#define DUK__EMIT_HSTR(js_ctx,h) duk__emit_hstring((js_ctx), (h))
29948#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
29949#define DUK__EMIT_CSTR(js_ctx,p) duk__emit_cstring((js_ctx), (p))
29950#endif
29951#define DUK__EMIT_STRIDX(js_ctx,i) duk__emit_stridx((js_ctx), (i))
29952#define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx))
29953
29955 DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
29956}
29957
29959 DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
29960}
29961
29963 DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
29964}
29965
29966#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
29967DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
29968 DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
29969}
29970#endif
29973 duk_hstring *h;
29974
29975 DUK_ASSERT_DISABLE(stridx >= 0); /* unsigned */
29977 h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
29978 DUK_ASSERT(h != NULL);
29979
29980 DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
29981}
29982
29984 DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
29985 DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
29986}
29987
29988#define DUK__MKESC(nybbles,esc1,esc2) \
29989 (((duk_uint_fast32_t) (nybbles)) << 16) | \
29990 (((duk_uint_fast32_t) (esc1)) << 8) | \
29991 ((duk_uint_fast32_t) (esc2))
29992
29993DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {
29995 duk_small_uint_t dig;
29996
29997 DUK_UNREF(js_ctx);
29998
29999 /* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
30000
30001 /* Select appropriate escape format automatically, and set 'tmp' to a
30002 * value encoding both the escape format character and the nybble count:
30003 *
30004 * (nybble_count << 16) | (escape_char1) | (escape_char2)
30005 */
30006
30007#ifdef DUK_USE_JX
30008 if (DUK_LIKELY(cp < 0x100UL)) {
30009 if (DUK_UNLIKELY(js_ctx->flag_ext_custom)) {
30011 } else {
30013 }
30014 } else
30015#endif
30016 if (DUK_LIKELY(cp < 0x10000UL)) {
30018 } else {
30019#ifdef DUK_USE_JX
30020 if (DUK_LIKELY(js_ctx->flag_ext_custom)) {
30022 } else
30023#endif
30024 {
30025 /* In compatible mode and standard JSON mode, output
30026 * something useful for non-BMP characters. This won't
30027 * roundtrip but will still be more or less readable and
30028 * more useful than an error.
30029 */
30031 }
30032 }
30033
30034 *q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
30035 *q++ = (duk_uint8_t) (tmp & 0xff);
30036
30037 tmp = tmp >> 16;
30038 while (tmp > 0) {
30039 tmp--;
30040 dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
30041 *q++ = duk_lc_digits[dig];
30042 }
30043
30044 return q;
30045}
30046
30048 const duk_int8_t *p, *p_start, *p_end; /* Note: intentionally signed. */
30049 duk_size_t k_len;
30050 duk_codepoint_t cp;
30051
30052 DUK_ASSERT(k != NULL);
30053
30054 /* Accept ASCII strings which conform to identifier requirements
30055 * as being emitted without key quotes. Since we only accept ASCII
30056 * there's no need for actual decoding: 'p' is intentionally signed
30057 * so that bytes >= 0x80 extend to negative values and are rejected
30058 * as invalid identifier codepoints.
30059 */
30060
30061 if (js_ctx->flag_avoid_key_quotes) {
30062 k_len = DUK_HSTRING_GET_BYTELEN(k);
30063 p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
30064 p_end = p_start + k_len;
30065 p = p_start;
30066
30067 if (p == p_end) {
30068 /* Zero length string is not accepted without quotes */
30069 goto quote_normally;
30070 }
30071 cp = (duk_codepoint_t) (*p++);
30073 goto quote_normally;
30074 }
30075 while (p < p_end) {
30076 cp = (duk_codepoint_t) (*p++);
30078 goto quote_normally;
30079 }
30080 }
30082 /* This seems faster than emitting bytes one at a time and
30083 * then potentially rewinding.
30084 */
30085 DUK__EMIT_HSTR(js_ctx, k);
30086 return;
30087 }
30088
30089 quote_normally:
30090 duk__enc_quote_string(js_ctx, k);
30091}
30092
30093/* The Quote(value) operation: quote a string.
30094 *
30095 * Stack policy: [ ] -> [ ].
30096 */
30097
30099 duk_hthread *thr = js_ctx->thr;
30100 const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
30101 duk_uint8_t *q;
30102 duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */
30103
30104 DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
30105
30106 DUK_ASSERT(h_str != NULL);
30107 p_start = DUK_HSTRING_GET_DATA(h_str);
30108 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
30109 p = p_start;
30110
30112
30113 /* Encode string in small chunks, estimating the maximum expansion so that
30114 * there's no need to ensure space while processing the chunk.
30115 */
30116
30117 while (p < p_end) {
30118 duk_size_t left, now, space;
30119
30120 left = (duk_size_t) (p_end - p);
30123
30124 /* Maximum expansion per input byte is 6:
30125 * - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
30126 * - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
30127 * - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
30128 */
30129 space = now * 6;
30130 q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
30131
30132 p_now = p + now;
30133
30134 while (p < p_now) {
30135#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
30136 duk_uint8_t b;
30137
30138 b = duk__json_quotestr_lookup[*p++];
30139 if (DUK_LIKELY(b < 0x80)) {
30140 /* Most input bytes go through here. */
30141 *q++ = b;
30142 } else if (b >= 0xa0) {
30143 *q++ = DUK_ASC_BACKSLASH;
30144 *q++ = (duk_uint8_t) (b - 0x80);
30145 } else if (b == 0x80) {
30146 cp = (duk_ucodepoint_t) (*(p - 1));
30147 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30148 } else if (b == 0x7f && js_ctx->flag_ascii_only) {
30149 /* 0x7F is special */
30150 DUK_ASSERT(b == 0x81);
30151 cp = (duk_ucodepoint_t) 0x7f;
30152 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30153 } else {
30154 DUK_ASSERT(b == 0x81);
30155 p--;
30156
30157 /* slow path is shared */
30158#else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
30159 cp = *p;
30160
30161 if (DUK_LIKELY(cp <= 0x7f)) {
30162 /* ascii fast path: avoid decoding utf-8 */
30163 p++;
30164 if (cp == 0x22 || cp == 0x5c) {
30165 /* double quote or backslash */
30166 *q++ = DUK_ASC_BACKSLASH;
30167 *q++ = (duk_uint8_t) cp;
30168 } else if (cp < 0x20) {
30169 duk_uint_fast8_t esc_char;
30170
30171 /* This approach is a bit shorter than a straight
30172 * if-else-ladder and also a bit faster.
30173 */
30174 if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
30175 (esc_char = duk__json_quotestr_esc[cp]) != 0) {
30176 *q++ = DUK_ASC_BACKSLASH;
30177 *q++ = (duk_uint8_t) esc_char;
30178 } else {
30179 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30180 }
30181 } else if (cp == 0x7f && js_ctx->flag_ascii_only) {
30182 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30183 } else {
30184 /* any other printable -> as is */
30185 *q++ = (duk_uint8_t) cp;
30186 }
30187 } else {
30188 /* slow path is shared */
30189#endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
30190
30191 /* slow path decode */
30192
30193 /* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
30194 * and go forward one byte. This is of course very lossy, but allows some kind
30195 * of output to be produced even for internal strings which don't conform to
30196 * XUTF-8. All standard Ecmascript strings are always CESU-8, so this behavior
30197 * does not violate the Ecmascript specification. The behavior is applied to
30198 * all modes, including Ecmascript standard JSON. Because the current XUTF-8
30199 * decoding is not very strict, this behavior only really affects initial bytes
30200 * and truncated codepoints.
30201 *
30202 * Another alternative would be to scan forwards to start of next codepoint
30203 * (or end of input) and emit just one replacement codepoint.
30204 */
30205
30206 p_tmp = p;
30207 if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
30208 /* Decode failed. */
30209 cp = *p_tmp;
30210 p = p_tmp + 1;
30211 }
30212
30213#ifdef DUK_USE_NONSTD_JSON_ESC_U2028_U2029
30214 if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
30215#else
30216 if (js_ctx->flag_ascii_only) {
30217#endif
30218 q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30219 } else {
30220 /* as is */
30221 DUK_RAW_WRITE_XUTF8(q, cp);
30222 }
30223 }
30224 }
30225
30226 DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
30227 }
30228
30230}
30231
30232/* Encode a double (checked by caller) from stack top. Stack top may be
30233 * replaced by serialized string but is not popped (caller does that).
30234 */
30236 duk_hthread *thr;
30237 duk_context *ctx;
30238 duk_tval *tv;
30239 duk_double_t d;
30242 duk_small_uint_t stridx;
30243 duk_small_uint_t n2s_flags;
30244 duk_hstring *h_str;
30245
30246 DUK_ASSERT(js_ctx != NULL);
30247 thr = js_ctx->thr;
30248 DUK_ASSERT(thr != NULL);
30249 ctx = (duk_context *) thr;
30250
30251 /* Caller must ensure 'tv' is indeed a double and not a fastint! */
30252 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30254 d = DUK_TVAL_GET_DOUBLE(tv);
30255
30258 DUK_UNREF(s);
30259
30260 if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
30262
30263#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30264 /* Negative zero needs special handling in JX/JC because
30265 * it would otherwise serialize to '0', not '-0'.
30266 */
30267 if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
30268 (js_ctx->flag_ext_custom_or_compatible))) {
30270 } else
30271#endif /* DUK_USE_JX || DUK_USE_JC */
30272 {
30273 n2s_flags = 0;
30274 /* [ ... number ] -> [ ... string ] */
30275 duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags);
30276 }
30277 h_str = duk_to_hstring(ctx, -1);
30278 DUK_ASSERT(h_str != NULL);
30279 DUK__EMIT_HSTR(js_ctx, h_str);
30280 return;
30281 }
30282
30283#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30284 if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
30286 stridx = DUK_STRIDX_LC_NULL;
30287 } else if (c == DUK_FP_NAN) {
30288 stridx = js_ctx->stridx_custom_nan;
30289 } else if (s == 0) {
30290 stridx = js_ctx->stridx_custom_posinf;
30291 } else {
30292 stridx = js_ctx->stridx_custom_neginf;
30293 }
30294#else
30295 stridx = DUK_STRIDX_LC_NULL;
30296#endif
30297 DUK__EMIT_STRIDX(js_ctx, stridx);
30298}
30299
30300#if defined(DUK_USE_FASTINT)
30301/* Encode a fastint from duk_tval ptr, no value stack effects. */
30302DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
30303 duk_int64_t v;
30304
30305 /* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
30306 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
30307 * (20 chars long). Alloc space for 64-bit range to be safe.
30308 */
30309 duk_uint8_t buf[20 + 1];
30311 /* Caller must ensure 'tv' is indeed a fastint! */
30312 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
30313 v = DUK_TVAL_GET_FASTINT(tv);
30314
30315 /* XXX: There are no format strings in duk_config.h yet, could add
30316 * one for formatting duk_int64_t. For now, assumes "%lld" and that
30317 * "long long" type exists. Could also rely on C99 directly but that
30318 * won't work for older MSVC.
30319 */
30320 DUK_SPRINTF((char *) buf, "%lld", (long long) v);
30321 DUK__EMIT_CSTR(js_ctx, (const char *) buf);
30322}
30323#endif
30324
30325#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30326#if defined(DUK_USE_HEX_FASTPATH)
30327DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
30328 duk_uint8_t *q;
30329 duk_uint16_t *q16;
30331 duk_size_t i, len_safe;
30332#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30333 duk_bool_t shift_dst;
30334#endif
30335
30336 /* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
30337 * For platforms where unaligned accesses are not allowed, shift 'dst'
30338 * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result
30339 * in place. The faster encoding loop makes up the difference.
30340 * There's always space for one extra byte because a terminator always
30341 * follows the hex data and that's been accounted for by the caller.
30342 */
30343
30344#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30345 q16 = (duk_uint16_t *) (void *) dst;
30346#else
30347 shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
30348 if (shift_dst) {
30349 DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
30350 q16 = (duk_uint16_t *) (void *) (dst + 1);
30351 } else {
30352 DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
30353 q16 = (duk_uint16_t *) (void *) dst;
30354 }
30355 DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
30356#endif
30357
30358 len_safe = src_len & ~0x03U;
30359 for (i = 0; i < len_safe; i += 4) {
30360 q16[0] = duk_hex_enctab[src[i]];
30361 q16[1] = duk_hex_enctab[src[i + 1]];
30362 q16[2] = duk_hex_enctab[src[i + 2]];
30363 q16[3] = duk_hex_enctab[src[i + 3]];
30364 q16 += 4;
30365 }
30366 q = (duk_uint8_t *) q16;
30367
30368#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30369 if (shift_dst) {
30370 q--;
30371 DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);
30372 DUK_ASSERT(dst + 2 * len_safe == q);
30373 }
30374#endif
30375
30376 for (; i < src_len; i++) {
30377 x = src[i];
30378 *q++ = duk_lc_digits[x >> 4];
30379 *q++ = duk_lc_digits[x & 0x0f];
30380 }
30381
30382 return q;
30383}
30384#else /* DUK_USE_HEX_FASTPATH */
30385DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
30386 const duk_uint8_t *p;
30387 const duk_uint8_t *p_end;
30388 duk_uint8_t *q;
30390
30391 p = src;
30392 p_end = src + src_len;
30393 q = dst;
30394 while (p != p_end) {
30395 x = *p++;
30396 *q++ = duk_lc_digits[x >> 4];
30397 *q++ = duk_lc_digits[x & 0x0f];
30398 }
30399
30400 return q;
30401}
30402#endif /* DUK_USE_HEX_FASTPATH */
30403
30404DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
30405 duk_hthread *thr;
30406 duk_uint8_t *q;
30407 duk_size_t space;
30408
30409 thr = js_ctx->thr;
30410
30411 DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
30413
30414 /* Buffer values are encoded in (lowercase) hex to make the
30415 * binary data readable. Base64 or similar would be more
30416 * compact but less readable, and the point of JX/JC
30417 * variants is to be as useful to a programmer as possible.
30418 */
30419
30420 /* The #ifdef clutter here needs to handle the three cases:
30421 * (1) JX+JC, (2) JX only, (3) JC only.
30422 */
30423
30424 /* Note: space must cater for both JX and JC. */
30425 space = 9 + buf_len * 2 + 2;
30426 DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
30427 DUK_ASSERT((space - 2) / 2 >= buf_len); /* overflow not possible, buffer limits */
30428 q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
30429
30430#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30431 if (js_ctx->flag_ext_custom)
30432#endif
30433#if defined(DUK_USE_JX)
30434 {
30435 *q++ = DUK_ASC_PIPE;
30436 q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
30437 *q++ = DUK_ASC_PIPE;
30438
30439 }
30440#endif
30441#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30442 else
30443#endif
30444#if defined(DUK_USE_JC)
30445 {
30447 DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */
30448 q += 9;
30449 q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
30450 *q++ = DUK_ASC_DOUBLEQUOTE;
30451 *q++ = DUK_ASC_RCURLY;
30452 }
30453#endif
30454
30455 DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
30456}
30457
30459 duk__enc_buffer_data(js_ctx,
30460 (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
30462}
30463#endif /* DUK_USE_JX || DUK_USE_JC */
30464
30465#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30466DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
30467 char buf[64]; /* XXX: how to figure correct size? */
30468 const char *fmt;
30469
30470 DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
30472
30473 DUK_MEMZERO(buf, sizeof(buf));
30474
30475 /* The #ifdef clutter here needs to handle the three cases:
30476 * (1) JX+JC, (2) JX only, (3) JC only.
30477 */
30478#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30479 if (js_ctx->flag_ext_custom)
30480#endif
30481#if defined(DUK_USE_JX)
30482 {
30483 fmt = ptr ? "(%p)" : "(null)";
30484 }
30485#endif
30486#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30487 else
30488#endif
30489#if defined(DUK_USE_JC)
30490 {
30492 fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
30493 }
30494#endif
30495
30496 /* When ptr == NULL, the format argument is unused. */
30497 DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
30498 DUK__EMIT_CSTR(js_ctx, buf);
30499}
30500#endif /* DUK_USE_JX || DUK_USE_JC */
30501
30502#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30505
30506 if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
30508 } else {
30509 /* Handle both full and partial slice (as long as covered). */
30510 duk__enc_buffer_data(js_ctx,
30511 (duk_uint8_t *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
30512 (duk_size_t) h_bufobj->length);
30513 }
30515#endif /* DUK_USE_JX || DUK_USE_JC */
30516
30517/* Indent helper. Calling code relies on js_ctx->recursion_depth also being
30518 * directly related to indent depth.
30519 */
30520#if defined(DUK_USE_PREFER_SIZE)
30522 DUK_ASSERT(js_ctx->h_gap != NULL);
30523 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
30524
30525 DUK__EMIT_1(js_ctx, 0x0a);
30526 while (depth-- > 0) {
30527 DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
30528 }
30529}
30530#else /* DUK_USE_PREFER_SIZE */
30532 const duk_uint8_t *gap_data;
30533 duk_size_t gap_len;
30534 duk_size_t avail_bytes; /* bytes of indent available for copying */
30535 duk_size_t need_bytes; /* bytes of indent still needed */
30536 duk_uint8_t *p_start;
30537 duk_uint8_t *p;
30538
30539 DUK_ASSERT(js_ctx->h_gap != NULL);
30540 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
30541
30542 DUK__EMIT_1(js_ctx, 0x0a);
30543 if (DUK_UNLIKELY(depth == 0)) {
30544 return;
30545 }
30546
30547 /* To handle deeper indents efficiently, make use of copies we've
30548 * already emitted. In effect we can emit a sequence of 1, 2, 4,
30549 * 8, etc copies, and then finish the last run. Byte counters
30550 * avoid multiply with gap_len on every loop.
30551 */
30552
30553 gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
30554 gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
30555 DUK_ASSERT(gap_len > 0);
30556
30557 need_bytes = gap_len * depth;
30558 p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
30559 p_start = p;
30560
30561 DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);
30562 p += gap_len;
30563 avail_bytes = gap_len;
30564 DUK_ASSERT(need_bytes >= gap_len);
30565 need_bytes -= gap_len;
30566
30567 while (need_bytes >= avail_bytes) {
30568 DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);
30569 p += avail_bytes;
30570 need_bytes -= avail_bytes;
30571 avail_bytes <<= 1;
30572 }
30573
30574 DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */
30575 DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);
30576 p += need_bytes;
30577 /*avail_bytes += need_bytes*/
30578
30579 DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
30580}
30581#endif /* DUK_USE_PREFER_SIZE */
30582
30583/* Shared entry handling for object/array serialization. */
30585 duk_context *ctx = (duk_context *) js_ctx->thr;
30586 duk_hobject *h_target;
30587 duk_uint_fast32_t i, n;
30588
30589 *entry_top = duk_get_top(ctx);
30590
30592
30593 /* Loop check using a hybrid approach: a fixed-size visited[] array
30594 * with overflow in a loop check object.
30595 */
30596
30597 h_target = duk_get_hobject(ctx, -1); /* object or array */
30598 DUK_ASSERT(h_target != NULL);
30599
30600 n = js_ctx->recursion_depth;
30603 }
30604 for (i = 0; i < n; i++) {
30605 if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
30606 DUK_DD(DUK_DDPRINT("slow path loop detect"));
30608 }
30609 }
30611 js_ctx->visiting[js_ctx->recursion_depth] = h_target;
30612 } else {
30613 duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
30614 duk_dup_top(ctx); /* -> [ ... voidp voidp ] */
30615 if (duk_has_prop(ctx, js_ctx->idx_loop)) {
30617 }
30618 duk_push_true(ctx); /* -> [ ... voidp true ] */
30619 duk_put_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
30620 }
30621
30622 /* C recursion check. */
30623
30624 DUK_ASSERT(js_ctx->recursion_depth >= 0);
30625 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
30626 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
30628 }
30629 js_ctx->recursion_depth++;
30630
30631 DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
30632 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
30633}
30634
30635/* Shared exit handling for object/array serialization. */
30636DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
30637 duk_context *ctx = (duk_context *) js_ctx->thr;
30638 duk_hobject *h_target;
30639
30640 /* C recursion check. */
30641
30642 DUK_ASSERT(js_ctx->recursion_depth > 0);
30643 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
30644 js_ctx->recursion_depth--;
30645
30646 /* Loop check. */
30647
30648 h_target = duk_get_hobject(ctx, *entry_top - 1); /* original target at entry_top - 1 */
30649 DUK_ASSERT(h_target != NULL);
30650
30652 /* Previous entry was inside visited[], nothing to do. */
30653 } else {
30654 duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
30655 duk_del_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
30656 }
30657
30658 /* Restore stack top after unbalanced code paths. */
30659 duk_set_top(ctx, *entry_top);
30660
30661 DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
30662 (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
30663}
30664
30665/* The JO(value) operation: encode object.
30666 *
30667 * Stack policy: [ object ] -> [ object ].
30668 */
30670 duk_context *ctx = (duk_context *) js_ctx->thr;
30671 duk_hstring *h_key;
30672 duk_idx_t entry_top;
30673 duk_idx_t idx_obj;
30674 duk_idx_t idx_keys;
30675 duk_bool_t emitted;
30676 duk_uarridx_t arr_len, i;
30677 duk_size_t prev_size;
30678
30679 DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30680
30681 duk__enc_objarr_entry(js_ctx, &entry_top);
30682
30683 idx_obj = entry_top - 1;
30684
30685 if (js_ctx->idx_proplist >= 0) {
30686 idx_keys = js_ctx->idx_proplist;
30687 } else {
30688 /* XXX: would be nice to enumerate an object at specified index */
30689 duk_dup(ctx, idx_obj);
30690 (void) duk_hobject_get_enumerated_keys(ctx, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); /* [ ... target ] -> [ ... target keys ] */
30691 idx_keys = duk_require_normalize_index(ctx, -1);
30692 /* leave stack unbalanced on purpose */
30693 }
30694
30695 DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
30696 (long) idx_keys, (duk_tval *) duk_get_tval(ctx, idx_keys)));
30697
30698 /* Steps 8-10 have been merged to avoid a "partial" variable. */
30699
30700 DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
30701
30702 /* XXX: keys is an internal object with all keys to be processed
30703 * in its (gapless) array part. Because nobody can touch the keys
30704 * object, we could iterate its array part directly (keeping in mind
30705 * that it can be reallocated).
30706 */
30707
30708 arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_keys);
30709 emitted = 0;
30710 for (i = 0; i < arr_len; i++) {
30711 duk_get_prop_index(ctx, idx_keys, i); /* -> [ ... key ] */
30712
30713 DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
30714 (duk_tval *) duk_get_tval(ctx, idx_obj),
30715 (duk_tval *) duk_get_tval(ctx, -1)));
30716
30717 h_key = duk_get_hstring(ctx, -1);
30718 DUK_ASSERT(h_key != NULL);
30719
30720 prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
30721 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30723 duk__enc_key_autoquote(js_ctx, h_key);
30725 } else {
30726 duk__enc_key_autoquote(js_ctx, h_key);
30727 DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
30728 }
30729
30730 /* [ ... key ] */
30731
30732 if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
30733 /* Value would yield 'undefined', so skip key altogether.
30734 * Side effects have already happened.
30735 */
30736 DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
30737 } else {
30738 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
30739 emitted = 1;
30740 }
30741
30742 /* [ ... ] */
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 }
30753 DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
30754
30755 duk__enc_objarr_exit(js_ctx, &entry_top);
30756
30757 DUK_ASSERT_TOP(ctx, entry_top);
30758}
30759
30760/* The JA(value) operation: encode array.
30761 *
30762 * Stack policy: [ array ] -> [ array ].
30763 */
30765 duk_context *ctx = (duk_context *) js_ctx->thr;
30766 duk_idx_t entry_top;
30767 duk_idx_t idx_arr;
30768 duk_bool_t emitted;
30769 duk_uarridx_t i, arr_len;
30770
30771 DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
30772 (duk_tval *) duk_get_tval(ctx, -1)));
30773
30774 duk__enc_objarr_entry(js_ctx, &entry_top);
30775
30776 idx_arr = entry_top - 1;
30777
30778 /* Steps 8-10 have been merged to avoid a "partial" variable. */
30779
30781
30782 arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_arr);
30783 emitted = 0;
30784 for (i = 0; i < arr_len; i++) {
30785 DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
30786 (duk_tval *) duk_get_tval(ctx, idx_arr),
30787 (long) i, (long) arr_len));
30788
30789 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30790 DUK_ASSERT(js_ctx->recursion_depth >= 1);
30792 }
30793
30794 /* XXX: duk_push_uint_string() */
30795 duk_push_uint(ctx, (duk_uint_t) i);
30796 duk_to_string(ctx, -1); /* -> [ ... key ] */
30797
30798 /* [ ... key ] */
30799
30800 if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
30801 /* Value would normally be omitted, replace with 'null'. */
30803 } else {
30804 ;
30805 }
30806
30807 /* [ ... ] */
30808
30809 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
30810 emitted = 1;
30811 }
30812
30813 if (emitted) {
30814 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
30815 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
30816 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30817 DUK_ASSERT(js_ctx->recursion_depth >= 1);
30818 duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
30819 }
30820 }
30822
30823 duk__enc_objarr_exit(js_ctx, &entry_top);
30824
30825 DUK_ASSERT_TOP(ctx, entry_top);
30826}
30827
30828/* The Str(key, holder) operation.
30829 *
30830 * Stack policy: [ ... key ] -> [ ... ]
30831 */
30833 duk_context *ctx = (duk_context *) js_ctx->thr;
30834 duk_hthread *thr = (duk_hthread *) ctx;
30835 duk_hobject *h_tmp;
30836 duk_tval *tv;
30837 duk_tval *tv_holder;
30838 duk_tval *tv_key;
30840
30841 DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
30842 (long) idx_holder, (duk_tval *) duk_get_tval(ctx, idx_holder),
30843 (duk_tval *) duk_get_tval(ctx, -1)));
30844
30845 DUK_UNREF(thr);
30846
30847 tv_holder = DUK_GET_TVAL_POSIDX(ctx, idx_holder);
30848 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
30849 tv_key = DUK_GET_TVAL_NEGIDX(ctx, -1);
30851 (void) duk_hobject_getprop(thr, tv_holder, tv_key);
30852
30853 /* -> [ ... key val ] */
30854
30855 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30856
30857 h_tmp = duk_get_hobject_or_lfunc_coerce(ctx, -1);
30858 if (h_tmp != NULL) {
30860 h_tmp = duk_get_hobject_or_lfunc_coerce(ctx, -1); /* toJSON() can also be a lightfunc */
30861
30862 if (h_tmp != NULL && DUK_HOBJECT_IS_CALLABLE(h_tmp)) {
30863 DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
30864 /* XXX: duk_dup_unvalidated(ctx, -2) etc. */
30865 duk_dup(ctx, -2); /* -> [ ... key val toJSON val ] */
30866 duk_dup(ctx, -4); /* -> [ ... key val toJSON val key ] */
30867 duk_call_method(ctx, 1); /* -> [ ... key val val' ] */
30868 duk_remove(ctx, -2); /* -> [ ... key val' ] */
30869 } else {
30870 duk_pop(ctx); /* -> [ ... key val ] */
30871 }
30872 }
30873
30874 /* [ ... key val ] */
30875
30876 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30877
30878 if (js_ctx->h_replacer) {
30879 /* XXX: Here a "slice copy" would be useful. */
30880 DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
30881 duk_push_hobject(ctx, js_ctx->h_replacer); /* -> [ ... key val replacer ] */
30882 duk_dup(ctx, idx_holder); /* -> [ ... key val replacer holder ] */
30883 duk_dup(ctx, -4); /* -> [ ... key val replacer holder key ] */
30884 duk_dup(ctx, -4); /* -> [ ... key val replacer holder key val ] */
30885 duk_call_method(ctx, 2); /* -> [ ... key val val' ] */
30886 duk_remove(ctx, -2); /* -> [ ... key val' ] */
30887 }
30888
30889 /* [ ... key val ] */
30890
30891 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30892
30893 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30894 if (DUK_TVAL_IS_OBJECT(tv)) {
30895 duk_hobject *h;
30896
30897 h = DUK_TVAL_GET_OBJECT(tv);
30898 DUK_ASSERT(h != NULL);
30899
30901#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30902 duk_hbufferobject *h_bufobj;
30903 h_bufobj = (duk_hbufferobject *) h;
30905
30906 /* Conceptually we'd extract the plain underlying buffer
30907 * or its slice and then do a type mask check below to
30908 * see if we should reject it. Do the mask check here
30909 * instead to avoid making a copy of the buffer slice.
30910 */
30911
30913 DUK_DDD(DUK_DDDPRINT("-> bufferobject (-> plain buffer) will result in undefined (type mask check)"));
30914 goto pop2_undef;
30915 }
30916 DUK_DDD(DUK_DDDPRINT("-> bufferobject won't result in undefined, encode directly"));
30917 duk__enc_bufferobject(js_ctx, h_bufobj);
30918 goto pop2_emitted;
30919#else
30920 DUK_DDD(DUK_DDDPRINT("no JX/JC support, bufferobject/buffer will always result in undefined"));
30921 goto pop2_undef;
30922#endif
30923 } else {
30925 switch ((int) c) {
30927 DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
30928 duk_to_number(ctx, -1);
30929 /* The coercion potentially invokes user .valueOf() and .toString()
30930 * but can't result in a function value because [[DefaultValue]] would
30931 * reject such a result: test-dev-json-stringify-coercion-1.js.
30932 */
30933 DUK_ASSERT(!duk_is_callable(ctx, -1));
30934 break;
30935 }
30937 DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
30938 duk_to_string(ctx, -1);
30939 /* Same coercion behavior as for Number. */
30940 DUK_ASSERT(!duk_is_callable(ctx, -1));
30941 break;
30942 }
30943#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30945#endif
30947 DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
30949 duk_remove(ctx, -2);
30950 break;
30951 }
30952 default: {
30953 /* Normal object which doesn't get automatically coerced to a
30954 * primitive value. Functions are checked for specially. The
30955 * primitive value coercions for Number, String, Pointer, and
30956 * Boolean can't result in functions so suffices to check here.
30957 */
30958 DUK_ASSERT(h != NULL);
30959 if (DUK_HOBJECT_IS_CALLABLE(h)) {
30960#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30961 if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
30963 /* We only get here when doing non-standard JSON encoding */
30964 DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
30967 goto pop2_emitted;
30968 } else {
30969 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
30970 goto pop2_undef;
30971 }
30972#else /* DUK_USE_JX || DUK_USE_JC */
30973 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
30974 goto pop2_undef;
30975#endif /* DUK_USE_JX || DUK_USE_JC */
30976 }
30977 }
30978 } /* end switch */
30979 }
30980 }
30981
30982 /* [ ... key val ] */
30983
30984 DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30985
30986 if (duk_check_type_mask(ctx, -1, js_ctx->mask_for_undefined)) {
30987 /* will result in undefined */
30988 DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
30989 goto pop2_undef;
30990 }
30991 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30992
30993 switch (DUK_TVAL_GET_TAG(tv)) {
30994#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30995 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
30996 case DUK_TAG_UNDEFINED: {
30998 break;
30999 }
31000#endif
31001 case DUK_TAG_NULL: {
31003 break;
31004 }
31005 case DUK_TAG_BOOLEAN: {
31008 break;
31009 }
31010#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31011 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
31012 case DUK_TAG_POINTER: {
31014 break;
31015 }
31016#endif /* DUK_USE_JX || DUK_USE_JC */
31017 case DUK_TAG_STRING: {
31019 DUK_ASSERT(h != NULL);
31020
31021 duk__enc_quote_string(js_ctx, h);
31022 break;
31023 }
31024 case DUK_TAG_OBJECT: {
31026 DUK_ASSERT(h != NULL);
31027
31028 /* Function values are handled completely above (including
31029 * coercion results):
31030 */
31032
31034 duk__enc_array(js_ctx);
31035 } else {
31036 duk__enc_object(js_ctx);
31037 }
31038 break;
31039 }
31040#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31041 /* When JX/JC not in use, the type mask above will avoid this case if needed. */
31042 case DUK_TAG_BUFFER: {
31044 break;
31045 }
31046#endif /* DUK_USE_JX || DUK_USE_JC */
31047 case DUK_TAG_LIGHTFUNC: {
31048#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31049 /* We only get here when doing non-standard JSON encoding */
31052#else
31053 /* Standard JSON omits functions */
31055#endif
31056 break;
31057 }
31058#if defined(DUK_USE_FASTINT)
31059 case DUK_TAG_FASTINT:
31060 /* Number serialization has a significant impact relative to
31061 * other fast path code, so careful fast path for fastints.
31062 */
31063 duk__enc_fastint_tval(js_ctx, tv);
31064 break;
31065#endif
31066 default: {
31067 /* number */
31070 /* XXX: A fast path for usual integers would be useful when
31071 * fastint support is not enabled.
31072 */
31073 duk__enc_double(js_ctx);
31074 break;
31075 }
31076 }
31077
31078 pop2_emitted:
31079 duk_pop_2(ctx); /* [ ... key val ] -> [ ... ] */
31080 return 1; /* emitted */
31081
31082 pop2_undef:
31083 duk_pop_2(ctx); /* [ ... key val ] -> [ ... ] */
31084 return 0; /* not emitted */
31085}
31086
31087/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
31089 duk_hobject *h;
31091
31092 DUK_ASSERT(tv != NULL);
31093 if (DUK_TVAL_IS_STRING(tv) || DUK_TVAL_IS_NUMBER(tv)) {
31094 return 1;
31095 } else if (DUK_TVAL_IS_OBJECT(tv)) {
31096 h = DUK_TVAL_GET_OBJECT(tv);
31097 DUK_ASSERT(h != NULL);
31100 return 1;
31101 }
31102 }
31103
31104 return 0;
31105}
31106
31107/*
31108 * JSON.stringify() fast path
31109 *
31110 * Otherwise supports full JSON, JX, and JC features, but bails out on any
31111 * possible side effect which might change the value being serialized. The
31112 * fast path can take advantage of the fact that the value being serialized
31113 * is unchanged so that we can walk directly through property tables etc.
31114 */
31115
31116#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
31117DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
31118 duk_uint_fast32_t i, n;
31119
31120 DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
31121
31122 DUK_ASSERT(js_ctx != NULL);
31123 DUK_ASSERT(js_ctx->thr != NULL);
31124
31125#if 0 /* disabled for now */
31126 restart_match:
31127#endif
31128
31129 DUK_ASSERT(tv != NULL);
31130
31131 switch (DUK_TVAL_GET_TAG(tv)) {
31132 case DUK_TAG_UNDEFINED: {
31133#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31134 if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
31136 break;
31137 } else {
31138 goto emit_undefined;
31139 }
31140#else
31141 goto emit_undefined;
31142#endif
31143 }
31144 case DUK_TAG_NULL: {
31146 break;
31147 }
31148 case DUK_TAG_BOOLEAN: {
31151 break;
31152 }
31153 case DUK_TAG_STRING: {
31154 duk_hstring *h;
31155
31156 h = DUK_TVAL_GET_STRING(tv);
31157 DUK_ASSERT(h != NULL);
31158 duk__enc_quote_string(js_ctx, h);
31159 break;
31160 }
31161 case DUK_TAG_OBJECT: {
31162 duk_hobject *obj;
31163 duk_tval *tv_val;
31164 duk_bool_t emitted = 0;
31165 duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
31166 c_func, c_bufobj, c_object;
31167
31168 /* For objects JSON.stringify() only looks for own, enumerable
31169 * properties which is nice for the fast path here.
31170 *
31171 * For arrays JSON.stringify() uses [[Get]] so it will actually
31172 * inherit properties during serialization! This fast path
31173 * supports gappy arrays as long as there's no actual inherited
31174 * property (which might be a getter etc).
31175 *
31176 * Since recursion only happens for objects, we can have both
31177 * recursion and loop checks here. We use a simple, depth-limited
31178 * loop check in the fast path because the object-based tracking
31179 * is very slow (when tested, it accounted for 50% of fast path
31180 * execution time for input data with a lot of small objects!).
31181 */
31182
31183 /* XXX: for real world code, could just ignore array inheritance
31184 * and only look at array own properties.
31185 */
31186
31187 /* We rely on a few object flag / class number relationships here,
31188 * assert for them.
31189 */
31190
31191 obj = DUK_TVAL_GET_OBJECT(tv);
31192 DUK_ASSERT(obj != NULL);
31194
31195 /* Once recursion depth is increased, exit path must decrease
31196 * it (though it's OK to abort the fast path).
31197 */
31198
31199 DUK_ASSERT(js_ctx->recursion_depth >= 0);
31200 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31201 if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
31202 DUK_DD(DUK_DDPRINT("fast path recursion limit"));
31204 }
31205
31206 for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
31207 if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
31208 DUK_DD(DUK_DDPRINT("fast path loop detect"));
31210 }
31211 }
31212
31213 /* Guaranteed by recursion_limit setup so we don't have to
31214 * check twice.
31215 */
31217 js_ctx->visiting[js_ctx->recursion_depth] = obj;
31218 js_ctx->recursion_depth++;
31219
31220 /* If object has a .toJSON() property, we can't be certain
31221 * that it wouldn't mutate any value arbitrarily, so bail
31222 * out of the fast path.
31223 *
31224 * If an object is a Proxy we also can't avoid side effects
31225 * so abandon.
31226 */
31227 /* XXX: non-callable .toJSON() doesn't need to cause an abort
31228 * but does at the moment, probably not worth fixing.
31229 */
31230 if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
31232 DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
31233 goto abort_fastpath;
31234 }
31235
31236 /* We could use a switch-case for the class number but it turns out
31237 * a small if-else ladder on class masks is better. The if-ladder
31238 * should be in order of relevancy.
31239 */
31240
31241 /* XXX: move masks to js_ctx? they don't change during one
31242 * fast path invocation.
31243 */
31245#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31246 if (js_ctx->flag_ext_custom_or_compatible) {
31247 c_all = DUK_HOBJECT_CMASK_ALL;
31248 c_array = DUK_HOBJECT_CMASK_ARRAY;
31249 c_unbox = DUK_HOBJECT_CMASK_NUMBER |
31255 c_undef = 0;
31256 c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
31257 }
31258 else
31259#endif
31260 {
31261 c_all = DUK_HOBJECT_CMASK_ALL;
31262 c_array = DUK_HOBJECT_CMASK_ARRAY;
31263 c_unbox = DUK_HOBJECT_CMASK_NUMBER |
31266 c_func = 0;
31267 c_bufobj = 0;
31268 c_undef = DUK_HOBJECT_CMASK_FUNCTION |
31271 c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
31272 }
31273
31274 c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj);
31275 if (c_bit & c_object) {
31276 /* All other object types. */
31277 DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
31278
31279 /* A non-Array object should not have an array part in practice.
31280 * But since it is supported internally (and perhaps used at some
31281 * point), check and abandon if that's the case.
31282 */
31283 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
31284 DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
31285 goto abort_fastpath;
31286 }
31287
31288 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
31289 duk_hstring *k;
31290 duk_size_t prev_size;
31291
31292 k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
31293 if (!k) {
31294 continue;
31295 }
31296 if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
31297 continue;
31298 }
31299 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
31300 /* Getter might have arbitrary side effects,
31301 * so bail out.
31302 */
31303 DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
31304 goto abort_fastpath;
31305 }
31306 if (DUK_HSTRING_HAS_INTERNAL(k)) {
31307 continue;
31308 }
31309
31310 tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
31311
31312 prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
31313 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31315 duk__enc_key_autoquote(js_ctx, k);
31317 } else {
31318 duk__enc_key_autoquote(js_ctx, k);
31319 DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
31320 }
31321
31322 if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
31323 DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
31324 DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
31325 } else {
31326 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
31327 emitted = 1;
31328 }
31329 }
31330
31331 /* If any non-Array value had enumerable virtual own
31332 * properties, they should be serialized here. Standard
31333 * types don't.
31334 */
31335
31336 if (emitted) {
31337 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
31338 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
31339 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31340 DUK_ASSERT(js_ctx->recursion_depth >= 1);
31341 duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
31342 }
31343 }
31344 DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
31345 } else if (c_bit & c_array) {
31346 duk_uint_fast32_t arr_len;
31347 duk_uint_fast32_t asize;
31348
31350
31351 /* Assume arrays are dense in the fast path. */
31352 if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
31353 DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
31354 goto abort_fastpath;
31355 }
31356
31357 arr_len = (duk_uint_fast32_t) duk_hobject_get_length(js_ctx->thr, obj);
31359 if (arr_len > asize) {
31360 /* Array length is larger than 'asize'. This shouldn't
31361 * happen in practice. Bail out just in case.
31362 */
31363 DUK_DD(DUK_DDPRINT("arr_len > asize, abort fast path"));
31364 goto abort_fastpath;
31365 }
31366 /* Array part may be larger than 'length'; if so, iterate
31367 * only up to array 'length'.
31368 */
31369 for (i = 0; i < arr_len; i++) {
31371
31372 tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
31373
31374 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31376 }
31377
31378 if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_val))) {
31379 /* Gap in array; check for inherited property,
31380 * bail out if one exists. This should be enough
31381 * to support gappy arrays for all practical code.
31382 */
31383 duk_hstring *h_tmp;
31384 duk_bool_t has_inherited;
31385
31386 /* XXX: refactor into an internal helper, pretty awkward */
31387 duk_push_uint((duk_context *) js_ctx->thr, (duk_uint_t) i);
31388 h_tmp = duk_to_hstring((duk_context *) js_ctx->thr, -1);
31389 DUK_ASSERT(h_tmp != NULL);
31390 has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
31391 duk_pop((duk_context *) js_ctx->thr);
31392
31393 if (has_inherited) {
31394 DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
31395 goto abort_fastpath;
31396 }
31397
31398 /* Ordinary gap, undefined encodes to 'null' in
31399 * standard JSON (and no JX/JC support here now).
31400 */
31401 DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
31402#if defined(DUK_USE_JX)
31404#else
31406#endif
31407 } else {
31408 if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
31410 }
31411 }
31412
31413 DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
31414 emitted = 1;
31415 }
31416
31417 if (emitted) {
31418 DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
31419 DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
31420 if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31421 DUK_ASSERT(js_ctx->recursion_depth >= 1);
31422 duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
31423 }
31424 }
31426 } else if (c_bit & c_unbox) {
31427 /* Certain boxed types are required to go through
31428 * automatic unboxing. Rely on internal value being
31429 * sane (to avoid infinite recursion).
31430 */
31431#if 1
31432 /* The code below is incorrect if .toString() or .valueOf() have
31433 * have been overridden. The correct approach would be to look up
31434 * the method(s) and if they resolve to the built-in function we
31435 * can safely bypass it and look up the internal value directly.
31436 * Unimplemented for now, abort fast path for boxed values.
31437 */
31438 goto abort_fastpath;
31439#else /* disabled */
31440 /* Disabled until fixed, see above. */
31441 duk_tval *tv_internal;
31442
31443 DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
31444
31445 tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
31446 DUK_ASSERT(tv_internal != NULL);
31447 DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
31448 DUK_TVAL_IS_NUMBER(tv_internal) ||
31449 DUK_TVAL_IS_BOOLEAN(tv_internal) ||
31450 DUK_TVAL_IS_POINTER(tv_internal));
31451
31452 tv = tv_internal;
31453 DUK_ASSERT(js_ctx->recursion_depth > 0);
31454 js_ctx->recursion_depth--; /* required to keep recursion depth correct */
31455 goto restart_match;
31456#endif /* disabled */
31457#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31458 } else if (c_bit & c_func) {
31460 } else if (c_bit & c_bufobj) {
31462#endif
31463 } else {
31464 DUK_ASSERT((c_bit & c_undef) != 0);
31465
31466 /* Must decrease recursion depth before returning. */
31467 DUK_ASSERT(js_ctx->recursion_depth > 0);
31468 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31469 js_ctx->recursion_depth--;
31470 goto emit_undefined;
31471 }
31472
31473 DUK_ASSERT(js_ctx->recursion_depth > 0);
31474 DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31475 js_ctx->recursion_depth--;
31476 break;
31477 }
31478 case DUK_TAG_BUFFER: {
31479#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31480 if (js_ctx->flag_ext_custom_or_compatible) {
31482 break;
31483 } else {
31484 goto emit_undefined;
31485 }
31486#else
31487 goto emit_undefined;
31488#endif
31489 }
31490 case DUK_TAG_POINTER: {
31491#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31492 if (js_ctx->flag_ext_custom_or_compatible) {
31494 break;
31495 } else {
31496 goto emit_undefined;
31497 }
31498#else
31499 goto emit_undefined;
31500#endif
31501 }
31502 case DUK_TAG_LIGHTFUNC: {
31503 /* A lightfunc might also inherit a .toJSON() so just bail out. */
31504 /* XXX: Could just lookup .toJSON() and continue in fast path,
31505 * as it would almost never be defined.
31506 */
31507 DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
31508 goto abort_fastpath;
31509 }
31510#if defined(DUK_USE_FASTINT)
31511 case DUK_TAG_FASTINT: {
31512 /* Number serialization has a significant impact relative to
31513 * other fast path code, so careful fast path for fastints.
31514 */
31515 duk__enc_fastint_tval(js_ctx, tv);
31516 break;
31517 }
31518#endif
31519 default: {
31520 /* XXX: A fast path for usual integers would be useful when
31521 * fastint support is not enabled.
31522 */
31525
31526 /* XXX: Stack discipline is annoying, could be changed in numconv. */
31527 duk_push_tval((duk_context *) js_ctx->thr, tv);
31528 duk__enc_double(js_ctx);
31529 duk_pop((duk_context *) js_ctx->thr);
31530
31531#if 0
31532 /* Could also rely on native sprintf(), but it will handle
31533 * values like NaN, Infinity, -0, exponent notation etc in
31534 * a JSON-incompatible way.
31535 */
31536 duk_double_t d;
31537 char buf[64];
31538
31540 d = DUK_TVAL_GET_DOUBLE(tv);
31541 DUK_SPRINTF(buf, "%lg", d);
31542 DUK__EMIT_CSTR(js_ctx, buf);
31543#endif
31544 }
31545 }
31546 return 1; /* not undefined */
31547
31548 emit_undefined:
31549 return 0; /* value was undefined/unsupported */
31550
31551 abort_fastpath:
31552 /* Error message doesn't matter: the error is ignored anyway. */
31553 DUK_DD(DUK_DDPRINT("aborting fast path"));
31555 return 0; /* unreachable */
31556}
31557
31558DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_context *ctx) {
31559 duk_json_enc_ctx *js_ctx;
31560 duk_tval *tv;
31561
31562 DUK_ASSERT(ctx != NULL);
31563 tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
31565 js_ctx = (duk_json_enc_ctx *) DUK_TVAL_GET_POINTER(tv);
31566 DUK_ASSERT(js_ctx != NULL);
31567
31568 tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
31569 if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
31570 DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
31571 return DUK_RET_ERROR; /* error message doesn't matter, ignored anyway */
31572 }
31573
31574 return 0;
31575}
31576#endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
31577
31578/*
31579 * Top level wrappers
31580 */
31581
31584 duk_idx_t idx_value,
31585 duk_idx_t idx_reviver,
31586 duk_small_uint_t flags) {
31587 duk_hthread *thr = (duk_hthread *) ctx;
31588 duk_json_dec_ctx js_ctx_alloc;
31589 duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
31590 duk_hstring *h_text;
31591#ifdef DUK_USE_ASSERTIONS
31592 duk_idx_t entry_top = duk_get_top(ctx);
31593#endif
31594
31595 /* negative top-relative indices not allowed now */
31596 DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
31597 DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
31598
31599 DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
31600 (duk_tval *) duk_get_tval(ctx, idx_value),
31601 (duk_tval *) duk_get_tval(ctx, idx_reviver),
31602 (unsigned long) flags,
31603 (long) duk_get_top(ctx)));
31604
31605 DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
31606 js_ctx->thr = thr;
31607#ifdef DUK_USE_EXPLICIT_NULL_INIT
31608 /* nothing now */
31609#endif
31611 DUK_ASSERT(js_ctx->recursion_depth == 0);
31612
31613 /* Flag handling currently assumes that flags are consistent. This is OK
31614 * because the call sites are now strictly controlled.
31615 */
31616
31617 js_ctx->flags = flags;
31618#if defined(DUK_USE_JX)
31619 js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
31620#endif
31621#if defined(DUK_USE_JC)
31623#endif
31624#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31626#endif
31627
31628 h_text = duk_to_hstring(ctx, idx_value); /* coerce in-place */
31629 DUK_ASSERT(h_text != NULL);
31630
31631 /* JSON parsing code is allowed to read [p_start,p_end]: p_end is
31632 * valid and points to the string NUL terminator (which is always
31633 * guaranteed for duk_hstrings.
31634 */
31635 js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
31636 js_ctx->p = js_ctx->p_start;
31637 js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
31639 DUK_ASSERT(*(js_ctx->p_end) == 0x00);
31640
31641 duk__dec_value(js_ctx); /* -> [ ... value ] */
31642
31643 /* Trailing whitespace has been eaten by duk__dec_value(), so if
31644 * we're not at end of input here, it's a SyntaxError.
31645 */
31646
31647 if (js_ctx->p != js_ctx->p_end) {
31648 duk__dec_syntax_error(js_ctx);
31649 }
31650
31651 if (duk_is_callable(ctx, idx_reviver)) {
31652 DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
31653 (duk_tval *) duk_get_tval(ctx, idx_reviver)));
31654
31655 js_ctx->idx_reviver = idx_reviver;
31656
31657 duk_push_object(ctx);
31658 duk_dup(ctx, -2); /* -> [ ... val root val ] */
31659 duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING); /* default attrs ok */
31660 duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); /* -> [ ... val root "" ] */
31661
31662 DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
31663 (duk_tval *) duk_get_tval(ctx, -2),
31664 (duk_tval *) duk_get_tval(ctx, -1)));
31665
31666 duk__dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */
31667 duk_remove(ctx, -2); /* -> [ ... val' ] */
31668 } else {
31669 DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
31670 (duk_tval *) duk_get_tval(ctx, idx_reviver)));
31671 }
31672
31673 /* Final result is at stack top. */
31674
31675 DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
31676 (duk_tval *) duk_get_tval(ctx, idx_value),
31677 (duk_tval *) duk_get_tval(ctx, idx_reviver),
31678 (unsigned long) flags,
31679 (duk_tval *) duk_get_tval(ctx, -1),
31680 (long) duk_get_top(ctx)));
31681
31682 DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
31683}
31684
31687 duk_idx_t idx_value,
31688 duk_idx_t idx_replacer,
31689 duk_idx_t idx_space,
31690 duk_small_uint_t flags) {
31691 duk_hthread *thr = (duk_hthread *) ctx;
31692 duk_json_enc_ctx js_ctx_alloc;
31693 duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
31694 duk_hobject *h;
31695 duk_idx_t idx_holder;
31696 duk_idx_t entry_top;
31697
31698 /* negative top-relative indices not allowed now */
31699 DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
31700 DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
31701 DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
31702
31703 DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
31704 (duk_tval *) duk_get_tval(ctx, idx_value),
31705 (duk_tval *) duk_get_tval(ctx, idx_replacer),
31706 (duk_tval *) duk_get_tval(ctx, idx_space),
31707 (unsigned long) flags,
31708 (long) duk_get_top(ctx)));
31709
31710 entry_top = duk_get_top(ctx);
31711
31712 /*
31713 * Context init
31714 */
31715
31716 DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
31717 js_ctx->thr = thr;
31718#ifdef DUK_USE_EXPLICIT_NULL_INIT
31719 js_ctx->h_replacer = NULL;
31720 js_ctx->h_gap = NULL;
31721#endif
31722 js_ctx->idx_proplist = -1;
31723
31724 /* Flag handling currently assumes that flags are consistent. This is OK
31725 * because the call sites are now strictly controlled.
31726 */
31727
31728 js_ctx->flags = flags;
31729 js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
31731#ifdef DUK_USE_JX
31732 js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
31733#endif
31734#ifdef DUK_USE_JC
31736#endif
31737#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31739#endif
31740
31741 /* The #ifdef clutter here handles the JX/JC enable/disable
31742 * combinations properly.
31743 */
31744#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31745 js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL; /* standard JSON; array gaps */
31746#if defined(DUK_USE_JX)
31747 if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
31752 js_ctx->stridx_custom_function =
31756 }
31757#endif /* DUK_USE_JX */
31758#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
31759 else
31760#endif /* DUK_USE_JX && DUK_USE_JC */
31761#if defined(DUK_USE_JC)
31762 if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
31768 }
31769#endif /* DUK_USE_JC */
31770#endif /* DUK_USE_JX || DUK_USE_JC */
31771
31772#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31773 if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
31775 DUK_ASSERT(js_ctx->mask_for_undefined == 0); /* already zero */
31776 }
31777 else
31778#endif /* DUK_USE_JX || DUK_USE_JC */
31779 {
31784 }
31785
31787
31788 js_ctx->idx_loop = duk_push_object_internal(ctx);
31789 DUK_ASSERT(js_ctx->idx_loop >= 0);
31790
31791 /* [ ... buf loop ] */
31792
31793 /*
31794 * Process replacer/proplist (2nd argument to JSON.stringify)
31795 */
31796
31797 h = duk_get_hobject(ctx, idx_replacer);
31798 if (h != NULL) {
31799 if (DUK_HOBJECT_IS_CALLABLE(h)) {
31800 js_ctx->h_replacer = h;
31802 /* Here the specification requires correct array index enumeration
31803 * which is a bit tricky for sparse arrays (it is handled by the
31804 * enum setup code). We now enumerate ancestors too, although the
31805 * specification is not very clear on whether that is required.
31806 */
31807
31808 duk_uarridx_t plist_idx = 0;
31809 duk_small_uint_t enum_flags;
31810
31811 js_ctx->idx_proplist = duk_push_array(ctx); /* XXX: array internal? */
31812
31813 enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
31814 DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */
31815 duk_enum(ctx, idx_replacer, enum_flags);
31816 while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) {
31817 /* [ ... proplist enum_obj key val ] */
31819 /* XXX: duplicates should be eliminated here */
31820 DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
31821 (duk_tval *) duk_get_tval(ctx, -2),
31822 (duk_tval *) duk_get_tval(ctx, -1)));
31823 duk_to_string(ctx, -1); /* extra coercion of strings is OK */
31824 duk_put_prop_index(ctx, -4, plist_idx); /* -> [ ... proplist enum_obj key ] */
31825 plist_idx++;
31826 duk_pop(ctx);
31827 } else {
31828 DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
31829 (duk_tval *) duk_get_tval(ctx, -2),
31830 (duk_tval *) duk_get_tval(ctx, -1)));
31831 duk_pop_2(ctx);
31832 }
31833 }
31834 duk_pop(ctx); /* pop enum */
31835
31836 /* [ ... proplist ] */
31837 }
31838 }
31839
31840 /* [ ... buf loop (proplist) ] */
31841
31842 /*
31843 * Process space (3rd argument to JSON.stringify)
31844 */
31845
31846 h = duk_get_hobject(ctx, idx_space);
31847 if (h != NULL) {
31849 if (c == DUK_HOBJECT_CLASS_NUMBER) {
31850 duk_to_number(ctx, idx_space);
31851 } else if (c == DUK_HOBJECT_CLASS_STRING) {
31852 duk_to_string(ctx, idx_space);
31853 }
31854 }
31855
31856 if (duk_is_number(ctx, idx_space)) {
31857 duk_small_int_t nspace;
31858 /* spaces[] must be static to allow initializer with old compilers like BCC */
31859 static const char spaces[10] = {
31863 }; /* XXX: helper */
31864
31865 /* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
31866 nspace = (duk_small_int_t) duk_to_int_clamped(ctx, idx_space, 0 /*minval*/, 10 /*maxval*/);
31867 DUK_ASSERT(nspace >= 0 && nspace <= 10);
31868
31869 duk_push_lstring(ctx, spaces, (duk_size_t) nspace);
31870 js_ctx->h_gap = duk_get_hstring(ctx, -1);
31871 DUK_ASSERT(js_ctx->h_gap != NULL);
31872 } else if (duk_is_string(ctx, idx_space)) {
31873 /* XXX: substring in-place at idx_place? */
31874 duk_dup(ctx, idx_space);
31875 duk_substring(ctx, -1, 0, 10); /* clamp to 10 chars */
31876 js_ctx->h_gap = duk_get_hstring(ctx, -1);
31877 DUK_ASSERT(js_ctx->h_gap != NULL);
31878 } else {
31879 /* nop */
31880 }
31881
31882 if (js_ctx->h_gap != NULL) {
31883 /* if gap is empty, behave as if not given at all */
31884 if (DUK_HSTRING_GET_CHARLEN(js_ctx->h_gap) == 0) {
31885 js_ctx->h_gap = NULL;
31886 }
31887 }
31888
31889 /* [ ... buf loop (proplist) (gap) ] */
31890
31891 /*
31892 * Fast path: assume no mutation, iterate object property tables
31893 * directly; bail out if that assumption doesn't hold.
31894 */
31895
31896#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
31897 if (js_ctx->h_replacer == NULL && /* replacer is a mutation risk */
31898 js_ctx->idx_proplist == -1) { /* proplist is very rare */
31899 duk_int_t pcall_rc;
31900#ifdef DUK_USE_MARK_AND_SWEEP
31901 duk_small_uint_t prev_mark_and_sweep_base_flags;
31902#endif
31903
31904 DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
31905
31906 /* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
31907 * array so we don't need two counter checks in the fast path. The
31908 * slow path has a much larger recursion limit which we'll use if
31909 * necessary.
31910 */
31913 DUK_ASSERT(js_ctx->recursion_depth == 0);
31914
31915 /* Execute the fast path in a protected call. If any error is thrown,
31916 * fall back to the slow path. This includes e.g. recursion limit
31917 * because the fast path has a smaller recursion limit (and simpler,
31918 * limited loop detection).
31919 */
31920
31921 duk_push_pointer(ctx, (void *) js_ctx);
31922 duk_dup(ctx, idx_value);
31923
31924#if defined(DUK_USE_MARK_AND_SWEEP)
31925 /* Must prevent finalizers which may have arbitrary side effects. */
31926 prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
31928 DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */
31929 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact any objects */
31930#endif
31931
31932 pcall_rc = duk_safe_call(ctx, duk__json_stringify_fast, 2 /*nargs*/, 0 /*nret*/);
31933
31934#if defined(DUK_USE_MARK_AND_SWEEP)
31935 thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
31936#endif
31937 if (pcall_rc == DUK_EXEC_SUCCESS) {
31938 DUK_DD(DUK_DDPRINT("fast path successful"));
31939 DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
31940 goto replace_finished;
31941 }
31942
31943 /* We come here for actual aborts (like encountering .toJSON())
31944 * but also for recursion/loop errors. Bufwriter size can be
31945 * kept because we'll probably need at least as much as we've
31946 * allocated so far.
31947 */
31948 DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
31949 DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
31950 js_ctx->recursion_depth = 0;
31951 }
31952#endif
31953
31954 /*
31955 * Create wrapper object and serialize
31956 */
31957
31958 idx_holder = duk_push_object(ctx);
31959 duk_dup(ctx, idx_value);
31961
31962 DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
31963 "proplist=%!T, gap=%!O, holder=%!T",
31964 (unsigned long) js_ctx->flags,
31965 (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
31966 (duk_heaphdr *) js_ctx->h_replacer,
31967 (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
31968 (duk_heaphdr *) js_ctx->h_gap,
31969 (duk_tval *) duk_get_tval(ctx, -1)));
31970
31971 /* serialize the wrapper with empty string key */
31972
31974
31975 /* [ ... buf loop (proplist) (gap) holder "" ] */
31976
31978 DUK_ASSERT(js_ctx->recursion_depth == 0);
31979
31980 if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */
31981 /* Result is undefined. */
31982 duk_push_undefined(ctx);
31983 } else {
31984 /* Convert buffer to result string. */
31985 DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
31986 }
31987
31988 DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
31989 "proplist=%!T, gap=%!O, holder=%!T",
31990 (unsigned long) js_ctx->flags,
31991 (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
31992 (duk_heaphdr *) js_ctx->h_replacer,
31993 (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
31994 (duk_heaphdr *) js_ctx->h_gap,
31995 (duk_tval *) duk_get_tval(ctx, idx_holder)));
31996
31997 /* The stack has a variable shape here, so force it to the
31998 * desired one explicitly.
31999 */
32000
32001#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
32002 replace_finished:
32003#endif
32004 duk_replace(ctx, entry_top);
32005 duk_set_top(ctx, entry_top + 1);
32007 DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
32008 "flags=0x%08lx, result=%!T, stack_top=%ld",
32009 (duk_tval *) duk_get_tval(ctx, idx_value),
32010 (duk_tval *) duk_get_tval(ctx, idx_replacer),
32011 (duk_tval *) duk_get_tval(ctx, idx_space),
32012 (unsigned long) flags,
32013 (duk_tval *) duk_get_tval(ctx, -1),
32014 (long) duk_get_top(ctx)));
32015
32016 DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
32017}
32018
32019/*
32020 * Entry points
32021 */
32022
32025 0 /*idx_value*/,
32026 1 /*idx_replacer*/,
32027 0 /*flags*/);
32028 return 1;
32029}
32030
32033 0 /*idx_value*/,
32034 1 /*idx_replacer*/,
32035 2 /*idx_space*/,
32036 0 /*flags*/);
32037 return 1;
32038}
32039
32040#undef DUK__JSON_DECSTR_BUFSIZE
32041#undef DUK__JSON_DECSTR_CHUNKSIZE
32042#undef DUK__JSON_ENCSTR_CHUNKSIZE
32043#undef DUK__JSON_STRINGIFY_BUFSIZE
32044#undef DUK__JSON_MAX_ESC_LEN
32045#line 1 "duk_bi_logger.c"
32047 * Logging support
32048 */
32049
32050/* include removed: duk_internal.h */
32051
32052/* 3-letter log level strings */
32053DUK_LOCAL const duk_uint8_t duk__log_level_strings[] = {
32054 (duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_C,
32055 (duk_uint8_t) DUK_ASC_UC_D, (duk_uint8_t) DUK_ASC_UC_B, (duk_uint8_t) DUK_ASC_UC_G,
32056 (duk_uint8_t) DUK_ASC_UC_I, (duk_uint8_t) DUK_ASC_UC_N, (duk_uint8_t) DUK_ASC_UC_F,
32057 (duk_uint8_t) DUK_ASC_UC_W, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_N,
32058 (duk_uint8_t) DUK_ASC_UC_E, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_R,
32059 (duk_uint8_t) DUK_ASC_UC_F, (duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_L
32060};
32061
32062/* Constructor */
32064 duk_hthread *thr = (duk_hthread *) ctx;
32065 duk_idx_t nargs;
32066
32067 /* Calling as a non-constructor is not meaningful. */
32068 if (!duk_is_constructor_call(ctx)) {
32069 return DUK_RET_TYPE_ERROR;
32070 }
32071
32072 nargs = duk_get_top(ctx);
32073 duk_set_top(ctx, 1);
32074
32075 duk_push_this(ctx);
32076
32077 /* [ name this ] */
32078
32079 if (nargs == 0) {
32080 /* Automatic defaulting of logger name from caller. This would
32081 * work poorly with tail calls, but constructor calls are currently
32082 * never tail calls, so tail calls are not an issue now.
32083 */
32084
32085 if (thr->callstack_top >= 2) {
32086 duk_activation *act_caller = thr->callstack + thr->callstack_top - 2;
32087 duk_hobject *func_caller;
32088
32089 func_caller = DUK_ACT_GET_FUNC(act_caller);
32090 if (func_caller) {
32091 /* Stripping the filename might be a good idea
32092 * ("/foo/bar/quux.js" -> logger name "quux"),
32093 * but now used verbatim.
32094 */
32095 duk_push_hobject(ctx, func_caller);
32097 duk_replace(ctx, 0);
32098 }
32099 }
32100 }
32101 /* the stack is unbalanced here on purpose; we only rely on the
32102 * initial two values: [ name this ].
32104
32105 if (duk_is_string(ctx, 0)) {
32106 duk_dup(ctx, 0);
32108 } else {
32109 /* don't set 'n' at all, inherited value is used as name */
32110 }
32111
32112 duk_compact(ctx, 1);
32113
32114 return 0; /* keep default instance */
32115}
32116
32117/* Default function to format objects. Tries to use toLogString() but falls
32118 * back to toString(). Any errors are propagated out without catching.
32119 */
32122 /* [ arg toLogString ] */
32123
32124 duk_dup(ctx, 0);
32125 duk_call_method(ctx, 0);
32126
32127 /* [ arg result ] */
32128 return 1;
32129 }
32130
32131 /* [ arg undefined ] */
32132 duk_pop(ctx);
32133 duk_to_string(ctx, 0);
32134 return 1;
32135}
32136
32137/* Default function to write a formatted log line. Writes to stderr,
32138 * appending a newline to the log line.
32139 *
32140 * The argument is a buffer whose visible size contains the log message.
32141 * This function should avoid coercing the buffer to a string to avoid
32142 * string table traffic.
32143 */
32145 const char *data;
32146 duk_size_t data_len;
32147
32148 DUK_UNREF(ctx);
32149 DUK_UNREF(data);
32150 DUK_UNREF(data_len);
32152#ifdef DUK_USE_FILE_IO
32153 data = (const char *) duk_require_buffer(ctx, 0, &data_len);
32154 DUK_FWRITE((const void *) data, 1, data_len, DUK_STDERR);
32155 DUK_FPUTC((int) '\n', DUK_STDERR);
32157#else
32158 /* nop */
32159#endif
32160 return 0;
32161}
32162
32163/* Log frontend shared helper, magic value indicates log level. Provides
32164 * frontend functions: trace(), debug(), info(), warn(), error(), fatal().
32165 * This needs to have small footprint, reasonable performance, minimal
32166 * memory churn, etc.
32167 */
32169 duk_hthread *thr = (duk_hthread *) ctx;
32170 duk_double_t now;
32171 duk_small_int_t entry_lev = duk_get_current_magic(ctx);
32172 duk_small_int_t logger_lev;
32173 duk_int_t nargs;
32174 duk_int_t i;
32175 duk_size_t tot_len;
32176 const duk_uint8_t *arg_str;
32177 duk_size_t arg_len;
32178 duk_uint8_t *buf, *p;
32179 const duk_uint8_t *q;
32180 duk_uint8_t date_buf[DUK_BI_DATE_ISO8601_BUFSIZE];
32181 duk_size_t date_len;
32182 duk_small_int_t rc;
32183
32184 DUK_ASSERT(entry_lev >= 0 && entry_lev <= 5);
32185 DUK_UNREF(thr);
32186
32187 /* XXX: sanitize to printable (and maybe ASCII) */
32188 /* XXX: better multiline */
32189
32190 /*
32191 * Logger arguments are:
32192 *
32193 * magic: log level (0-5)
32194 * this: logger
32195 * stack: plain log args
32196 *
32197 * We want to minimize memory churn so a two-pass approach
32198 * is used: first pass formats arguments and computes final
32199 * string length, second pass copies strings either into a
32200 * pre-allocated and reused buffer (short messages) or into a
32201 * newly allocated fixed buffer. If the backend function plays
32202 * nice, it won't coerce the buffer to a string (and thus
32203 * intern it).
32204 */
32205
32206 nargs = duk_get_top(ctx);
32207
32208 /* [ arg1 ... argN this ] */
32209
32210 /*
32211 * Log level check
32212 */
32213
32214 duk_push_this(ctx);
32215
32217 logger_lev = (duk_small_int_t) duk_get_int(ctx, -1);
32218 if (entry_lev < logger_lev) {
32219 return 0;
32220 }
32221 /* log level could be popped but that's not necessary */
32222
32223 now = DUK_USE_DATE_GET_NOW(ctx);
32224 duk_bi_date_format_timeval(now, date_buf);
32225 date_len = DUK_STRLEN((const char *) date_buf);
32226
32228 duk_to_string(ctx, -1);
32229 DUK_ASSERT(duk_is_string(ctx, -1));
32230
32231 /* [ arg1 ... argN this loggerLevel loggerName ] */
32232
32233 /*
32234 * Pass 1
32235 */
32236
32237 /* Line format: <time> <entryLev> <loggerName>: <msg> */
32238
32239 tot_len = 0;
32240 tot_len += 3 + /* separators: space, space, colon */
32241 3 + /* level string */
32242 date_len + /* time */
32243 duk_get_length(ctx, -1); /* loggerName */
32244
32245 for (i = 0; i < nargs; i++) {
32246 /* When formatting an argument to a string, errors may happen from multiple
32247 * causes. In general we want to catch obvious errors like a toLogString()
32248 * throwing an error, but we don't currently try to catch every possible
32249 * error. In particular, internal errors (like out of memory or stack) are
32250 * not caught. Also, we expect Error toString() to not throw an error.
32251 */
32252 if (duk_is_object(ctx, i)) {
32253 /* duk_pcall_prop() may itself throw an error, but we're content
32254 * in catching the obvious errors (like toLogString() throwing an
32255 * error).
32256 */
32258 duk_dup(ctx, i);
32259 /* [ arg1 ... argN this loggerLevel loggerName 'fmt' arg ] */
32260 /* call: this.fmt(arg) */
32261 rc = duk_pcall_prop(ctx, -5 /*obj_index*/, 1 /*nargs*/);
32262 if (rc) {
32263 /* Keep the error as the result (coercing it might fail below,
32264 * but we don't catch that now).
32265 */
32266 ;
32267 }
32268 duk_replace(ctx, i);
32269 }
32270 (void) duk_to_lstring(ctx, i, &arg_len);
32271 tot_len++; /* sep (even before first one) */
32272 tot_len += arg_len;
32273 }
32274
32275 /*
32276 * Pass 2
32277 */
32278
32279 /* XXX: There used to be a shared log buffer here, but it was removed
32280 * when dynamic buffer spare was removed. The problem with using
32281 * bufwriter is that, without the spare, the buffer gets passed on
32282 * as an argument to the raw() call so it'd need to be resized
32283 * (reallocated) anyway. If raw() call convention is changed, this
32284 * could be made more efficient.
32285 */
32286
32287 buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, tot_len);
32288 DUK_ASSERT(buf != NULL);
32289 p = buf;
32290
32291 DUK_MEMCPY((void *) p, (const void *) date_buf, (size_t) date_len);
32292 p += date_len;
32293 *p++ = (duk_uint8_t) DUK_ASC_SPACE;
32294
32295 q = duk__log_level_strings + (entry_lev * 3);
32296 DUK_MEMCPY((void *) p, (const void *) q, (size_t) 3);
32297 p += 3;
32298
32299 *p++ = (duk_uint8_t) DUK_ASC_SPACE;
32300
32301 arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, -2, &arg_len);
32302 DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
32303 p += arg_len;
32304
32305 *p++ = (duk_uint8_t) DUK_ASC_COLON;
32306
32307 for (i = 0; i < nargs; i++) {
32308 *p++ = (duk_uint8_t) DUK_ASC_SPACE;
32309
32310 arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &arg_len);
32311 DUK_ASSERT(arg_str != NULL);
32312 DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
32313 p += arg_len;
32314 }
32315 DUK_ASSERT(buf + tot_len == p);
32316
32317 /* [ arg1 ... argN this loggerLevel loggerName buffer ] */
32318
32319#if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_LOGGING)
32320 /* Do debugger forwarding before raw() because the raw() function
32321 * doesn't get the log level right now.
32322 */
32323 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
32324 const char *log_buf;
32325 duk_size_t sz_buf;
32326 log_buf = (const char *) duk_get_buffer(ctx, -1, &sz_buf);
32327 DUK_ASSERT(log_buf != NULL);
32328 duk_debug_write_notify(thr, DUK_DBG_CMD_LOG);
32329 duk_debug_write_int(thr, (duk_int32_t) entry_lev);
32330 duk_debug_write_string(thr, (const char *) log_buf, sz_buf);
32331 duk_debug_write_eom(thr);
32332 }
32333#endif
32334
32335 /* Call this.raw(msg); look up through the instance allows user to override
32336 * the raw() function in the instance or in the prototype for maximum
32337 * flexibility.
32338 */
32340 duk_dup(ctx, -2);
32341 /* [ arg1 ... argN this loggerLevel loggerName buffer 'raw' buffer ] */
32342 duk_call_prop(ctx, -6, 1); /* this.raw(buffer) */
32343
32344 return 0;
32345}
32346#line 1 "duk_bi_math.c"
32348 * Math built-ins
32349 */
32351/* include removed: duk_internal.h */
32352
32353#if defined(DUK_USE_MATH_BUILTIN)
32354
32355/*
32356 * Use static helpers which can work with math.h functions matching
32357 * the following signatures. This is not portable if any of these math
32358 * functions is actually a macro.
32359 *
32360 * Typing here is intentionally 'double' wherever values interact with
32361 * the standard library APIs.
32362 */
32363
32364typedef double (*duk__one_arg_func)(double);
32365typedef double (*duk__two_arg_func)(double, double);
32366
32368 duk_idx_t n = duk_get_top(ctx);
32369 duk_idx_t i;
32370 duk_double_t res = initial;
32371 duk_double_t t;
32372
32373 /*
32374 * Note: fmax() does not match the E5 semantics. E5 requires
32375 * that if -any- input to Math.max() is a NaN, the result is a
32376 * NaN. fmax() will return a NaN only if -both- inputs are NaN.
32377 * Same applies to fmin().
32378 *
32379 * Note: every input value must be coerced with ToNumber(), even
32380 * if we know the result will be a NaN anyway: ToNumber() may have
32381 * side effects for which even order of evaluation matters.
32382 */
32383
32384 for (i = 0; i < n; i++) {
32385 t = duk_to_number(ctx, i);
32386 if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
32387 /* Note: not normalized, but duk_push_number() will normalize */
32389 } else {
32390 res = (duk_double_t) min_max(res, (double) t);
32391 }
32392 }
32393
32394 duk_push_number(ctx, res);
32395 return 1;
32396}
32397
32398DUK_LOCAL double duk__fmin_fixed(double x, double y) {
32399 /* fmin() with args -0 and +0 is not guaranteed to return
32400 * -0 as Ecmascript requires.
32401 */
32402 if (x == 0 && y == 0) {
32403 /* XXX: what's the safest way of creating a negative zero? */
32404 if (DUK_SIGNBIT(x) != 0 || DUK_SIGNBIT(y) != 0) {
32405 return -0.0;
32406 } else {
32407 return +0.0;
32408 }
32409 }
32410#ifdef DUK_USE_MATH_FMIN
32411 return DUK_FMIN(x, y);
32412#else
32413 return (x < y ? x : y);
32414#endif
32415}
32416
32417DUK_LOCAL double duk__fmax_fixed(double x, double y) {
32418 /* fmax() with args -0 and +0 is not guaranteed to return
32419 * +0 as Ecmascript requires.
32420 */
32421 if (x == 0 && y == 0) {
32422 if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
32423 return +0.0;
32424 } else {
32425 return -0.0;
32426 }
32427 }
32428#ifdef DUK_USE_MATH_FMAX
32429 return DUK_FMAX(x, y);
32430#else
32431 return (x > y ? x : y);
32432#endif
32433}
32434
32435DUK_LOCAL double duk__round_fixed(double x) {
32436 /* Numbers half-way between integers must be rounded towards +Infinity,
32437 * e.g. -3.5 must be rounded to -3 (not -4). When rounded to zero, zero
32438 * sign must be set appropriately. E5.1 Section 15.8.2.15.
32439 *
32440 * Note that ANSI C round() is "round to nearest integer, away from zero",
32441 * which is incorrect for negative values. Here we make do with floor().
32442 */
32443
32445 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
32446 return x;
32447 }
32448
32449 /*
32450 * x is finite and non-zero
32451 *
32452 * -1.6 -> floor(-1.1) -> -2
32453 * -1.5 -> floor(-1.0) -> -1 (towards +Inf)
32454 * -1.4 -> floor(-0.9) -> -1
32455 * -0.5 -> -0.0 (special case)
32456 * -0.1 -> -0.0 (special case)
32457 * +0.1 -> +0.0 (special case)
32458 * +0.5 -> floor(+1.0) -> 1 (towards +Inf)
32459 * +1.4 -> floor(+1.9) -> 1
32460 * +1.5 -> floor(+2.0) -> 2 (towards +Inf)
32461 * +1.6 -> floor(+2.1) -> 2
32462 */
32463
32464 if (x >= -0.5 && x < 0.5) {
32465 /* +0.5 is handled by floor, this is on purpose */
32466 if (x < 0.0) {
32467 return -0.0;
32468 } else {
32469 return +0.0;
32470 }
32471 }
32472
32473 return DUK_FLOOR(x + 0.5);
32474}
32475
32476DUK_LOCAL double duk__pow_fixed(double x, double y) {
32477 /* The ANSI C pow() semantics differ from Ecmascript.
32478 *
32479 * E.g. when x==1 and y is +/- infinite, the Ecmascript required
32480 * result is NaN, while at least Linux pow() returns 1.
32481 */
32482
32483 duk_small_int_t cx, cy, sx;
32484
32485 DUK_UNREF(cx);
32486 DUK_UNREF(sx);
32488
32489 if (cy == DUK_FP_NAN) {
32490 goto ret_nan;
32491 }
32492 if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
32493 goto ret_nan;
32494 }
32495#if defined(DUK_USE_POW_NETBSD_WORKAROUND)
32496 /* See test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least) does not
32497 * correctly handle some cases where x=+/-0. Specific fixes to these
32498 * here.
32499 */
32501 if (cx == DUK_FP_ZERO && y < 0.0) {
32502 sx = (duk_small_int_t) DUK_SIGNBIT(x);
32503 if (sx == 0) {
32504 /* Math.pow(+0,y) should be Infinity when y<0. NetBSD pow()
32505 * returns -Infinity instead when y is <0 and finite. The
32506 * if-clause also catches y == -Infinity (which works even
32507 * without the fix).
32508 */
32509 return DUK_DOUBLE_INFINITY;
32510 } else {
32511 /* Math.pow(-0,y) where y<0 should be:
32512 * - -Infinity if y<0 and an odd integer
32513 * - Infinity otherwise
32514 * NetBSD pow() returns -Infinity for all finite y<0. The
32515 * if-clause also catches y == -Infinity (which works even
32516 * without the fix).
32517 */
32518
32519 /* fmod() return value has same sign as input (negative) so
32520 * the result here will be in the range ]-2,0], 1 indicates
32521 * odd. If x is -Infinity, NaN is returned and the odd check
32522 * always concludes "not odd" which results in desired outcome.
32523 */
32524 double tmp = DUK_FMOD(y, 2);
32525 if (tmp == -1.0) {
32526 return -DUK_DOUBLE_INFINITY;
32527 } else {
32528 /* Not odd, or y == -Infinity */
32529 return DUK_DOUBLE_INFINITY;
32530 }
32532 }
32533#endif
32534 return DUK_POW(x, y);
32535
32536 ret_nan:
32538}
32539
32540/* Wrappers for calling standard math library methods. These may be required
32541 * on platforms where one or more of the math built-ins are defined as macros
32542 * or inline functions and are thus not suitable to be used as function pointers.
32544#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32545DUK_LOCAL double duk__fabs(double x) {
32546 return DUK_FABS(x);
32547}
32548DUK_LOCAL double duk__acos(double x) {
32549 return DUK_ACOS(x);
32550}
32551DUK_LOCAL double duk__asin(double x) {
32552 return DUK_ASIN(x);
32553}
32554DUK_LOCAL double duk__atan(double x) {
32555 return DUK_ATAN(x);
32556}
32557DUK_LOCAL double duk__ceil(double x) {
32558 return DUK_CEIL(x);
32559}
32560DUK_LOCAL double duk__cos(double x) {
32561 return DUK_COS(x);
32562}
32563DUK_LOCAL double duk__exp(double x) {
32564 return DUK_EXP(x);
32565}
32566DUK_LOCAL double duk__floor(double x) {
32567 return DUK_FLOOR(x);
32568}
32569DUK_LOCAL double duk__log(double x) {
32570 return DUK_LOG(x);
32571}
32572DUK_LOCAL double duk__sin(double x) {
32573 return DUK_SIN(x);
32574}
32575DUK_LOCAL double duk__sqrt(double x) {
32576 return DUK_SQRT(x);
32577}
32578DUK_LOCAL double duk__tan(double x) {
32579 return DUK_TAN(x);
32580}
32581DUK_LOCAL double duk__atan2(double x, double y) {
32582 return DUK_ATAN2(x, y);
32583}
32584#endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
32585
32586/* order must match constants in genbuiltins.py */
32588#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32589 duk__fabs,
32590 duk__acos,
32591 duk__asin,
32592 duk__atan,
32593 duk__ceil,
32594 duk__cos,
32595 duk__exp,
32596 duk__floor,
32597 duk__log,
32599 duk__sin,
32600 duk__sqrt,
32601 duk__tan
32602#else
32604 DUK_ACOS,
32605 DUK_ASIN,
32606 DUK_ATAN,
32607 DUK_CEIL,
32608 DUK_COS,
32609 DUK_EXP,
32610 DUK_FLOOR,
32611 DUK_LOG,
32614 DUK_SQRT,
32615 DUK_TAN
32616#endif
32617};
32618
32619/* order must match constants in genbuiltins.py */
32621#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32622 duk__atan2,
32624#else
32625 DUK_ATAN2,
32627#endif
32628};
32629
32633
32634 DUK_ASSERT(fun_idx >= 0);
32636 fun = duk__one_arg_funcs[fun_idx];
32637 duk_push_number(ctx, (duk_double_t) fun((double) duk_to_number(ctx, 0)));
32638 return 1;
32644
32645 DUK_ASSERT(fun_idx >= 0);
32646 DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
32647 fun = duk__two_arg_funcs[fun_idx];
32648 duk_push_number(ctx, (duk_double_t) fun((double) duk_to_number(ctx, 0), (double) duk_to_number(ctx, 1)));
32649 return 1;
32650}
32651
32654}
32655
32658}
32659
32662 return 1;
32663}
32664
32665#else /* DUK_USE_MATH_BUILTIN */
32666
32667/* A stubbed built-in is useful for e.g. compilation torture testing with BCC. */
32668
32670 DUK_UNREF(ctx);
32672}
32673
32675 DUK_UNREF(ctx);
32677}
32678
32680 DUK_UNREF(ctx);
32682}
32683
32687}
32688
32690 DUK_UNREF(ctx);
32692}
32693
32694#endif /* DUK_USE_MATH_BUILTIN */
32695#line 1 "duk_bi_number.c"
32696/*
32697 * Number built-ins
32698 */
32699
32700/* include removed: duk_internal.h */
32701
32703 duk_hobject *h;
32704
32705 /* Number built-in accepts a plain number or a Number object (whose
32706 * internal value is operated on). Other types cause TypeError.
32707 */
32708
32709 duk_push_this(ctx);
32710 if (duk_is_number(ctx, -1)) {
32711 DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
32712 goto done;
32714 h = duk_get_hobject(ctx, -1);
32715 if (!h ||
32717 DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
32718 DUK_ERROR_TYPE((duk_hthread *) ctx, "number expected");
32719 }
32721 DUK_ASSERT(duk_is_number(ctx, -1));
32722 DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
32723 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
32724 duk_remove(ctx, -2);
32725
32726 done:
32727 return duk_get_number(ctx, -1);
32728}
32729
32731 duk_hthread *thr = (duk_hthread *) ctx;
32732 duk_idx_t nargs;
32733 duk_hobject *h_this;
32734
32735 DUK_UNREF(thr);
32736
32737 /*
32738 * The Number constructor uses ToNumber(arg) for number coercion
32739 * (coercing an undefined argument to NaN). However, if the
32740 * argument is not given at all, +0 must be used instead. To do
32741 * this, a vararg function is used.
32742 */
32743
32744 nargs = duk_get_top(ctx);
32745 if (nargs == 0) {
32746 duk_push_int(ctx, 0);
32747 }
32748 duk_to_number(ctx, 0);
32749 duk_set_top(ctx, 1);
32750 DUK_ASSERT_TOP(ctx, 1);
32751
32752 if (!duk_is_constructor_call(ctx)) {
32753 return 1;
32754 }
32755
32756 /*
32757 * E5 Section 15.7.2.1 requires that the constructed object
32758 * must have the original Number.prototype as its internal
32759 * prototype. However, since Number.prototype is non-writable
32760 * and non-configurable, this doesn't have to be enforced here:
32761 * The default object (bound to 'this') is OK, though we have
32762 * to change its class.
32763 *
32764 * Internal value set to ToNumber(arg) or +0; if no arg given,
32765 * ToNumber(undefined) = NaN, so special treatment is needed
32766 * (above). String internal value is immutable.
32768
32769 /* XXX: helper */
32770 duk_push_this(ctx);
32771 h_this = duk_get_hobject(ctx, -1);
32772 DUK_ASSERT(h_this != NULL);
32774
32778
32779 duk_dup(ctx, 0); /* -> [ val obj val ] */
32781 return 0; /* no return value -> don't replace created value */
32782}
32783
32785 (void) duk__push_this_number_plain(ctx);
32786 return 1;
32787}
32788
32790 duk_small_int_t radix;
32791 duk_small_uint_t n2s_flags;
32792
32794 if (duk_is_undefined(ctx, 0)) {
32795 radix = 10;
32796 } else {
32797 radix = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 2, 36);
32798 }
32799 DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
32800
32801 n2s_flags = 0;
32802
32804 radix /*radix*/,
32805 0 /*digits*/,
32806 n2s_flags /*flags*/);
32807 return 1;
32808}
32809
32811 /* XXX: just use toString() for now; permitted although not recommended.
32812 * nargs==1, so radix is passed to toString().
32813 */
32815}
32816
32817/*
32818 * toFixed(), toExponential(), toPrecision()
32819 */
32820
32821/* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
32822
32824 duk_small_int_t frac_digits;
32825 duk_double_t d;
32827 duk_small_uint_t n2s_flags;
32828
32829 frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
32831
32833 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
32834 goto use_to_string;
32835 }
32836
32837 if (d >= 1.0e21 || d <= -1.0e21) {
32838 goto use_to_string;
32840
32841 n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
32843
32845 10 /*radix*/,
32846 frac_digits /*digits*/,
32847 n2s_flags /*flags*/);
32848 return 1;
32849
32850 use_to_string:
32851 DUK_ASSERT_TOP(ctx, 2);
32852 duk_to_string(ctx, -1);
32853 return 1;
32854}
32855
32857 duk_bool_t frac_undefined;
32858 duk_small_int_t frac_digits;
32859 duk_double_t d;
32861 duk_small_uint_t n2s_flags;
32862
32864
32865 frac_undefined = duk_is_undefined(ctx, 0);
32866 duk_to_int(ctx, 0); /* for side effects */
32867
32869 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
32870 goto use_to_string;
32871 }
32872
32873 frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
32874
32875 n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
32876 (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
32877
32879 10 /*radix*/,
32880 frac_digits + 1 /*leading digit + fractions*/,
32881 n2s_flags /*flags*/);
32882 return 1;
32883
32884 use_to_string:
32885 DUK_ASSERT_TOP(ctx, 2);
32886 duk_to_string(ctx, -1);
32887 return 1;
32888}
32889
32891 /* The specification has quite awkward order of coercion and
32892 * checks for toPrecision(). The operations below are a bit
32893 * reordered, within constraints of observable side effects.
32894 */
32895
32896 duk_double_t d;
32897 duk_small_int_t prec;
32899 duk_small_uint_t n2s_flags;
32900
32901 DUK_ASSERT_TOP(ctx, 1);
32902
32904 if (duk_is_undefined(ctx, 0)) {
32905 goto use_to_string;
32906 }
32907 DUK_ASSERT_TOP(ctx, 2);
32908
32909 duk_to_int(ctx, 0); /* for side effects */
32910
32912 if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
32913 goto use_to_string;
32914 }
32915
32916 prec = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 1, 21);
32917
32918 n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
32920
32922 10 /*radix*/,
32923 prec /*digits*/,
32924 n2s_flags /*flags*/);
32925 return 1;
32927 use_to_string:
32928 /* Used when precision is undefined; also used for NaN (-> "NaN"),
32929 * and +/- infinity (-> "Infinity", "-Infinity").
32930 */
32931
32932 DUK_ASSERT_TOP(ctx, 2);
32933 duk_to_string(ctx, -1);
32934 return 1;
32935}
32936#line 1 "duk_bi_object.c"
32937/*
32938 * Object built-ins
32939 */
32940
32941/* include removed: duk_internal.h */
32942
32944 if (!duk_is_constructor_call(ctx) &&
32945 !duk_is_null_or_undefined(ctx, 0)) {
32946 duk_to_object(ctx, 0);
32947 return 1;
32948 }
32949
32950 if (duk_is_object(ctx, 0)) {
32951 return 1;
32952 }
32953
32954 /* Pointer and buffer primitive values are treated like other
32955 * primitives values which have a fully fledged object counterpart:
32956 * promote to an object value. Lightfuncs are coerced with
32957 * ToObject() even they could also be returned as is.
32958 */
32965 duk_to_object(ctx, 0);
32966 return 1;
32967 }
32968
32973 return 1;
32974}
32975
32976/* Shared helper to implement Object.getPrototypeOf and the ES6
32977 * Object.prototype.__proto__ getter.
32978 *
32979 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
32980 */
32982 duk_hthread *thr = (duk_hthread *) ctx;
32983 duk_hobject *h;
32985
32986 DUK_UNREF(thr);
32987
32988 /* magic: 0=getter call, 1=Object.getPrototypeOf */
32989 if (duk_get_current_magic(ctx) == 0) {
32991 duk_insert(ctx, 0);
32992 }
32993
32994 h = duk_require_hobject_or_lfunc(ctx, 0);
32995 /* h is NULL for lightfunc */
32996
32997 /* XXX: should the API call handle this directly, i.e. attempt
32998 * to duk_push_hobject(ctx, null) would push a null instead?
32999 * (On the other hand 'undefined' would be just as logical, but
33000 * not wanted here.)
33001 */
33002
33003 if (h == NULL) {
33005 } else {
33007 if (proto) {
33008 duk_push_hobject(ctx, proto);
33009 } else {
33010 duk_push_null(ctx);
33011 }
33012 }
33013 return 1;
33014}
33015
33016/* Shared helper to implement ES6 Object.setPrototypeOf and
33017 * Object.prototype.__proto__ setter.
33018 *
33019 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
33020 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
33021 */
33023 duk_hthread *thr = (duk_hthread *) ctx;
33024 duk_hobject *h_obj;
33025 duk_hobject *h_new_proto;
33026 duk_hobject *h_curr;
33027 duk_ret_t ret_success = 1; /* retval for success path */
33028
33029 /* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4);
33030 * magic: 0=setter call, 1=Object.setPrototypeOf
33031 */
33032 if (duk_get_current_magic(ctx) == 0) {
33034 duk_insert(ctx, 0);
33036 return 0;
33037 }
33038
33039 /* __proto__ setter returns 'undefined' on success unlike the
33040 * setPrototypeOf() call which returns the target object.
33041 */
33042 ret_success = 0;
33043 } else {
33046 }
33047
33048 h_new_proto = duk_get_hobject(ctx, 1);
33049 /* h_new_proto may be NULL */
33050 if (duk_is_lightfunc(ctx, 0)) {
33051 if (h_new_proto == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]) {
33052 goto skip;
33053 }
33054 goto fail_nonextensible;
33055 }
33056 h_obj = duk_get_hobject(ctx, 0);
33057 if (!h_obj) {
33058 goto skip;
33059 }
33060 DUK_ASSERT(h_obj != NULL);
33061
33062 /* [[SetPrototypeOf]] standard behavior, E6 9.1.2 */
33063 /* TODO: implement Proxy object support here */
33064
33065 if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
33066 goto skip;
33067 }
33068 if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
33069 goto fail_nonextensible;
33070 }
33071 for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
33072 /* Loop prevention */
33073 if (h_curr == h_obj) {
33074 goto fail_loop;
33075 }
33076 }
33077 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
33078 /* fall thru */
33079
33080 skip:
33081 duk_set_top(ctx, 1);
33082 return ret_success;
33083
33084 fail_nonextensible:
33085 fail_loop:
33086 return DUK_RET_TYPE_ERROR;
33087}
33088
33090 /* XXX: no need for indirect call */
33092}
33093
33095 duk_tval *tv;
33097
33098 DUK_ASSERT_TOP(ctx, 2);
33099
33100 tv = duk_get_tval(ctx, 0);
33101 DUK_ASSERT(tv != NULL);
33102 if (DUK_TVAL_IS_NULL(tv)) {
33103 ;
33104 } else if (DUK_TVAL_IS_OBJECT(tv)) {
33106 DUK_ASSERT(proto != NULL);
33107 } else {
33108 return DUK_RET_TYPE_ERROR;
33109 }
33110
33114 proto);
33115
33116 if (!duk_is_undefined(ctx, 1)) {
33117 /* [ O Properties obj ] */
33119 duk_replace(ctx, 0);
33120
33121 /* [ obj Properties ] */
33122
33123 /* Just call the "original" Object.defineProperties() to
33124 * finish up.
33125 */
33126
33128 }
33129
33130 /* [ O Properties obj ] */
33131
33132 return 1;
33133}
33134
33136 duk_hobject *obj;
33137 duk_hstring *key;
33138 duk_hobject *get;
33139 duk_hobject *set;
33140 duk_idx_t idx_value;
33141 duk_uint_t defprop_flags;
33142
33143 DUK_ASSERT(ctx != NULL);
33144
33145 DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
33146 (void *) ctx,
33147 (duk_tval *) duk_get_tval(ctx, 0),
33148 (duk_tval *) duk_get_tval(ctx, 1),
33149 (duk_tval *) duk_get_tval(ctx, 2)));
33150
33151 /* [ obj key desc ] */
33152
33153 /* Lightfuncs are currently supported by coercing to a temporary
33154 * Function object; changes will be allowed (the coerced value is
33155 * extensible) but will be lost.
33156 */
33158 (void) duk_to_string(ctx, 1);
33159 key = duk_require_hstring(ctx, 1);
33160 (void) duk_require_hobject(ctx, 2);
33161
33162 DUK_ASSERT(obj != NULL);
33163 DUK_ASSERT(key != NULL);
33164 DUK_ASSERT(duk_get_hobject(ctx, 2) != NULL);
33165
33166 /*
33167 * Validate and convert argument property descriptor (an Ecmascript
33168 * object) into a set of defprop_flags and possibly property value,
33169 * getter, and/or setter values on the value stack.
33170 *
33171 * Lightfunc set/get values are coerced to full Functions.
33172 */
33173
33175 2 /*idx_desc*/,
33176 &defprop_flags,
33177 &idx_value,
33178 &get,
33179 &set);
33180
33181 /*
33182 * Use Object.defineProperty() helper for the actual operation.
33183 */
33184
33186 defprop_flags,
33187 obj,
33188 key,
33189 idx_value,
33190 get,
33191 set);
33192
33193 /* Ignore the normalize/validate helper outputs on the value stack,
33194 * they're popped automatically.
33195 */
33196
33197 /*
33198 * Return target object.
33199 */
33200
33201 duk_push_hobject(ctx, obj);
33202 return 1;
33203}
33204
33206 duk_small_uint_t pass;
33207 duk_uint_t defprop_flags;
33208 duk_hobject *obj;
33209 duk_idx_t idx_value;
33210 duk_hobject *get;
33211 duk_hobject *set;
33212
33213 /* Lightfunc handling by ToObject() coercion. */
33214 obj = duk_require_hobject_or_lfunc_coerce(ctx, 0); /* target */
33215 DUK_ASSERT(obj != NULL);
33216
33217 duk_to_object(ctx, 1); /* properties object */
33218
33219 DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
33220 (duk_tval *) duk_get_tval(ctx, 0),
33221 (duk_tval *) duk_get_tval(ctx, 1)));
33222
33223 /*
33224 * Two pass approach to processing the property descriptors.
33225 * On first pass validate and normalize all descriptors before
33226 * any changes are made to the target object. On second pass
33227 * make the actual modifications to the target object.
33228 *
33229 * Right now we'll just use the same normalize/validate helper
33230 * on both passes, ignoring its outputs on the first pass.
33231 */
33232
33233 for (pass = 0; pass < 2; pass++) {
33234 duk_set_top(ctx, 2); /* -> [ hobject props ] */
33235 duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/);
33236
33237 for (;;) {
33238 duk_hstring *key;
33239
33240 /* [ hobject props enum(props) ] */
33241
33242 duk_set_top(ctx, 3);
33243
33244 if (!duk_next(ctx, 2, 1 /*get_value*/)) {
33245 break;
33246 }
33247
33248 DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
33249 (duk_tval *) duk_get_tval(ctx, -2),
33250 (duk_tval *) duk_get_tval(ctx, -1)));
33251
33252 /* [ hobject props enum(props) key desc ] */
33253
33255 4 /*idx_desc*/,
33256 &defprop_flags,
33257 &idx_value,
33258 &get,
33259 &set);
33260
33261 /* [ hobject props enum(props) key desc value? getter? setter? ] */
33262
33263 if (pass == 0) {
33264 continue;
33265 }
33266
33267 key = duk_get_hstring(ctx, 3);
33268 DUK_ASSERT(key != NULL);
33269
33271 defprop_flags,
33272 obj,
33273 key,
33274 idx_value,
33275 get,
33276 set);
33277 }
33278 }
33279
33280 /*
33281 * Return target object
33282 */
33283
33284 duk_dup(ctx, 0);
33285 return 1;
33286}
33287
33289 duk_hthread *thr = (duk_hthread *) ctx;
33290 duk_hobject *h;
33291 duk_bool_t is_freeze;
33292
33294 if (!h) {
33295 /* Lightfunc, always success. */
33296 return 1;
33297 }
33298
33299 is_freeze = (duk_bool_t) duk_get_current_magic(ctx);
33300 duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
33301
33302 /* Sealed and frozen objects cannot gain any more properties,
33303 * so this is a good time to compact them.
33304 */
33306
33307 return 1;
33308}
33309
33311 duk_hthread *thr = (duk_hthread *) ctx;
33312 duk_hobject *h;
33313
33315 if (!h) {
33316 /* Lightfunc, always success. */
33317 return 1;
33318 }
33319 DUK_ASSERT(h != NULL);
33320
33322
33323 /* A non-extensible object cannot gain any more properties,
33324 * so this is a good time to compact.
33325 */
33327
33328 return 1;
33329}
33332 duk_hobject *h;
33333 duk_bool_t is_frozen;
33334 duk_bool_t rc;
33335
33336 h = duk_require_hobject_or_lfunc(ctx, 0);
33337 if (!h) {
33338 duk_push_true(ctx); /* frozen and sealed */
33339 } else {
33340 is_frozen = duk_get_current_magic(ctx);
33341 rc = duk_hobject_object_is_sealed_frozen_helper((duk_hthread *) ctx, h, is_frozen /*is_frozen*/);
33342 duk_push_boolean(ctx, rc);
33343 }
33344 return 1;
33346
33348 duk_hobject *h;
33349
33350 h = duk_require_hobject_or_lfunc(ctx, 0);
33351 if (!h) {
33352 duk_push_false(ctx);
33353 } else {
33355 }
33356 return 1;
33357}
33358
33359/* Shared helper for Object.getOwnPropertyNames() and Object.keys().
33360 * Magic: 0=getOwnPropertyNames, 1=Object.keys.
33361 */
33363 duk_hthread *thr = (duk_hthread *) ctx;
33364 duk_hobject *obj;
33365#if defined(DUK_USE_ES6_PROXY)
33366 duk_hobject *h_proxy_target;
33367 duk_hobject *h_proxy_handler;
33368 duk_hobject *h_trap_result;
33369 duk_uarridx_t i, len, idx;
33370#endif
33371 duk_small_uint_t enum_flags;
33372
33373 DUK_ASSERT_TOP(ctx, 1);
33374 DUK_UNREF(thr);
33375
33377 DUK_ASSERT(obj != NULL);
33378 DUK_UNREF(obj);
33379
33380#if defined(DUK_USE_ES6_PROXY)
33382 obj,
33383 &h_proxy_target,
33384 &h_proxy_handler))) {
33385 goto skip_proxy;
33386 }
33387
33388 duk_push_hobject(ctx, h_proxy_handler);
33390 /* Careful with reachability here: don't pop 'obj' before pushing
33391 * proxy target.
33392 */
33393 DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
33394 duk_pop_2(ctx);
33395 duk_push_hobject(ctx, h_proxy_target);
33396 duk_replace(ctx, 0);
33397 DUK_ASSERT_TOP(ctx, 1);
33398 goto skip_proxy;
33399 }
33400
33401 /* [ obj handler trap ] */
33402 duk_insert(ctx, -2);
33403 duk_push_hobject(ctx, h_proxy_target); /* -> [ obj trap handler target ] */
33404 duk_call_method(ctx, 1 /*nargs*/); /* -> [ obj trap_result ] */
33405 h_trap_result = duk_require_hobject(ctx, -1);
33406 DUK_UNREF(h_trap_result);
33407
33408 len = (duk_uarridx_t) duk_get_length(ctx, -1);
33409 idx = 0;
33410 duk_push_array(ctx);
33411 for (i = 0; i < len; i++) {
33412 /* [ obj trap_result res_arr ] */
33413 if (duk_get_prop_index(ctx, -2, i) && duk_is_string(ctx, -1)) {
33414 /* XXX: for Object.keys() we should check enumerability of key */
33415 /* [ obj trap_result res_arr propname ] */
33416 duk_put_prop_index(ctx, -2, idx);
33417 idx++;
33418 } else {
33419 duk_pop(ctx);
33420 }
33421 }
33422
33423 /* XXX: missing trap result validation for non-configurable target keys
33424 * (must be present), for non-extensible target all target keys must be
33425 * present and no extra keys can be present.
33426 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
33427 */
33428
33429 /* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
33430 * should be filtered so that only enumerable keys remain. Enumerability
33431 * should be checked with [[GetOwnProperty]] on the original object
33432 * (i.e., the proxy in this case). If the proxy has a getOwnPropertyDescriptor
33433 * trap, it should be triggered for every property. If the proxy doesn't have
33434 * the trap, enumerability should be checked against the target object instead.
33435 * We don't do any of this now, so Object.keys() and Object.getOwnPropertyNames()
33436 * return the same result now for proxy traps. We still do clean up the trap
33437 * result, so that Object.keys() and Object.getOwnPropertyNames() will return a
33438 * clean array of strings without gaps.
33439 */
33440 return 1;
33441
33442 skip_proxy:
33443#endif /* DUK_USE_ES6_PROXY */
33445 DUK_ASSERT_TOP(ctx, 1);
33446
33447 if (duk_get_current_magic(ctx)) {
33448 /* Object.keys */
33449 enum_flags = DUK_ENUM_OWN_PROPERTIES_ONLY |
33451 } else {
33452 /* Object.getOwnPropertyNames */
33453 enum_flags = DUK_ENUM_INCLUDE_NONENUMERABLE |
33456 }
33457
33458 return duk_hobject_get_enumerated_keys(ctx, enum_flags);
33459}
33460
33464 return 1;
33465}
33466
33468 DUK_ASSERT_TOP(ctx, 0);
33471 if (!duk_is_callable(ctx, 1)) {
33472 return DUK_RET_TYPE_ERROR;
33473 }
33474 duk_dup(ctx, 0); /* -> [ O toString O ] */
33475 duk_call_method(ctx, 0); /* XXX: call method tail call? */
33476 return 1;
33477}
33478
33481 return 1;
33482}
33483
33485 duk_hthread *thr = (duk_hthread *) ctx;
33486 duk_hobject *h_v;
33487 duk_hobject *h_obj;
33488
33489 DUK_ASSERT_TOP(ctx, 1);
33491 h_v = duk_get_hobject(ctx, 0);
33492 if (!h_v) {
33493 duk_push_false(ctx); /* XXX: tail call: return duk_push_false(ctx) */
33494 return 1;
33495 }
33496
33498 DUK_ASSERT(h_obj != NULL);
33499
33500 /* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
33501 * Prototype loops should cause an error to be thrown.
33502 */
33503 duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
33504 return 1;
33505}
33506
33508 return duk_hobject_object_ownprop_helper(ctx, 0 /*required_desc_flags*/);
33509}
33510
33512 return duk_hobject_object_ownprop_helper(ctx, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
33513}
33514#line 1 "duk_bi_pointer.c"
33515/*
33516 * Pointer built-ins
33517 */
33518
33519/* include removed: duk_internal.h */
33520
33521/*
33522 * Constructor
33523 */
33524
33526 /* XXX: this behavior is quite useless now; it would be nice to be able
33527 * to create pointer values from e.g. numbers or strings. Numbers are
33528 * problematic on 64-bit platforms though. Hex encoded strings?
33529 */
33530 if (duk_get_top(ctx) == 0) {
33531 duk_push_pointer(ctx, NULL);
33532 } else {
33533 duk_to_pointer(ctx, 0);
33534 }
33535 DUK_ASSERT(duk_is_pointer(ctx, 0));
33536 duk_set_top(ctx, 1);
33537
33538 if (duk_is_constructor_call(ctx)) {
33543
33544 /* Pointer object internal value is immutable */
33545 duk_dup(ctx, 0);
33547 }
33548 /* Note: unbalanced stack on purpose */
33549
33550 return 1;
33551}
33552
33553/*
33554 * toString(), valueOf()
33555 */
33556
33558 duk_tval *tv;
33559 duk_small_int_t to_string = duk_get_current_magic(ctx);
33560
33561 duk_push_this(ctx);
33562 tv = duk_require_tval(ctx, -1);
33563 DUK_ASSERT(tv != NULL);
33564
33565 if (DUK_TVAL_IS_POINTER(tv)) {
33566 /* nop */
33567 } else if (DUK_TVAL_IS_OBJECT(tv)) {
33569 DUK_ASSERT(h != NULL);
33570
33571 /* Must be a "pointer object", i.e. class "Pointer" */
33573 goto type_error;
33574 }
33575
33577 } else {
33578 goto type_error;
33579 }
33581 if (to_string) {
33582 duk_to_string(ctx, -1);
33583 }
33584 return 1;
33585
33586 type_error:
33587 return DUK_RET_TYPE_ERROR;
33588}
33589#line 1 "duk_bi_proxy.c"
33590/*
33591 * Proxy built-in (ES6)
33592 */
33593
33594/* include removed: duk_internal.h */
33595
33596#if defined(DUK_USE_ES6_PROXY)
33598 duk_hobject *h_target;
33599 duk_hobject *h_handler;
33600
33601 if (!duk_is_constructor_call(ctx)) {
33602 return DUK_RET_TYPE_ERROR;
33603 }
33604
33605 /* Reject a proxy object as the target because it would need
33606 * special handler in property lookups. (ES6 has no such restriction)
33607 */
33608 h_target = duk_require_hobject_or_lfunc_coerce(ctx, 0);
33609 DUK_ASSERT(h_target != NULL);
33610 if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_target)) {
33611 return DUK_RET_TYPE_ERROR;
33612 }
33613
33614 /* Reject a proxy object as the handler because it would cause
33615 * potentially unbounded recursion. (ES6 has no such restriction)
33616 */
33617 h_handler = duk_require_hobject_or_lfunc_coerce(ctx, 1);
33618 DUK_ASSERT(h_handler != NULL);
33619 if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_handler)) {
33620 return DUK_RET_TYPE_ERROR;
33621 }
33622
33623 /* XXX: the returned value is exotic in ES6, but we use a
33624 * simple object here with no prototype. Without a prototype,
33625 * [[DefaultValue]] coercion fails which is abit confusing.
33626 * No callable check/handling in the current Proxy subset.
33627 */
33632 NULL);
33633 DUK_ASSERT_TOP(ctx, 3);
33634
33635 /* Make _Target and _Handler non-configurable and non-writable.
33636 * They can still be forcibly changed by C code (both user and
33637 * Duktape internal), but not by Ecmascript code.
33638 */
33639
33640 /* Proxy target */
33641 duk_dup(ctx, 0);
33643
33644 /* Proxy handler */
33645 duk_dup(ctx, 1);
33647
33648 return 1; /* replacement handler */
33649}
33650#else /* DUK_USE_ES6_PROXY */
33652 DUK_UNREF(ctx);
33654}
33655#endif /* DUK_USE_ES6_PROXY */
33656#line 1 "duk_bi_regexp.c"
33657/*
33658 * RegExp built-ins
33660
33661/* include removed: duk_internal.h */
33662
33663#ifdef DUK_USE_REGEXP_SUPPORT
33664
33666 duk_hobject *h;
33667
33668 duk_push_this(ctx);
33670 DUK_ASSERT(h != NULL);
33671 DUK_UNREF(h);
33672 duk_insert(ctx, 0); /* prepend regexp to valstack 0 index */
33673}
33674
33675/* XXX: much to improve (code size) */
33677 duk_hthread *thr = (duk_hthread *) ctx;
33678 duk_hobject *h_pattern;
33679
33680 DUK_ASSERT_TOP(ctx, 2);
33681 h_pattern = duk_get_hobject(ctx, 0);
33682
33683 if (!duk_is_constructor_call(ctx) &&
33684 h_pattern != NULL &&
33686 duk_is_undefined(ctx, 1)) {
33687 /* Called as a function, pattern has [[Class]] "RegExp" and
33688 * flags is undefined -> return object as is.
33689 */
33690 duk_dup(ctx, 0);
33691 return 1;
33692 }
33693
33694 /* Else functionality is identical for function call and constructor
33695 * call.
33696 */
33697
33698 if (h_pattern != NULL &&
33700 if (duk_is_undefined(ctx, 1)) {
33701 duk_bool_t flag_g, flag_i, flag_m;
33706
33707 duk_push_sprintf(ctx, "%s%s%s",
33708 (const char *) (flag_g ? "g" : ""),
33709 (const char *) (flag_i ? "i" : ""),
33710 (const char *) (flag_m ? "m" : ""));
33711
33712 /* [ ... pattern flags ] */
33713 } else {
33714 return DUK_RET_TYPE_ERROR;
33715 }
33716 } else {
33717 if (duk_is_undefined(ctx, 0)) {
33718 duk_push_string(ctx, "");
33719 } else {
33720 duk_dup(ctx, 0);
33721 duk_to_string(ctx, -1);
33722 }
33723 if (duk_is_undefined(ctx, 1)) {
33724 duk_push_string(ctx, "");
33725 } else {
33726 duk_dup(ctx, 1);
33727 duk_to_string(ctx, -1);
33728 }
33729
33730 /* [ ... pattern flags ] */
33731 }
33733 DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
33734 (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
33735
33736 /* [ ... pattern flags ] */
33737
33738 duk_regexp_compile(thr);
33739
33740 /* [ ... bytecode escaped_source ] */
33741
33743
33744 /* [ ... RegExp ] */
33745
33746 return 1;
33747}
33748
33751
33752 /* [ regexp input ] */
33753
33755
33756 /* [ result ] */
33757
33758 return 1;
33760
33763
33764 /* [ regexp input ] */
33765
33766 /* result object is created and discarded; wasteful but saves code space */
33768
33769 /* [ result ] */
33770
33771 duk_push_boolean(ctx, (duk_is_null(ctx, -1) ? 0 : 1));
33772
33773 return 1;
33774}
33775
33777 duk_hstring *h_bc;
33778 duk_small_int_t re_flags;
33779
33780#if 0
33781 /* A little tricky string approach to provide the flags string.
33782 * This depends on the specific flag values in duk_regexp.h,
33783 * which needs to be asserted for. In practice this doesn't
33784 * produce more compact code than the easier approach in use.
33785 */
33786
33787 const char *flag_strings = "gim\0gi\0gm\0g\0";
33788 duk_uint8_t flag_offsets[8] = {
33789 (duk_uint8_t) 3, /* flags: "" */
33790 (duk_uint8_t) 10, /* flags: "g" */
33791 (duk_uint8_t) 5, /* flags: "i" */
33792 (duk_uint8_t) 4, /* flags: "gi" */
33793 (duk_uint8_t) 2, /* flags: "m" */
33794 (duk_uint8_t) 7, /* flags: "gm" */
33795 (duk_uint8_t) 1, /* flags: "im" */
33796 (duk_uint8_t) 0, /* flags: "gim" */
33797 };
33801#endif
33802
33804
33805 /* [ regexp ] */
33806
33809 h_bc = duk_get_hstring(ctx, -1);
33810 DUK_ASSERT(h_bc != NULL);
33813 DUK_ASSERT(DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);
33814 re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
33815
33816 /* [ regexp source bytecode ] */
33817
33818#if 1
33819 /* This is a cleaner approach and also produces smaller code than
33820 * the other alternative. Use duk_require_string() for format
33821 * safety (although the source property should always exist).
33822 */
33823 duk_push_sprintf(ctx, "/%s/%s%s%s",
33824 (const char *) duk_require_string(ctx, -2), /* require to be safe */
33825 (re_flags & DUK_RE_FLAG_GLOBAL) ? "g" : "",
33826 (re_flags & DUK_RE_FLAG_IGNORE_CASE) ? "i" : "",
33827 (re_flags & DUK_RE_FLAG_MULTILINE) ? "m" : "");
33828#else
33829 /* This should not be necessary because no-one should tamper with the
33830 * regexp bytecode, but is prudent to avoid potential segfaults if that
33831 * were to happen for some reason.
33832 */
33833 re_flags &= 0x07;
33834 DUK_ASSERT(re_flags >= 0 && re_flags <= 7); /* three flags */
33835 duk_push_sprintf(ctx, "/%s/%s",
33836 (const char *) duk_require_string(ctx, -2),
33837 (const char *) (flag_strings + flag_offsets[re_flags]));
33838#endif
33839
33840 return 1;
33841}
33842
33843#else /* DUK_USE_REGEXP_SUPPORT */
33844
33846 DUK_UNREF(ctx);
33848}
33849
33851 DUK_UNREF(ctx);
33853}
33854
33856 DUK_UNREF(ctx);
33858}
33859
33861 DUK_UNREF(ctx);
33863}
33864
33865#endif /* DUK_USE_REGEXP_SUPPORT */
33866#line 1 "duk_bi_string.c"
33867/*
33868 * String built-ins
33870
33871/* XXX: There are several limitations in the current implementation for
33872 * strings with >= 0x80000000UL characters. In some cases one would need
33873 * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
33874 * Generally character and byte length are assumed to fit into signed 32
33875 * bits (< 0x80000000UL). Places with issues are not marked explicitly
33876 * below in all cases, look for signed type usage (duk_int_t etc) for
33877 * offsets/lengths.
33878 */
33879
33880/* include removed: duk_internal.h */
33881
33882/*
33883 * Constructor
33884 */
33885
33887 /* String constructor needs to distinguish between an argument not given at all
33888 * vs. given as 'undefined'. We're a vararg function to handle this properly.
33889 */
33890
33891 if (duk_get_top(ctx) == 0) {
33893 } else {
33894 duk_to_string(ctx, 0);
33895 }
33896 DUK_ASSERT(duk_is_string(ctx, 0));
33897 duk_set_top(ctx, 1);
33899 if (duk_is_constructor_call(ctx)) {
33905
33906 /* String object internal value is immutable */
33907 duk_dup(ctx, 0);
33909 }
33910 /* Note: unbalanced stack on purpose */
33911
33912 return 1;
33913}
33914
33916 duk_hthread *thr = (duk_hthread *) ctx;
33917 duk_bufwriter_ctx bw_alloc;
33919 duk_idx_t i, n;
33921
33922 /* XXX: It would be nice to build the string directly but ToUint16()
33923 * coercion is needed so a generic helper would not be very
33924 * helpful (perhaps coerce the value stack first here and then
33925 * build a string from a duk_tval number sequence in one go?).
33926 */
33927
33928 n = duk_get_top(ctx);
33929
33930 bw = &bw_alloc;
33931 DUK_BW_INIT_PUSHBUF(thr, bw, n); /* initial estimate for ASCII only codepoints */
33932
33933 for (i = 0; i < n; i++) {
33934 /* XXX: could improve bufwriter handling to write multiple codepoints
33935 * with one ensure call but the relative benefit would be quite small.
33936 */
33937
33938#if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
33939 /* ToUint16() coercion is mandatory in the E5.1 specification, but
33940 * this non-compliant behavior makes more sense because we support
33941 * non-BMP codepoints. Don't use CESU-8 because that'd create
33942 * surrogate pairs.
33943 */
33944
33946 DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
33947#else
33948 cp = (duk_ucodepoint_t) duk_to_uint16(ctx, i);
33949 DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
33950#endif
33951 }
33952
33953 DUK_BW_COMPACT(thr, bw);
33954 duk_to_string(ctx, -1);
33955 return 1;
33956}
33957
33958/*
33959 * toString(), valueOf()
33960 */
33961
33963 duk_tval *tv;
33964
33965 duk_push_this(ctx);
33966 tv = duk_require_tval(ctx, -1);
33967 DUK_ASSERT(tv != NULL);
33968
33969 if (DUK_TVAL_IS_STRING(tv)) {
33970 /* return as is */
33971 return 1;
33972 } else if (DUK_TVAL_IS_OBJECT(tv)) {
33974 DUK_ASSERT(h != NULL);
33975
33976 /* Must be a "string object", i.e. class "String" */
33978 goto type_error;
33979 }
33980
33983
33984 return 1;
33985 } else {
33986 goto type_error;
33987 }
33988
33989 /* never here, but fall through */
33990
33991 type_error:
33992 return DUK_RET_TYPE_ERROR;
33994
33995/*
33996 * Character and charcode access
33997 */
33998
34000 duk_int_t pos;
34001
34002 /* XXX: faster implementation */
34003
34005 pos = duk_to_int(ctx, 0);
34006 duk_substring(ctx, -1, pos, pos + 1);
34007 return 1;
34008}
34009
34011 duk_hthread *thr = (duk_hthread *) ctx;
34012 duk_int_t pos;
34013 duk_hstring *h;
34014 duk_bool_t clamped;
34015
34016 /* XXX: faster implementation */
34017
34018 DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(ctx, 0)));
34019
34021 DUK_ASSERT(h != NULL);
34022
34023 pos = duk_to_int_clamped_raw(ctx,
34024 0 /*index*/,
34025 0 /*min(incl)*/,
34026 DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
34027 &clamped /*out_clamped*/);
34028 if (clamped) {
34030 return 1;
34031 }
34032
34033 duk_push_u32(ctx, (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, pos));
34034 return 1;
34035}
34036
34037/*
34038 * substring(), substr(), slice()
34039 */
34040
34041/* XXX: any chance of merging these three similar but still slightly
34042 * different algorithms so that footprint would be reduced?
34043 */
34044
34046 duk_hstring *h;
34047 duk_int_t start_pos, end_pos;
34048 duk_int_t len;
34049
34051 DUK_ASSERT(h != NULL);
34053
34054 /* [ start end str ] */
34055
34056 start_pos = duk_to_int_clamped(ctx, 0, 0, len);
34057 if (duk_is_undefined(ctx, 1)) {
34058 end_pos = len;
34059 } else {
34060 end_pos = duk_to_int_clamped(ctx, 1, 0, len);
34062 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34063 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34064
34065 if (start_pos > end_pos) {
34066 duk_int_t tmp = start_pos;
34067 start_pos = end_pos;
34068 end_pos = tmp;
34069 }
34070
34071 DUK_ASSERT(end_pos >= start_pos);
34072
34073 duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34074 return 1;
34075}
34076
34077#ifdef DUK_USE_SECTION_B
34079 duk_hstring *h;
34080 duk_int_t start_pos, end_pos;
34081 duk_int_t len;
34082
34083 /* Unlike non-obsolete String calls, substr() algorithm in E5.1
34084 * specification will happily coerce undefined and null to strings
34085 * ("undefined" and "null").
34086 */
34087 duk_push_this(ctx);
34088 h = duk_to_hstring(ctx, -1);
34089 DUK_ASSERT(h != NULL);
34091
34092 /* [ start length str ] */
34093
34094 /* The implementation for computing of start_pos and end_pos differs
34095 * from the standard algorithm, but is intended to result in the exactly
34096 * same behavior. This is not always obvious.
34097 */
34098
34099 /* combines steps 2 and 5; -len ensures max() not needed for step 5 */
34100 start_pos = duk_to_int_clamped(ctx, 0, -len, len);
34101 if (start_pos < 0) {
34102 start_pos = len + start_pos;
34103 }
34104 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34105
34106 /* combines steps 3, 6; step 7 is not needed */
34107 if (duk_is_undefined(ctx, 1)) {
34108 end_pos = len;
34109 } else {
34110 DUK_ASSERT(start_pos <= len);
34111 end_pos = start_pos + duk_to_int_clamped(ctx, 1, 0, len - start_pos);
34112 }
34113 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34114 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34115 DUK_ASSERT(end_pos >= start_pos);
34116
34117 duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34118 return 1;
34119}
34120#else /* DUK_USE_SECTION_B */
34122 DUK_UNREF(ctx);
34124}
34125#endif /* DUK_USE_SECTION_B */
34126
34128 duk_hstring *h;
34129 duk_int_t start_pos, end_pos;
34130 duk_int_t len;
34131
34133 DUK_ASSERT(h != NULL);
34135
34136 /* [ start end str ] */
34137
34138 start_pos = duk_to_int_clamped(ctx, 0, -len, len);
34139 if (start_pos < 0) {
34140 start_pos = len + start_pos;
34141 }
34142 if (duk_is_undefined(ctx, 1)) {
34143 end_pos = len;
34144 } else {
34145 end_pos = duk_to_int_clamped(ctx, 1, -len, len);
34146 if (end_pos < 0) {
34147 end_pos = len + end_pos;
34148 }
34149 }
34150 DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34151 DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34152
34153 if (end_pos < start_pos) {
34154 end_pos = start_pos;
34155 }
34156
34157 DUK_ASSERT(end_pos >= start_pos);
34158
34159 duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34160 return 1;
34161}
34162
34164 * Case conversion
34165 */
34166
34168 duk_hthread *thr = (duk_hthread *) ctx;
34169 duk_small_int_t uppercase = duk_get_current_magic(ctx);
34170
34173 return 1;
34174}
34175
34176/*
34177 * indexOf() and lastIndexOf()
34178 */
34179
34181 duk_hthread *thr = (duk_hthread *) ctx;
34182 duk_hstring *h_this;
34183 duk_hstring *h_search;
34184 duk_int_t clen_this;
34185 duk_int_t cpos;
34186 duk_int_t bpos;
34187 const duk_uint8_t *p_start, *p_end, *p;
34188 const duk_uint8_t *q_start;
34189 duk_int_t q_blen;
34190 duk_uint8_t firstbyte;
34191 duk_uint8_t t;
34192 duk_small_int_t is_lastindexof = duk_get_current_magic(ctx); /* 0=indexOf, 1=lastIndexOf */
34193
34195 DUK_ASSERT(h_this != NULL);
34196 clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
34197
34198 h_search = duk_to_hstring(ctx, 0);
34199 DUK_ASSERT(h_search != NULL);
34200 q_start = DUK_HSTRING_GET_DATA(h_search);
34201 q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
34202
34203 duk_to_number(ctx, 1);
34204 if (duk_is_nan(ctx, 1) && is_lastindexof) {
34205 /* indexOf: NaN should cause pos to be zero.
34206 * lastIndexOf: NaN should cause pos to be +Infinity
34207 * (and later be clamped to len).
34208 */
34209 cpos = clen_this;
34210 } else {
34211 cpos = duk_to_int_clamped(ctx, 1, 0, clen_this);
34212 }
34213
34214 /* Empty searchstring always matches; cpos must be clamped here.
34215 * (If q_blen were < 0 due to clamped coercion, it would also be
34216 * caught here.)
34217 */
34218 if (q_blen <= 0) {
34219 duk_push_int(ctx, cpos);
34220 return 1;
34221 }
34222 DUK_ASSERT(q_blen > 0);
34223
34224 bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
34225
34226 p_start = DUK_HSTRING_GET_DATA(h_this);
34227 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
34228 p = p_start + bpos;
34229
34230 /* This loop is optimized for size. For speed, there should be
34231 * two separate loops, and we should ensure that memcmp() can be
34232 * used without an extra "will searchstring fit" check. Doing
34233 * the preconditioning for 'p' and 'p_end' is easy but cpos
34234 * must be updated if 'p' is wound back (backward scanning).
34235 */
34236
34237 firstbyte = q_start[0]; /* leading byte of match string */
34238 while (p <= p_end && p >= p_start) {
34239 t = *p;
34240
34241 /* For Ecmascript strings, this check can only match for
34242 * initial UTF-8 bytes (not continuation bytes). For other
34243 * strings all bets are off.
34244 */
34245
34246 if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
34247 DUK_ASSERT(q_blen > 0); /* no issues with memcmp() zero size, even if broken */
34248 if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34249 duk_push_int(ctx, cpos);
34250 return 1;
34251 }
34252 }
34253
34254 /* track cpos while scanning */
34255 if (is_lastindexof) {
34256 /* when going backwards, we decrement cpos 'early';
34257 * 'p' may point to a continuation byte of the char
34258 * at offset 'cpos', but that's OK because we'll
34259 * backtrack all the way to the initial byte.
34260 */
34261 if ((t & 0xc0) != 0x80) {
34262 cpos--;
34263 }
34264 p--;
34265 } else {
34266 if ((t & 0xc0) != 0x80) {
34267 cpos++;
34268 }
34269 p++;
34270 }
34271 }
34272
34273 /* Not found. Empty string case is handled specially above. */
34274 duk_push_int(ctx, -1);
34275 return 1;
34277
34278/*
34279 * replace()
34280 */
34281
34282/* XXX: the current implementation works but is quite clunky; it compiles
34283 * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
34284 * shared helpers, etc). Some ideas for refactoring:
34285 *
34286 * - a primitive to convert a string into a regexp matcher (reduces matching
34287 * code at the cost of making matching much slower)
34288 * - use replace() as a basic helper for match() and split(), which are both
34289 * much simpler
34290 * - API call to get_prop and to_boolean
34291 */
34292
34294 duk_hthread *thr = (duk_hthread *) ctx;
34295 duk_hstring *h_input;
34296 duk_hstring *h_match;
34297 duk_hstring *h_search;
34298 duk_hobject *h_re;
34299 duk_bufwriter_ctx bw_alloc;
34301#ifdef DUK_USE_REGEXP_SUPPORT
34302 duk_bool_t is_regexp;
34303 duk_bool_t is_global;
34304#endif
34305 duk_bool_t is_repl_func;
34306 duk_uint32_t match_start_coff, match_start_boff;
34307#ifdef DUK_USE_REGEXP_SUPPORT
34308 duk_int_t match_caps;
34309#endif
34310 duk_uint32_t prev_match_end_boff;
34311 const duk_uint8_t *r_start, *r_end, *r; /* repl string scan */
34312 duk_size_t tmp_sz;
34313
34314 DUK_ASSERT_TOP(ctx, 2);
34315 h_input = duk_push_this_coercible_to_string(ctx);
34316 DUK_ASSERT(h_input != NULL);
34317
34318 bw = &bw_alloc;
34319 DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* input size is good output starting point */
34320
34321 DUK_ASSERT_TOP(ctx, 4);
34322
34323 /* stack[0] = search value
34324 * stack[1] = replace value
34325 * stack[2] = input string
34326 * stack[3] = result buffer
34327 */
34328
34330 if (h_re) {
34331#ifdef DUK_USE_REGEXP_SUPPORT
34332 is_regexp = 1;
34334
34335 if (is_global) {
34336 /* start match from beginning */
34337 duk_push_int(ctx, 0);
34339 }
34340#else /* DUK_USE_REGEXP_SUPPORT */
34342#endif /* DUK_USE_REGEXP_SUPPORT */
34343 } else {
34344 duk_to_string(ctx, 0);
34345#ifdef DUK_USE_REGEXP_SUPPORT
34346 is_regexp = 0;
34347 is_global = 0;
34348#endif
34349 }
34350
34351 if (duk_is_function(ctx, 1)) {
34352 is_repl_func = 1;
34353 r_start = NULL;
34354 r_end = NULL;
34355 } else {
34356 duk_hstring *h_repl;
34357
34358 is_repl_func = 0;
34359 h_repl = duk_to_hstring(ctx, 1);
34360 DUK_ASSERT(h_repl != NULL);
34361 r_start = DUK_HSTRING_GET_DATA(h_repl);
34362 r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
34363 }
34364
34365 prev_match_end_boff = 0;
34366
34367 for (;;) {
34368 /*
34369 * If matching with a regexp:
34370 * - non-global RegExp: lastIndex not touched on a match, zeroed
34371 * on a non-match
34372 * - global RegExp: on match, lastIndex will be updated by regexp
34373 * executor to point to next char after the matching part (so that
34374 * characters in the matching part are not matched again)
34375 *
34376 * If matching with a string:
34377 * - always non-global match, find first occurrence
34378 *
34379 * We need:
34380 * - The character offset of start-of-match for the replacer function
34381 * - The byte offsets for start-of-match and end-of-match to implement
34382 * the replacement values $&, $`, and $', and to copy non-matching
34383 * input string portions (including header and trailer) verbatim.
34384 *
34385 * NOTE: the E5.1 specification is a bit vague how the RegExp should
34386 * behave in the replacement process; e.g. is matching done first for
34387 * all matches (in the global RegExp case) before any replacer calls
34388 * are made? See: test-bi-string-proto-replace.js for discussion.
34389 */
34390
34391 DUK_ASSERT_TOP(ctx, 4);
34392
34393#ifdef DUK_USE_REGEXP_SUPPORT
34394 if (is_regexp) {
34395 duk_dup(ctx, 0);
34396 duk_dup(ctx, 2);
34397 duk_regexp_match(thr); /* [ ... regexp input ] -> [ res_obj ] */
34398 if (!duk_is_object(ctx, -1)) {
34399 duk_pop(ctx);
34400 break;
34401 }
34402
34404 DUK_ASSERT(duk_is_number(ctx, -1));
34405 match_start_coff = duk_get_int(ctx, -1);
34406 duk_pop(ctx);
34407
34408 duk_get_prop_index(ctx, -1, 0);
34409 DUK_ASSERT(duk_is_string(ctx, -1));
34410 h_match = duk_get_hstring(ctx, -1);
34411 DUK_ASSERT(h_match != NULL);
34412 duk_pop(ctx); /* h_match is borrowed, remains reachable through match_obj */
34413
34414 if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
34415 /* This should be equivalent to match() algorithm step 8.f.iii.2:
34416 * detect an empty match and allow it, but don't allow it twice.
34417 */
34418 duk_uint32_t last_index;
34419
34421 last_index = (duk_uint32_t) duk_get_uint(ctx, -1);
34422 DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
34423 (long) last_index, (long) (last_index + 1)));
34424 duk_pop(ctx);
34425 duk_push_int(ctx, last_index + 1);
34427 }
34428
34429 DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_INT_MAX); /* string limits */
34430 match_caps = (duk_int_t) duk_get_length(ctx, -1);
34431 } else {
34432#else /* DUK_USE_REGEXP_SUPPORT */
34433 { /* unconditionally */
34434#endif /* DUK_USE_REGEXP_SUPPORT */
34435 const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
34436 const duk_uint8_t *q_start; /* match string */
34437 duk_size_t q_blen;
34438
34439#ifdef DUK_USE_REGEXP_SUPPORT
34440 DUK_ASSERT(!is_global); /* single match always */
34441#endif
34442
34443 p_start = DUK_HSTRING_GET_DATA(h_input);
34444 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
34445 p = p_start;
34446
34447 h_search = duk_get_hstring(ctx, 0);
34448 DUK_ASSERT(h_search != NULL);
34449 q_start = DUK_HSTRING_GET_DATA(h_search);
34450 q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
34451
34452 p_end -= q_blen; /* ensure full memcmp() fits in while */
34453
34454 match_start_coff = 0;
34455
34456 while (p <= p_end) {
34457 DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
34458 if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34459 duk_dup(ctx, 0);
34460 h_match = duk_get_hstring(ctx, -1);
34461 DUK_ASSERT(h_match != NULL);
34462#ifdef DUK_USE_REGEXP_SUPPORT
34463 match_caps = 0;
34464#endif
34465 goto found;
34466 }
34467
34468 /* track utf-8 non-continuation bytes */
34469 if ((p[0] & 0xc0) != 0x80) {
34470 match_start_coff++;
34471 }
34472 p++;
34473 }
34474
34475 /* not found */
34476 break;
34477 }
34478 found:
34479
34480 /* stack[0] = search value
34481 * stack[1] = replace value
34482 * stack[2] = input string
34483 * stack[3] = result buffer
34484 * stack[4] = regexp match OR match string
34485 */
34486
34487 match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
34488
34489 tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
34490 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
34491
34492 prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
34493
34494 if (is_repl_func) {
34495 duk_idx_t idx_args;
34496 duk_hstring *h_repl;
34497
34498 /* regexp res_obj is at index 4 */
34499
34500 duk_dup(ctx, 1);
34501 idx_args = duk_get_top(ctx);
34502
34503#ifdef DUK_USE_REGEXP_SUPPORT
34504 if (is_regexp) {
34505 duk_int_t idx;
34506 duk_require_stack(ctx, match_caps + 2);
34507 for (idx = 0; idx < match_caps; idx++) {
34508 /* match followed by capture(s) */
34509 duk_get_prop_index(ctx, 4, idx);
34510 }
34511 } else {
34512#else /* DUK_USE_REGEXP_SUPPORT */
34513 { /* unconditionally */
34514#endif /* DUK_USE_REGEXP_SUPPORT */
34515 /* match == search string, by definition */
34516 duk_dup(ctx, 0);
34517 }
34518 duk_push_int(ctx, match_start_coff);
34519 duk_dup(ctx, 2);
34520
34521 /* [ ... replacer match [captures] match_char_offset input ] */
34522
34523 duk_call(ctx, duk_get_top(ctx) - idx_args);
34524 h_repl = duk_to_hstring(ctx, -1); /* -> [ ... repl_value ] */
34525 DUK_ASSERT(h_repl != NULL);
34526
34527 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
34528
34529 duk_pop(ctx); /* repl_value */
34530 } else {
34531 r = r_start;
34532
34533 while (r < r_end) {
34534 duk_int_t ch1;
34535 duk_int_t ch2;
34536#ifdef DUK_USE_REGEXP_SUPPORT
34537 duk_int_t ch3;
34538#endif
34540
34541 ch1 = *r++;
34542 if (ch1 != DUK_ASC_DOLLAR) {
34543 goto repl_write;
34544 }
34545 left = r_end - r;
34546
34547 if (left <= 0) {
34548 goto repl_write;
34549 }
34550
34551 ch2 = r[0];
34552 switch ((int) ch2) {
34553 case DUK_ASC_DOLLAR: {
34554 ch1 = (1 << 8) + DUK_ASC_DOLLAR;
34555 goto repl_write;
34556 }
34557 case DUK_ASC_AMP: {
34558 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
34559 r++;
34560 continue;
34561 }
34562 case DUK_ASC_GRAVE: {
34563 tmp_sz = (duk_size_t) match_start_boff;
34564 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
34565 r++;
34566 continue;
34567 }
34568 case DUK_ASC_SINGLEQUOTE: {
34569 duk_uint32_t match_end_boff;
34570
34571 /* Use match charlen instead of bytelen, just in case the input and
34572 * match codepoint encodings would have different lengths.
34573 */
34574 match_end_boff = duk_heap_strcache_offset_char2byte(thr,
34575 h_input,
34576 match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match));
34577
34578 tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
34579 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
34580 r++;
34581 continue;
34582 }
34583 default: {
34584#ifdef DUK_USE_REGEXP_SUPPORT
34585 duk_int_t capnum, captmp, capadv;
34586 /* XXX: optional check, match_caps is zero if no regexp,
34587 * so dollar will be interpreted literally anyway.
34588 */
34589
34590 if (!is_regexp) {
34591 goto repl_write;
34592 }
34593
34594 if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
34595 goto repl_write;
34596 }
34597 capnum = ch2 - DUK_ASC_0;
34598 capadv = 1;
34599
34600 if (left >= 2) {
34601 ch3 = r[1];
34602 if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
34603 captmp = capnum * 10 + (ch3 - DUK_ASC_0);
34604 if (captmp < match_caps) {
34605 capnum = captmp;
34606 capadv = 2;
34607 }
34608 }
34609 }
34610
34611 if (capnum > 0 && capnum < match_caps) {
34612 DUK_ASSERT(is_regexp != 0); /* match_caps == 0 without regexps */
34613
34614 /* regexp res_obj is at offset 4 */
34615 duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum);
34616 if (duk_is_string(ctx, -1)) {
34617 duk_hstring *h_tmp_str;
34618
34619 h_tmp_str = duk_get_hstring(ctx, -1);
34620 DUK_ASSERT(h_tmp_str != NULL);
34621
34622 DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
34623 } else {
34624 /* undefined -> skip (replaced with empty) */
34625 }
34626 duk_pop(ctx);
34627 r += capadv;
34628 continue;
34629 } else {
34630 goto repl_write;
34631 }
34632#else /* DUK_USE_REGEXP_SUPPORT */
34633 goto repl_write; /* unconditionally */
34634#endif /* DUK_USE_REGEXP_SUPPORT */
34635 } /* default case */
34636 } /* switch (ch2) */
34637
34638 repl_write:
34639 /* ch1 = (r_increment << 8) + byte */
34640
34641 DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
34642 r += ch1 >> 8;
34643 } /* while repl */
34644 } /* if (is_repl_func) */
34645
34646 duk_pop(ctx); /* pop regexp res_obj or match string */
34647
34648#ifdef DUK_USE_REGEXP_SUPPORT
34649 if (!is_global) {
34650#else
34651 { /* unconditionally; is_global==0 */
34652#endif
34653 break;
34654 }
34655 }
34656
34657 /* trailer */
34658 tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
34659 DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
34660
34661 DUK_ASSERT_TOP(ctx, 4);
34662 DUK_BW_COMPACT(thr, bw);
34663 duk_to_string(ctx, -1);
34664 return 1;
34665}
34666
34667/*
34668 * split()
34669 */
34670
34671/* XXX: very messy now, but works; clean up, remove unused variables (nomimally
34672 * used so compiler doesn't complain).
34673 */
34674
34676 duk_hthread *thr = (duk_hthread *) ctx;
34677 duk_hstring *h_input;
34678 duk_hstring *h_sep;
34679 duk_uint32_t limit;
34680 duk_uint32_t arr_idx;
34681#ifdef DUK_USE_REGEXP_SUPPORT
34682 duk_bool_t is_regexp;
34683#endif
34684 duk_bool_t matched; /* set to 1 if any match exists (needed for empty input special case) */
34685 duk_uint32_t prev_match_end_coff, prev_match_end_boff;
34686 duk_uint32_t match_start_boff, match_start_coff;
34687 duk_uint32_t match_end_boff, match_end_coff;
34688
34689 DUK_UNREF(thr);
34690
34691 h_input = duk_push_this_coercible_to_string(ctx);
34692 DUK_ASSERT(h_input != NULL);
34693
34694 duk_push_array(ctx);
34695
34696 if (duk_is_undefined(ctx, 1)) {
34697 limit = 0xffffffffUL;
34698 } else {
34699 limit = duk_to_uint32(ctx, 1);
34700 }
34701
34702 if (limit == 0) {
34703 return 1;
34704 }
34705
34706 /* If the separator is a RegExp, make a "clone" of it. The specification
34707 * algorithm calls [[Match]] directly for specific indices; we emulate this
34708 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
34709 * which will use global-style matching even when the RegExp itself is non-global.
34710 */
34711
34712 if (duk_is_undefined(ctx, 0)) {
34713 /* The spec algorithm first does "R = ToString(separator)" before checking
34714 * whether separator is undefined. Since this is side effect free, we can
34715 * skip the ToString() here.
34716 */
34717 duk_dup(ctx, 2);
34718 duk_put_prop_index(ctx, 3, 0);
34719 return 1;
34721#ifdef DUK_USE_REGEXP_SUPPORT
34723 duk_dup(ctx, 0);
34724 duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */
34725 duk_replace(ctx, 0);
34726 /* lastIndex is initialized to zero by new RegExp() */
34727 is_regexp = 1;
34728#else
34730#endif
34731 } else {
34732 duk_to_string(ctx, 0);
34733#ifdef DUK_USE_REGEXP_SUPPORT
34734 is_regexp = 0;
34735#endif
34736 }
34737
34738 /* stack[0] = separator (string or regexp)
34739 * stack[1] = limit
34740 * stack[2] = input string
34741 * stack[3] = result array
34742 */
34743
34744 prev_match_end_boff = 0;
34745 prev_match_end_coff = 0;
34746 arr_idx = 0;
34747 matched = 0;
34748
34749 for (;;) {
34750 /*
34751 * The specification uses RegExp [[Match]] to attempt match at specific
34752 * offsets. We don't have such a primitive, so we use an actual RegExp
34753 * and tweak lastIndex. Since the RegExp may be non-global, we use a
34754 * special variant which forces global-like behavior for matching.
34755 */
34756
34757 DUK_ASSERT_TOP(ctx, 4);
34758
34759#ifdef DUK_USE_REGEXP_SUPPORT
34760 if (is_regexp) {
34761 duk_dup(ctx, 0);
34762 duk_dup(ctx, 2);
34763 duk_regexp_match_force_global(thr); /* [ ... regexp input ] -> [ res_obj ] */
34764 if (!duk_is_object(ctx, -1)) {
34765 duk_pop(ctx);
34766 break;
34767 }
34768 matched = 1;
34769
34771 DUK_ASSERT(duk_is_number(ctx, -1));
34772 match_start_coff = duk_get_int(ctx, -1);
34773 match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
34774 duk_pop(ctx);
34775
34776 if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
34777 /* don't allow an empty match at the end of the string */
34778 duk_pop(ctx);
34779 break;
34780 }
34781
34783 DUK_ASSERT(duk_is_number(ctx, -1));
34784 match_end_coff = duk_get_int(ctx, -1);
34785 match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
34786 duk_pop(ctx);
34787
34788 /* empty match -> bump and continue */
34789 if (prev_match_end_boff == match_end_boff) {
34790 duk_push_int(ctx, match_end_coff + 1);
34792 duk_pop(ctx);
34793 continue;
34794 }
34795 } else {
34796#else /* DUK_USE_REGEXP_SUPPORT */
34797 { /* unconditionally */
34798#endif /* DUK_USE_REGEXP_SUPPORT */
34799 const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
34800 const duk_uint8_t *q_start; /* match string */
34801 duk_size_t q_blen, q_clen;
34802
34803 p_start = DUK_HSTRING_GET_DATA(h_input);
34804 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
34805 p = p_start + prev_match_end_boff;
34806
34807 h_sep = duk_get_hstring(ctx, 0);
34808 DUK_ASSERT(h_sep != NULL);
34809 q_start = DUK_HSTRING_GET_DATA(h_sep);
34810 q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
34811 q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
34812
34813 p_end -= q_blen; /* ensure full memcmp() fits in while */
34814
34815 match_start_coff = prev_match_end_coff;
34816
34817 if (q_blen == 0) {
34818 /* Handle empty separator case: it will always match, and always
34819 * triggers the check in step 13.c.iii initially. Note that we
34820 * must skip to either end of string or start of first codepoint,
34821 * skipping over any continuation bytes!
34822 *
34823 * Don't allow an empty string to match at the end of the input.
34824 */
34825
34826 matched = 1; /* empty separator can always match */
34827
34828 match_start_coff++;
34829 p++;
34830 while (p < p_end) {
34831 if ((p[0] & 0xc0) != 0x80) {
34832 goto found;
34833 }
34834 p++;
34835 }
34836 goto not_found;
34837 }
34838
34839 DUK_ASSERT(q_blen > 0 && q_clen > 0);
34840 while (p <= p_end) {
34841 DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
34842 DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */
34843 if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34844 /* never an empty match, so step 13.c.iii can't be triggered */
34845 goto found;
34846 }
34847
34848 /* track utf-8 non-continuation bytes */
34849 if ((p[0] & 0xc0) != 0x80) {
34850 match_start_coff++;
34851 }
34852 p++;
34853 }
34854
34855 not_found:
34856 /* not found */
34857 break;
34858
34859 found:
34860 matched = 1;
34861 match_start_boff = (duk_uint32_t) (p - p_start);
34862 match_end_coff = (duk_uint32_t) (match_start_coff + q_clen); /* constrained by string length */
34863 match_end_boff = (duk_uint32_t) (match_start_boff + q_blen); /* ditto */
34864
34865 /* empty match (may happen with empty separator) -> bump and continue */
34866 if (prev_match_end_boff == match_end_boff) {
34867 prev_match_end_boff++;
34868 prev_match_end_coff++;
34869 continue;
34870 }
34871 } /* if (is_regexp) */
34872
34873 /* stack[0] = separator (string or regexp)
34874 * stack[1] = limit
34875 * stack[2] = input string
34876 * stack[3] = result array
34877 * stack[4] = regexp res_obj (if is_regexp)
34878 */
34879
34880 DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
34881 (long) match_start_boff, (long) match_start_coff,
34882 (long) match_end_boff, (long) match_end_coff,
34883 (long) prev_match_end_boff, (long) prev_match_end_coff));
34884
34885 duk_push_lstring(ctx,
34886 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
34887 (duk_size_t) (match_start_boff - prev_match_end_boff));
34888 duk_put_prop_index(ctx, 3, arr_idx);
34889 arr_idx++;
34890 if (arr_idx >= limit) {
34891 goto hit_limit;
34892 }
34893
34894#ifdef DUK_USE_REGEXP_SUPPORT
34895 if (is_regexp) {
34896 duk_size_t i, len;
34897
34898 len = duk_get_length(ctx, 4);
34899 for (i = 1; i < len; i++) {
34900 DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* cannot have >4G captures */
34901 duk_get_prop_index(ctx, 4, (duk_uarridx_t) i);
34902 duk_put_prop_index(ctx, 3, arr_idx);
34903 arr_idx++;
34904 if (arr_idx >= limit) {
34905 goto hit_limit;
34906 }
34907 }
34908
34909 duk_pop(ctx);
34910 /* lastIndex already set up for next match */
34911 } else {
34912#else /* DUK_USE_REGEXP_SUPPORT */
34913 { /* unconditionally */
34914#endif /* DUK_USE_REGEXP_SUPPORT */
34915 /* no action */
34916 }
34917
34918 prev_match_end_boff = match_end_boff;
34919 prev_match_end_coff = match_end_coff;
34920 continue;
34921 } /* for */
34922
34923 /* Combined step 11 (empty string special case) and 14-15. */
34924
34925 DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
34926 (long) prev_match_end_boff, (long) prev_match_end_coff));
34927
34928 if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) {
34929 /* Add trailer if:
34930 * a) non-empty input
34931 * b) empty input and no (zero size) match found (step 11)
34932 */
34933
34934 duk_push_lstring(ctx,
34935 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
34936 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
34937 duk_put_prop_index(ctx, 3, arr_idx);
34938 /* No arr_idx update or limit check */
34939 }
34940
34941 return 1;
34942
34943 hit_limit:
34944#ifdef DUK_USE_REGEXP_SUPPORT
34945 if (is_regexp) {
34946 duk_pop(ctx);
34947 }
34948#endif
34949
34950 return 1;
34951}
34952
34953/*
34954 * Various
34955 */
34956
34957#ifdef DUK_USE_REGEXP_SUPPORT
34959 duk_hobject *h;
34960
34961 /* Shared helper for match() steps 3-4, search() steps 3-4. */
34962
34963 DUK_ASSERT(index >= 0);
34964
34965 if (force_new) {
34966 goto do_new;
34968
34970 if (!h) {
34971 goto do_new;
34972 }
34973 return;
34974
34975 do_new:
34977 duk_dup(ctx, index);
34978 duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */
34979 duk_replace(ctx, index);
34980}
34981#endif /* DUK_USE_REGEXP_SUPPORT */
34982
34983#ifdef DUK_USE_REGEXP_SUPPORT
34985 duk_hthread *thr = (duk_hthread *) ctx;
34986
34987 /* Easiest way to implement the search required by the specification
34988 * is to do a RegExp test() with lastIndex forced to zero. To avoid
34989 * side effects on the argument, "clone" the RegExp if a RegExp was
34990 * given as input.
34991 *
34992 * The global flag of the RegExp should be ignored; setting lastIndex
34993 * to zero (which happens when "cloning" the RegExp) should have an
34994 * equivalent effect.
34995 */
34996
34997 DUK_ASSERT_TOP(ctx, 1);
34998 (void) duk_push_this_coercible_to_string(ctx); /* at index 1 */
34999 duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/);
35000
35001 /* stack[0] = regexp
35002 * stack[1] = string
35003 */
35004
35005 /* Avoid using RegExp.prototype methods, as they're writable and
35006 * configurable and may have been changed.
35007 */
35008
35009 duk_dup(ctx, 0);
35010 duk_dup(ctx, 1); /* [ ... re_obj input ] */
35011 duk_regexp_match(thr); /* -> [ ... res_obj ] */
35012
35013 if (!duk_is_object(ctx, -1)) {
35014 duk_push_int(ctx, -1);
35015 return 1;
35016 }
35017
35019 DUK_ASSERT(duk_is_number(ctx, -1));
35020 return 1;
35021}
35022#else /* DUK_USE_REGEXP_SUPPORT */
35024 DUK_UNREF(ctx);
35026}
35027#endif /* DUK_USE_REGEXP_SUPPORT */
35028
35029#ifdef DUK_USE_REGEXP_SUPPORT
35031 duk_hthread *thr = (duk_hthread *) ctx;
35032 duk_bool_t global;
35033 duk_int_t prev_last_index;
35034 duk_int_t this_index;
35035 duk_int_t arr_idx;
35036
35037 DUK_ASSERT_TOP(ctx, 1);
35039 duk__to_regexp_helper(ctx, 0 /*index*/, 0 /*force_new*/);
35041 DUK_ASSERT_TOP(ctx, 2);
35042
35043 /* stack[0] = regexp
35044 * stack[1] = string
35045 */
35046
35047 if (!global) {
35048 duk_regexp_match(thr); /* -> [ res_obj ] */
35049 return 1; /* return 'res_obj' */
35050 }
35051
35052 /* Global case is more complex. */
35053
35054 /* [ regexp string ] */
35055
35056 duk_push_int(ctx, 0);
35058 duk_push_array(ctx);
35059
35060 /* [ regexp string res_arr ] */
35061
35062 prev_last_index = 0;
35063 arr_idx = 0;
35064
35065 for (;;) {
35066 DUK_ASSERT_TOP(ctx, 3);
35067
35068 duk_dup(ctx, 0);
35069 duk_dup(ctx, 1);
35070 duk_regexp_match(thr); /* -> [ ... regexp string ] -> [ ... res_obj ] */
35071
35072 if (!duk_is_object(ctx, -1)) {
35073 duk_pop(ctx);
35074 break;
35075 }
35076
35078 DUK_ASSERT(duk_is_number(ctx, -1));
35079 this_index = duk_get_int(ctx, -1);
35080 duk_pop(ctx);
35081
35082 if (this_index == prev_last_index) {
35083 this_index++;
35084 duk_push_int(ctx, this_index);
35086 }
35087 prev_last_index = this_index;
35088
35089 duk_get_prop_index(ctx, -1, 0); /* match string */
35090 duk_put_prop_index(ctx, 2, arr_idx);
35091 arr_idx++;
35092 duk_pop(ctx); /* res_obj */
35093 }
35094
35095 if (arr_idx == 0) {
35096 duk_push_null(ctx);
35097 }
35098
35099 return 1; /* return 'res_arr' or 'null' */
35100}
35101#else /* DUK_USE_REGEXP_SUPPORT */
35103 DUK_UNREF(ctx);
35105}
35106#endif /* DUK_USE_REGEXP_SUPPORT */
35109 /* duk_concat() coerces arguments with ToString() in correct order */
35111 duk_insert(ctx, 0); /* this is relatively expensive */
35112 duk_concat(ctx, duk_get_top(ctx));
35113 return 1;
35114}
35115
35117 DUK_ASSERT_TOP(ctx, 0);
35119 duk_trim(ctx, 0);
35120 DUK_ASSERT_TOP(ctx, 1);
35121 return 1;
35122}
35123
35125 duk_hstring *h1;
35126 duk_hstring *h2;
35127 duk_size_t h1_len, h2_len, prefix_len;
35128 duk_small_int_t ret = 0;
35129 duk_small_int_t rc;
35130
35131 /* The current implementation of localeCompare() is simply a codepoint
35132 * by codepoint comparison, implemented with a simple string compare
35133 * because UTF-8 should preserve codepoint ordering (assuming valid
35134 * shortest UTF-8 encoding).
35135 *
35136 * The specification requires that the return value must be related
35137 * to the sort order: e.g. negative means that 'this' comes before
35138 * 'that' in sort order. We assume an ascending sort order.
35139 */
35140
35141 /* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
35142
35144 DUK_ASSERT(h1 != NULL);
35145
35146 h2 = duk_to_hstring(ctx, 0);
35147 DUK_ASSERT(h2 != NULL);
35148
35149 h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
35150 h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
35151 prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
35152
35153 /* Zero size compare not an issue with DUK_MEMCMP. */
35154 rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),
35155 (const void *) DUK_HSTRING_GET_DATA(h2),
35156 (size_t) prefix_len);
35157
35158 if (rc < 0) {
35159 ret = -1;
35160 goto done;
35161 } else if (rc > 0) {
35162 ret = 1;
35163 goto done;
35164 }
35165
35166 /* prefix matches, lengths matter now */
35167 if (h1_len > h2_len) {
35168 ret = 1;
35169 goto done;
35170 } else if (h1_len == h2_len) {
35171 DUK_ASSERT(ret == 0);
35172 goto done;
35173 }
35174 ret = -1;
35175 goto done;
35176
35177 done:
35178 duk_push_int(ctx, (duk_int_t) ret);
35179 return 1;
35180}
35181#line 1 "duk_bi_thread.c"
35182/*
35183 * Thread builtins
35184 */
35185
35186/* include removed: duk_internal.h */
35187
35188/*
35189 * Constructor
35190 */
35191
35193 duk_hthread *new_thr;
35194 duk_hobject *func;
35195
35196 /* XXX: need a duk_require_func_or_lfunc_coerce() */
35197 if (!duk_is_callable(ctx, 0)) {
35198 return DUK_RET_TYPE_ERROR;
35199 }
35201 DUK_ASSERT(func != NULL);
35202
35203 duk_push_thread(ctx);
35204 new_thr = (duk_hthread *) duk_get_hobject(ctx, -1);
35205 DUK_ASSERT(new_thr != NULL);
35207
35208 /* push initial function call to new thread stack; this is
35209 * picked up by resume().
35210 */
35211 duk_push_hobject((duk_context *) new_thr, func);
35212
35213 return 1; /* return thread */
35215
35216/*
35217 * Resume a thread.
35218 *
35219 * The thread must be in resumable state, either (a) new thread which hasn't
35220 * yet started, or (b) a thread which has previously yielded. This method
35221 * must be called from an Ecmascript function.
35222 *
35223 * Args:
35224 * - thread
35225 * - value
35226 * - isError (defaults to false)
35227 *
35228 * Note: yield and resume handling is currently asymmetric.
35229 */
35230
35232 duk_hthread *thr = (duk_hthread *) ctx;
35233 duk_hthread *thr_resume;
35234 duk_tval *tv;
35235 duk_hobject *func;
35236 duk_hobject *caller_func;
35237 duk_small_int_t is_error;
35238
35239 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
35240 (duk_tval *) duk_get_tval(ctx, 0),
35241 (duk_tval *) duk_get_tval(ctx, 1),
35242 (duk_tval *) duk_get_tval(ctx, 2)));
35243
35245 DUK_ASSERT(thr->heap->curr_thread == thr);
35246
35247 thr_resume = duk_require_hthread(ctx, 0);
35248 is_error = (duk_small_int_t) duk_to_boolean(ctx, 2);
35249 duk_set_top(ctx, 2);
35250
35251 /* [ thread value ] */
35252
35253 /*
35254 * Thread state and calling context checks
35255 */
35256
35257 if (thr->callstack_top < 2) {
35258 DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
35259 goto state_error;
35260 }
35261 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
35263 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
35264
35265 caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
35266 if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
35267 DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
35268 goto state_error;
35269 }
35270
35271 /* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
35272 * like for yield.
35273 */
35274
35275 if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
35276 thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
35277 DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
35278 goto state_error;
35279 }
35280
35282 thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
35283
35284 /* Further state-dependent pre-checks */
35285
35286 if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
35287 /* no pre-checks now, assume a previous yield() has left things in
35288 * tip-top shape (longjmp handler will assert for these).
35289 */
35290 } else {
35292
35293 if ((thr_resume->callstack_top != 0) ||
35294 (thr_resume->valstack_top - thr_resume->valstack != 1)) {
35295 goto state_invalid_initial;
35296 }
35297 tv = &thr_resume->valstack_top[-1];
35298 DUK_ASSERT(tv >= thr_resume->valstack && tv < thr_resume->valstack_top);
35299 if (!DUK_TVAL_IS_OBJECT(tv)) {
35300 goto state_invalid_initial;
35301 }
35302 func = DUK_TVAL_GET_OBJECT(tv);
35303 DUK_ASSERT(func != NULL);
35305 /* Note: cannot be a bound function either right now,
35306 * this would be easy to relax though.
35307 */
35308 goto state_invalid_initial;
35309 }
35310
35311 }
35312
35313 /*
35314 * The error object has been augmented with a traceback and other
35315 * info from its creation point -- usually another thread. The
35316 * error handler is called here right before throwing, but it also
35317 * runs in the resumer's thread. It might be nice to get a traceback
35318 * from the resumee but this is not the case now.
35319 */
35320
35321#if defined(DUK_USE_AUGMENT_ERROR_THROW)
35322 if (is_error) {
35323 DUK_ASSERT_TOP(ctx, 2); /* value (error) is at stack top */
35324 duk_err_augment_error_throw(thr); /* in resumer's context */
35325 }
35326#endif
35327
35328#ifdef DUK_USE_DEBUG
35329 if (is_error) {
35330 DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
35331 (duk_tval *) duk_get_tval(ctx, 0),
35332 (duk_tval *) duk_get_tval(ctx, 1)));
35333 } else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
35334 DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
35335 (duk_tval *) duk_get_tval(ctx, 0),
35336 (duk_tval *) duk_get_tval(ctx, 1)));
35337 } else {
35338 DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
35339 (duk_tval *) duk_get_tval(ctx, 0),
35340 (duk_tval *) duk_get_tval(ctx, 1)));
35341 }
35342#endif
35343
35345
35346 /* lj value2: thread */
35348 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]); /* side effects */
35349
35350 /* lj value1: value */
35351 DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
35352 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
35354
35355 thr->heap->lj.iserror = is_error;
35356
35357 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
35358 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
35359 return 0; /* never here */
35360
35361 state_invalid_initial:
35362 DUK_ERROR_TYPE(thr, "invalid initial thread state/stack");
35363 return 0; /* never here */
35364
35365 state_error:
35366 DUK_ERROR_TYPE(thr, "invalid state");
35367 return 0; /* never here */
35369
35370/*
35371 * Yield the current thread.
35372 *
35373 * The thread must be in yieldable state: it must have a resumer, and there
35374 * must not be any yield-preventing calls (native calls and constructor calls,
35375 * currently) in the thread's call stack (otherwise a resume would not be
35376 * possible later). This method must be called from an Ecmascript function.
35377 *
35378 * Args:
35379 * - value
35380 * - isError (defaults to false)
35381 *
35382 * Note: yield and resume handling is currently asymmetric.
35383 */
35384
35386 duk_hthread *thr = (duk_hthread *) ctx;
35387 duk_hobject *caller_func;
35388 duk_small_int_t is_error;
35389
35390 DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
35391 (duk_tval *) duk_get_tval(ctx, 0),
35392 (duk_tval *) duk_get_tval(ctx, 1)));
35393
35395 DUK_ASSERT(thr->heap->curr_thread == thr);
35396
35397 is_error = (duk_small_int_t) duk_to_boolean(ctx, 1);
35398 duk_set_top(ctx, 1);
35399
35400 /* [ value ] */
35401
35402 /*
35403 * Thread state and calling context checks
35404 */
35405
35406 if (!thr->resumer) {
35407 DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
35408 goto state_error;
35409 }
35411
35412 if (thr->callstack_top < 2) {
35413 DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
35414 goto state_error;
35415 }
35416 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
35418 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
35419
35420 caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
35421 if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
35422 DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
35423 goto state_error;
35424 }
35425
35426 DUK_ASSERT(thr->callstack_preventcount >= 1); /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
35427 if (thr->callstack_preventcount != 1) {
35428 /* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
35429 DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
35430 (long) thr->callstack_preventcount));
35431 goto state_error;
35432 }
35433
35434 /*
35435 * The error object has been augmented with a traceback and other
35436 * info from its creation point -- usually the current thread.
35437 * The error handler, however, is called right before throwing
35438 * and runs in the yielder's thread.
35439 */
35440
35441#if defined(DUK_USE_AUGMENT_ERROR_THROW)
35442 if (is_error) {
35443 DUK_ASSERT_TOP(ctx, 1); /* value (error) is at stack top */
35444 duk_err_augment_error_throw(thr); /* in yielder's context */
35445 }
35446#endif
35447
35448#ifdef DUK_USE_DEBUG
35449 if (is_error) {
35450 DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
35451 (duk_tval *) duk_get_tval(ctx, 0)));
35452 } else {
35453 DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
35454 (duk_tval *) duk_get_tval(ctx, 0)));
35455 }
35456#endif
35457
35458 /*
35459 * Process yield
35460 *
35461 * After longjmp(), processing continues in bytecode executor longjmp
35462 * handler, which will e.g. update thr->resumer to NULL.
35463 */
35464
35465 thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
35467 /* lj value1: value */
35469 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
35471
35472 thr->heap->lj.iserror = is_error;
35473
35474 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
35475 duk_err_longjmp(thr); /* execution resumes in bytecode executor */
35476 return 0; /* never here */
35478 state_error:
35479 DUK_ERROR_TYPE(thr, "invalid state");
35480 return 0; /* never here */
35481}
35482
35485 return 1;
35486}
35487#line 1 "duk_bi_thrower.c"
35488/*
35489 * Type error thrower, E5 Section 13.2.3.
35490 */
35491
35492/* include removed: duk_internal.h */
35493
35495 DUK_UNREF(ctx);
35496 return DUK_RET_TYPE_ERROR;
35497}
35498#line 1 "duk_debug_fixedbuffer.c"
35499/*
35500 * Fixed buffer helper useful for debugging, requires no allocation
35501 * which is critical for debugging.
35502 */
35503
35504/* include removed: duk_internal.h */
35505
35506#ifdef DUK_USE_DEBUG
35507
35508DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
35509 duk_size_t avail;
35510 duk_size_t copylen;
35511
35512 avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
35513 if (length > avail) {
35514 copylen = avail;
35515 fb->truncated = 1;
35516 } else {
35517 copylen = length;
35518 }
35519 DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);
35520 fb->offset += copylen;
35521}
35522
35523DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
35524 duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
35525}
35526
35527DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
35528 duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
35529}
35530
35531DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
35532 duk_size_t avail;
35533 va_list ap;
35534
35535 va_start(ap, fmt);
35536 avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
35537 if (avail > 0) {
35538 duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
35539 if (res < 0) {
35540 /* error */
35541 } else if ((duk_size_t) res >= avail) {
35542 /* (maybe) truncated */
35543 fb->offset += avail;
35544 if ((duk_size_t) res > avail) {
35545 /* actual chars dropped (not just NUL term) */
35546 fb->truncated = 1;
35547 }
35548 } else {
35549 /* normal */
35550 fb->offset += res;
35551 }
35552 }
35553 va_end(ap);
35554}
35555
35556DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
35557 char buf[64+1];
35558 duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
35559 buf[sizeof(buf) - 1] = (char) 0;
35560 duk_fb_put_cstring(fb, buf);
35561}
35562
35563DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
35564 return (fb->offset >= fb->length);
35565}
35566
35567#endif /* DUK_USE_DEBUG */
35568#line 1 "duk_debug_heap.c"
35569/*
35570 * Debug dumping of duk_heap.
35571 */
35572
35573/* include removed: duk_internal.h */
35574
35575#ifdef DUK_USE_DEBUG
35576
35577#if 0 /*unused*/
35578DUK_LOCAL void duk__sanitize_snippet(char *buf, duk_size_t buf_size, duk_hstring *str) {
35579 duk_size_t i;
35580 duk_size_t nchars;
35581 duk_size_t maxchars;
35582 duk_uint8_t *data;
35583
35584 DUK_MEMZERO(buf, buf_size);
35585
35586 maxchars = (duk_size_t) (buf_size - 1);
35587 data = DUK_HSTRING_GET_DATA(str);
35588 nchars = ((duk_size_t) str->blen < maxchars ? (duk_size_t) str->blen : maxchars);
35589 for (i = 0; i < nchars; i++) {
35590 duk_small_int_t c = (duk_small_int_t) data[i];
35591 if (c < 0x20 || c > 0x7e) {
35592 c = '.';
35593 }
35594 buf[i] = (char) c;
35595 }
35596}
35597#endif
35598
35599#if 0
35600DUK_LOCAL const char *duk__get_heap_type_string(duk_heaphdr *hdr) {
35601 switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
35602 case DUK_HTYPE_STRING:
35603 return "string";
35604 case DUK_HTYPE_OBJECT:
35605 return "object";
35606 case DUK_HTYPE_BUFFER:
35607 return "buffer";
35608 default:
35609 return "???";
35610 }
35611}
35612#endif
35613
35614#if 0
35615DUK_LOCAL void duk__dump_indented(duk_heaphdr *obj, int index) {
35616 DUK_UNREF(obj);
35618 DUK_UNREF(duk__get_heap_type_string);
35619
35620#ifdef DUK_USE_REFERENCE_COUNTING
35621 DUK_D(DUK_DPRINT(" [%ld]: %p %s (flags: 0x%08lx, ref: %ld) -> %!O",
35622 (long) index,
35623 (void *) obj,
35624 (const char *) duk__get_heap_type_string(obj),
35625 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
35626 (long) DUK_HEAPHDR_GET_REFCOUNT(obj),
35627 (duk_heaphdr *) obj));
35628#else
35629 DUK_D(DUK_DPRINT(" [%ld]: %p %s (flags: 0x%08lx) -> %!O",
35630 (long) index,
35631 (void *) obj,
35632 (const char *) duk__get_heap_type_string(obj),
35633 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
35634 (duk_heaphdr *) obj));
35635#endif
35636}
35637#endif
35638
35639#if 0 /*unused*/
35640DUK_LOCAL void duk__dump_heaphdr_list(duk_heap *heap, duk_heaphdr *root, const char *name) {
35641 duk_int_t count;
35642 duk_heaphdr *curr;
35643
35644 DUK_UNREF(heap);
35645 DUK_UNREF(name);
35646
35647 count = 0;
35648 curr = root;
35649 while (curr) {
35650 count++;
35651 curr = DUK_HEAPHDR_GET_NEXT(curr);
35652 }
35653
35654 DUK_D(DUK_DPRINT("%s, %ld objects", (const char *) name, (long) count));
35655
35656 count = 0;
35657 curr = root;
35658 while (curr) {
35659 count++;
35660 duk__dump_indented(curr, count);
35661 curr = DUK_HEAPHDR_GET_NEXT(curr);
35662 }
35663}
35664#endif
35665
35666#if 0 /*unused*/
35667DUK_LOCAL void duk__dump_stringtable(duk_heap *heap) {
35669 char buf[64+1];
35670
35671 DUK_D(DUK_DPRINT("stringtable %p, used %ld, size %ld, load %ld%%",
35672 (void *) heap->strtable,
35673 (long) heap->st_used,
35674 (long) heap->st_size,
35675 (long) (((double) heap->st_used) / ((double) heap->st_size) * 100.0)));
35676
35677 for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
35678 duk_hstring *e = heap->strtable[i];
35679
35680 if (!e) {
35681 DUK_D(DUK_DPRINT(" [%ld]: NULL", (long) i));
35682 } else if (e == DUK_STRTAB_DELETED_MARKER(heap)) {
35683 DUK_D(DUK_DPRINT(" [%ld]: DELETED", (long) i));
35684 } else {
35685 duk__sanitize_snippet(buf, sizeof(buf), e);
35686
35687#ifdef DUK_USE_REFERENCE_COUNTING
35688 DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx, ref: %ld) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
35689 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
35690 (long) i,
35691 (void *) e,
35692 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
35694 (const char *) buf,
35695 (unsigned long) e->hash,
35696 (long) e->blen,
35697 (long) e->clen,
35698 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
35699 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
35700 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
35701 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
35702 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
35703#else
35704 DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
35705 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
35706 (long) i,
35707 (void *) e,
35708 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
35709 (const char *) buf,
35710 (long) e->hash,
35711 (long) e->blen,
35712 (long) e->clen,
35713 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
35714 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
35715 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
35716 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
35717 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
35718#endif
35719 }
35720 }
35721}
35722#endif
35723
35724#if 0 /*unused*/
35725DUK_LOCAL void duk__dump_strcache(duk_heap *heap) {
35727 char buf[64+1];
35728
35729 DUK_D(DUK_DPRINT("stringcache"));
35730
35731 for (i = 0; i < (duk_uint_fast32_t) DUK_HEAP_STRCACHE_SIZE; i++) {
35732 duk_strcache *c = &heap->strcache[i];
35733 if (!c->h) {
35734 DUK_D(DUK_DPRINT(" [%ld]: bidx=%ld, cidx=%ld, str=NULL",
35735 (long) i, (long) c->bidx, (long) c->cidx));
35736 } else {
35737 duk__sanitize_snippet(buf, sizeof(buf), c->h);
35738 DUK_D(DUK_DPRINT(" [%ld]: bidx=%ld cidx=%ld str=%s",
35739 (long) i, (long) c->bidx, (long) c->cidx, (const char *) buf));
35740 }
35741 }
35742}
35743#endif
35744
35745#if 0 /*unused*/
35746DUK_INTERNAL void duk_debug_dump_heap(duk_heap *heap) {
35747 char buf[64+1];
35748
35749 DUK_D(DUK_DPRINT("=== heap %p ===", (void *) heap));
35750 DUK_D(DUK_DPRINT(" flags: 0x%08lx", (unsigned long) heap->flags));
35751
35752 /* Note: there is no standard formatter for function pointers */
35753#ifdef DUK_USE_GCC_PRAGMAS
35754#pragma GCC diagnostic push
35755#pragma GCC diagnostic ignored "-pedantic"
35756#endif
35757 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->alloc_func, sizeof(heap->alloc_func));
35758 DUK_D(DUK_DPRINT(" alloc_func: %s", (const char *) buf));
35759 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->realloc_func, sizeof(heap->realloc_func));
35760 DUK_D(DUK_DPRINT(" realloc_func: %s", (const char *) buf));
35761 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->free_func, sizeof(heap->free_func));
35762 DUK_D(DUK_DPRINT(" free_func: %s", (const char *) buf));
35763 duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->fatal_func, sizeof(heap->fatal_func));
35764 DUK_D(DUK_DPRINT(" fatal_func: %s", (const char *) buf));
35765#ifdef DUK_USE_GCC_PRAGMAS
35766#pragma GCC diagnostic pop
35767#endif
35768
35769 DUK_D(DUK_DPRINT(" heap_udata: %p", (void *) heap->heap_udata));
35770
35771#ifdef DUK_USE_MARK_AND_SWEEP
35772#ifdef DUK_USE_VOLUNTARY_GC
35773 DUK_D(DUK_DPRINT(" mark-and-sweep trig counter: %ld", (long) heap->mark_and_sweep_trigger_counter));
35774#endif
35775 DUK_D(DUK_DPRINT(" mark-and-sweep rec depth: %ld", (long) heap->mark_and_sweep_recursion_depth));
35776 DUK_D(DUK_DPRINT(" mark-and-sweep base flags: 0x%08lx", (unsigned long) heap->mark_and_sweep_base_flags));
35777#endif
35778
35779 DUK_D(DUK_DPRINT(" lj.jmpbuf_ptr: %p", (void *) heap->lj.jmpbuf_ptr));
35780 DUK_D(DUK_DPRINT(" lj.type: %ld", (long) heap->lj.type));
35781 DUK_D(DUK_DPRINT(" lj.value1: %!T", (duk_tval *) &heap->lj.value1));
35782 DUK_D(DUK_DPRINT(" lj.value2: %!T", (duk_tval *) &heap->lj.value2));
35783 DUK_D(DUK_DPRINT(" lj.iserror: %ld", (long) heap->lj.iserror));
35784
35785 DUK_D(DUK_DPRINT(" handling_error: %ld", (long) heap->handling_error));
35786
35787 DUK_D(DUK_DPRINT(" heap_thread: %!@O", (duk_heaphdr *) heap->heap_thread));
35788 DUK_D(DUK_DPRINT(" curr_thread: %!@O", (duk_heaphdr *) heap->curr_thread));
35789 DUK_D(DUK_DPRINT(" heap_object: %!@O", (duk_heaphdr *) heap->heap_object));
35790
35791 DUK_D(DUK_DPRINT(" call_recursion_depth: %ld", (long) heap->call_recursion_depth));
35792 DUK_D(DUK_DPRINT(" call_recursion_limit: %ld", (long) heap->call_recursion_limit));
35793
35794 DUK_D(DUK_DPRINT(" hash_seed: 0x%08lx", (unsigned long) heap->hash_seed));
35795 DUK_D(DUK_DPRINT(" rnd_state: 0x%08lx", (unsigned long) heap->rnd_state));
35796
35797 duk__dump_strcache(heap);
35798
35799 duk__dump_heaphdr_list(heap, heap->heap_allocated, "heap allocated");
35800
35801#ifdef DUK_USE_REFERENCE_COUNTING
35802 duk__dump_heaphdr_list(heap, heap->refzero_list, "refcounting refzero list");
35803#endif
35804
35805#ifdef DUK_USE_MARK_AND_SWEEP
35806 duk__dump_heaphdr_list(heap, heap->finalize_list, "mark-and-sweep finalize list");
35807#endif
35808
35809 duk__dump_stringtable(heap);
35810
35811 /* heap->strs: not worth dumping */
35812}
35813#endif
35814
35815#endif /* DUK_USE_DEBUG */
35816#line 1 "duk_debug_vsnprintf.c"
35817/*
35818 * Custom formatter for debug printing, allowing Duktape specific data
35819 * structures (such as tagged values and heap objects) to be printed with
35820 * a nice format string. Because debug printing should not affect execution
35821 * state, formatting here must be independent of execution (see implications
35822 * below) and must not allocate memory.
35823 *
35824 * Custom format tags begin with a '%!' to safely distinguish them from
35825 * standard format tags. The following conversions are supported:
35826 *
35827 * %!T tagged value (duk_tval *)
35828 * %!O heap object (duk_heaphdr *)
35829 * %!I decoded bytecode instruction
35830 * %!C bytecode instruction opcode name (arg is long)
35831 *
35832 * Everything is serialized in a JSON-like manner. The default depth is one
35833 * level, internal prototype is not followed, and internal properties are not
35834 * serialized. The following modifiers change this behavior:
35835 *
35836 * @ print pointers
35837 * # print binary representations (where applicable)
35838 * d deep traversal of own properties (not prototype)
35839 * p follow prototype chain (useless without 'd')
35840 * i include internal properties (other than prototype)
35841 * x hexdump buffers
35842 * h heavy formatting
35843 *
35844 * For instance, the following serializes objects recursively, but does not
35845 * follow the prototype chain nor print internal properties: "%!dO".
35846 *
35847 * Notes:
35848 *
35849 * * Standard snprintf return value semantics seem to vary. This
35850 * implementation returns the number of bytes it actually wrote
35851 * (excluding the null terminator). If retval == buffer size,
35852 * output was truncated (except for corner cases).
35853 *
35854 * * Output format is intentionally different from Ecmascript
35855 * formatting requirements, as formatting here serves debugging
35856 * of internals.
35857 *
35858 * * Depth checking (and updating) is done in each type printer
35859 * separately, to allow them to call each other freely.
35860 *
35861 * * Some pathological structures might take ages to print (e.g.
35862 * self recursion with 100 properties pointing to the object
35863 * itself). To guard against these, each printer also checks
35864 * whether the output buffer is full; if so, early exit.
35865 *
35866 * * Reference loops are detected using a loop stack.
35867 */
35868
35869/* include removed: duk_internal.h */
35870
35871#ifdef DUK_USE_DEBUG
35872
35873#include <stdio.h>
35874#include <stdarg.h>
35875#include <string.h>
35876
35877/* list of conversion specifiers that terminate a format tag;
35878 * this is unfortunately guesswork.
35879 */
35880#define DUK__ALLOWED_STANDARD_SPECIFIERS "diouxXeEfFgGaAcsCSpnm"
35881
35882/* maximum length of standard format tag that we support */
35883#define DUK__MAX_FORMAT_TAG_LENGTH 32
35884
35885/* heapobj recursion depth when deep printing is selected */
35886#define DUK__DEEP_DEPTH_LIMIT 8
35887
35888/* maximum recursion depth for loop detection stacks */
35889#define DUK__LOOP_STACK_DEPTH 256
35890
35891/* must match bytecode defines now; build autogenerate? */
35892DUK_LOCAL const char *duk__bc_optab[64] = {
35893 "LDREG", "STREG", "LDCONST", "LDINT", "LDINTX", "MPUTOBJ", "MPUTOBJI", "MPUTARR", "MPUTARRI", "NEW",
35894 "NEWI", "REGEXP", "CSREG", "CSREGI", "GETVAR", "PUTVAR", "DECLVAR", "DELVAR", "CSVAR", "CSVARI",
35895 "CLOSURE", "GETPROP", "PUTPROP", "DELPROP", "CSPROP", "CSPROPI", "ADD", "SUB", "MUL", "DIV",
35896 "MOD", "BAND", "BOR", "BXOR", "BASL", "BLSR", "BASR", "EQ", "NEQ", "SEQ",
35897 "SNEQ", "GT", "GE", "LT", "LE", "IF", "JUMP", "RETURN", "CALL", "CALLI",
35898 "TRYCATCH", "EXTRA", "PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
35899 "PREINCP", "PREDECP", "POSTINCP", "POSTDECP"
35900};
35901
35902DUK_LOCAL const char *duk__bc_extraoptab[256] = {
35903 "NOP", "INVALID", "LDTHIS", "LDUNDEF", "LDNULL", "LDTRUE", "LDFALSE", "NEWOBJ", "NEWARR", "SETALEN",
35904 "TYPEOF", "TYPEOFID", "INITENUM", "NEXTENUM", "INITSET", "INITSETI", "INITGET", "INITGETI", "ENDTRY", "ENDCATCH",
35905 "ENDFIN", "THROW", "INVLHS", "UNM", "UNP", "DEBUGGER", "BREAK", "CONTINUE", "BNOT", "LNOT",
35906 "INSTOF", "IN", "LABEL", "ENDLABEL", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35907 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35908
35909 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35910 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35911 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35912 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35913 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35914
35915 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35916 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35917 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35918 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35919 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35920
35921 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35922 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35923 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35924 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35925 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35926
35927 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35928 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35929 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35930 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35931 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
35932
35933 "XXX", "XXX", "XXX", "XXX", "XXX", "XXX"
35934};
35935
35936typedef struct duk__dprint_state duk__dprint_state;
35937struct duk__dprint_state {
35938 duk_fixedbuffer *fb;
35939
35940 /* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
35941 * to not couple these two mechanisms unnecessarily.
35942 */
35943 duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
35944 duk_int_t loop_stack_index;
35945 duk_int_t loop_stack_limit;
35946
35948 duk_int_t depth_limit;
35949
35950 duk_bool_t pointer;
35951 duk_bool_t heavy;
35952 duk_bool_t binary;
35953 duk_bool_t follow_proto;
35954 duk_bool_t internal;
35955 duk_bool_t hexdump;
35956};
35957
35958/* helpers */
35959DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
35960DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
35961DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
35962DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
35963DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
35964DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
35965DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
35966DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
35967
35968DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
35969 duk_fixedbuffer *fb = st->fb;
35970
35971 if (st->heavy) {
35972 duk_fb_sprintf(fb, "(%p)", (void *) h);
35973 }
35974
35975 if (!h) {
35976 return;
35977 }
35978
35979 if (st->binary) {
35980 duk_size_t i;
35981 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
35982 for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
35983 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
35984 }
35985 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
35986 }
35987
35988#ifdef DUK_USE_REFERENCE_COUNTING /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
35989 if (st->heavy) {
35990 duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
35991 "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
35992 (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
35993 (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
35994 (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
35995 (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
35996 (long) DUK_HEAPHDR_GET_TYPE(h),
35997 (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
35998 (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
35999 (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
36000 (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
36001 }
36002#else
36003 if (st->heavy) {
36004 duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
36005 (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
36006 (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
36007 (long) DUK_HEAPHDR_GET_TYPE(h),
36008 (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
36009 (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
36010 (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
36011 (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
36012 }
36013#endif
36014}
36015
36016DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
36017 duk_fixedbuffer *fb = st->fb;
36018
36019 if (st->heavy) {
36020 duk_fb_sprintf(fb, "(%p)", (void *) h);
36021 }
36022
36023 if (!h) {
36024 return;
36025 }
36026
36027 if (st->binary) {
36028 duk_size_t i;
36029 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
36030 for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
36031 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
36032 }
36033 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
36034 }
36035
36036#ifdef DUK_USE_REFERENCE_COUNTING
36037 if (st->heavy) {
36038 duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
36039 (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
36040 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
36041 (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
36042 (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
36043 (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
36044 (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
36045 (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
36046 }
36047#else
36048 if (st->heavy) {
36049 duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
36050 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
36051 (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
36052 (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
36053 (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
36054 (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
36055 (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
36056 }
36057#endif
36058}
36059
36060DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
36061 duk_fixedbuffer *fb = st->fb;
36062 const duk_uint8_t *p;
36063 const duk_uint8_t *p_end;
36064
36065 /* terminal type: no depth check */
36066
36067 if (duk_fb_is_full(fb)) {
36068 return;
36069 }
36070
36071 duk__print_shared_heaphdr_string(st, &h->hdr);
36072
36073 if (!h) {
36074 duk_fb_put_cstring(fb, "NULL");
36075 return;
36076 }
36077
36078 p = DUK_HSTRING_GET_DATA(h);
36079 p_end = p + DUK_HSTRING_GET_BYTELEN(h);
36080
36081 if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
36082 /* if property key begins with underscore, encode it with
36083 * forced quotes (e.g. "_Foo") to distinguish it from encoded
36084 * internal properties (e.g. \xffBar -> _Bar).
36085 */
36086 quotes = 1;
36087 }
36088
36089 if (quotes) {
36090 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
36091 }
36092 while (p < p_end) {
36093 duk_uint8_t ch = *p++;
36094
36095 /* two special escapes: '\' and '"', other printables as is */
36096 if (ch == '\\') {
36097 duk_fb_sprintf(fb, "\\\\");
36098 } else if (ch == '"') {
36099 duk_fb_sprintf(fb, "\\\"");
36100 } else if (ch >= 0x20 && ch <= 0x7e) {
36101 duk_fb_put_byte(fb, ch);
36102 } else if (ch == 0xff && !quotes) {
36103 /* encode \xffBar as _Bar if no quotes are applied, this is for
36104 * readable internal keys.
36105 */
36106 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
36107 } else {
36108 duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
36109 }
36110 }
36111 if (quotes) {
36112 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
36113 }
36114#ifdef DUK_USE_REFERENCE_COUNTING
36115 /* XXX: limit to quoted strings only, to save keys from being cluttered? */
36116 duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
36117#endif
36118}
36119
36120#ifdef DUK__COMMA
36121#undef DUK__COMMA
36122#endif
36123#define DUK__COMMA() do { \
36124 if (first) { \
36125 first = 0; \
36126 } else { \
36127 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
36128 } \
36129 } while (0)
36130
36131DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
36132 duk_fixedbuffer *fb = st->fb;
36134 duk_tval *tv;
36135 duk_hstring *key;
36136 duk_bool_t first = 1;
36137 const char *brace1 = "{";
36138 const char *brace2 = "}";
36139 duk_bool_t pushed_loopstack = 0;
36140
36141 if (duk_fb_is_full(fb)) {
36142 return;
36143 }
36144
36145 duk__print_shared_heaphdr(st, &h->hdr);
36146
36147 if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
36148 brace1 = "[";
36149 brace2 = "]";
36150 }
36151
36152 if (!h) {
36153 duk_fb_put_cstring(fb, "NULL");
36154 goto finished;
36155 }
36156
36157 if (st->depth >= st->depth_limit) {
36159 duk_fb_sprintf(fb, "%sobject/compiledfunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36160 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
36161 duk_fb_sprintf(fb, "%sobject/nativefunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36162 } else if (DUK_HOBJECT_IS_THREAD(h)) {
36163 duk_fb_sprintf(fb, "%sobject/thread %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36164 } else {
36165 duk_fb_sprintf(fb, "%sobject %p%s", (const char *) brace1, (void *) h, (const char *) brace2); /* may be NULL */
36166 }
36167 return;
36168 }
36169
36170 for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
36171 if (st->loop_stack[i] == h) {
36172 duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36173 return;
36174 }
36175 }
36176
36177 /* after this, return paths should 'goto finished' for decrement */
36178 st->depth++;
36179
36180 if (st->loop_stack_index >= st->loop_stack_limit) {
36181 duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
36182 goto finished;
36183 }
36184 st->loop_stack[st->loop_stack_index++] = h;
36185 pushed_loopstack = 1;
36186
36187 /*
36188 * Notation: double underscore used for internal properties which are not
36189 * stored in the property allocation (e.g. '__valstack').
36190 */
36191
36192 duk_fb_put_cstring(fb, brace1);
36193
36194 if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
36195 duk_uint32_t a_limit;
36196
36197 a_limit = DUK_HOBJECT_GET_ASIZE(h);
36198 if (st->internal) {
36199 /* dump all allocated entries, unused entries print as 'unused',
36200 * note that these may extend beyond current 'length' and look
36201 * a bit funny.
36202 */
36203 } else {
36204 /* leave out trailing 'unused' elements */
36205 while (a_limit > 0) {
36206 tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
36207 if (!DUK_TVAL_IS_UNUSED(tv)) {
36208 break;
36209 }
36210 a_limit--;
36211 }
36212 }
36213
36214 for (i = 0; i < a_limit; i++) {
36216 DUK__COMMA();
36217 duk__print_tval(st, tv);
36218 }
36219 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
36220 key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
36221 if (!key) {
36222 continue;
36223 }
36224 if (!st->internal &&
36225 DUK_HSTRING_GET_BYTELEN(key) > 0 &&
36226 DUK_HSTRING_GET_DATA(key)[0] == 0xff) {
36227 /* XXX: use DUK_HSTRING_FLAG_INTERNAL? */
36228 continue;
36229 }
36230 DUK__COMMA();
36231 duk__print_hstring(st, key, 0);
36232 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
36234 duk_fb_sprintf(fb, "[get:%p,set:%p]",
36235 (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
36236 (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
36237 } else {
36238 tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
36239 duk__print_tval(st, tv);
36240 }
36241 if (st->heavy) {
36242 duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
36243 }
36244 }
36245 }
36246 if (st->internal) {
36248 DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
36249 } else {
36250 ;
36251 }
36253 DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
36254 } else {
36255 ;
36256 }
36257 if (DUK_HOBJECT_HAS_BOUND(h)) {
36258 DUK__COMMA(); duk_fb_sprintf(fb, "__bound:true");
36259 } else {
36260 ;
36261 }
36263 DUK__COMMA(); duk_fb_sprintf(fb, "__compiledfunction:true");
36264 } else {
36265 ;
36266 }
36268 DUK__COMMA(); duk_fb_sprintf(fb, "__nativefunction:true");
36269 } else {
36270 ;
36271 }
36272 if (DUK_HOBJECT_HAS_THREAD(h)) {
36273 DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
36274 } else {
36275 ;
36276 }
36278 DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
36279 } else {
36280 ;
36281 }
36282 if (DUK_HOBJECT_HAS_STRICT(h)) {
36283 DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
36284 } else {
36285 ;
36286 }
36287 if (DUK_HOBJECT_HAS_NEWENV(h)) {
36288 DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
36289 } else {
36290 ;
36291 }
36293 DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
36294 } else {
36295 ;
36296 }
36298 DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
36299 } else {
36300 ;
36301 }
36303 DUK__COMMA(); duk_fb_sprintf(fb, "__envrecclosed:true");
36304 } else {
36305 ;
36306 }
36308 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
36309 } else {
36310 ;
36311 }
36313 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
36314 } else {
36315 ;
36316 }
36318 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
36319 } else {
36320 ;
36321 }
36323 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_dukfunc:true");
36324 } else {
36325 ;
36326 }
36328 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufferobj:true");
36329 } else {
36330 ;
36331 }
36333 DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
36334 } else {
36335 ;
36336 }
36337 }
36338 if (st->internal && DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
36340 DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
36341 duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
36342 DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
36343 DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
36344#if defined(DUK_USE_DEBUGGER_SUPPORT)
36345 DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
36346 DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
36347#endif
36348 DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
36349 duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
36350 } else if (st->internal && DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
36352 DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
36353 duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
36354 DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
36355 DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
36356 } else if (st->internal && DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
36358 DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
36359 duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
36360 DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
36361 DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
36362 DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
36363 DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
36364 } else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
36365 duk_hthread *t = (duk_hthread *) h;
36366 DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
36367 DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
36368 DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
36369 DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
36370 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_max:%ld", (long) t->valstack_max);
36371 DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_max:%ld", (long) t->callstack_max);
36372 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_max:%ld", (long) t->catchstack_max);
36373 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
36374 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
36375 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
36376 DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
36377 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack:%p", (void *) t->catchstack);
36378 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_size:%ld", (long) t->catchstack_size);
36379 DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_top:%ld", (long) t->catchstack_top);
36380 DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
36381 /* XXX: print built-ins array? */
36382
36383 }
36384#ifdef DUK_USE_REFERENCE_COUNTING
36385 if (st->internal) {
36386 DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
36387 }
36388#endif
36389 if (st->internal) {
36390 DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
36391 }
36392
36393 DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h); /* own pointer */
36394
36395 /* prototype should be last, for readability */
36397 if (st->follow_proto) {
36398 DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
36399 } else {
36400 DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
36401 }
36402 }
36403
36404 duk_fb_put_cstring(fb, brace2);
36405
36406#if defined(DUK_USE_HOBJECT_HASH_PART)
36407 if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
36408 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
36409 for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
36411 if (i > 0) {
36412 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
36413 }
36414 if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
36415 duk_fb_sprintf(fb, "u");
36416 } else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
36417 duk_fb_sprintf(fb, "d");
36418 } else {
36419 duk_fb_sprintf(fb, "%ld", (long) h_idx);
36420 }
36421 }
36422 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
36423 }
36424#endif
36425
36426 finished:
36427 st->depth--;
36428 if (pushed_loopstack) {
36429 st->loop_stack_index--;
36430 st->loop_stack[st->loop_stack_index] = NULL;
36431 }
36432}
36433
36434#undef DUK__COMMA
36435
36436DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
36437 duk_fixedbuffer *fb = st->fb;
36438 duk_size_t i, n;
36439 duk_uint8_t *p;
36440
36441 if (duk_fb_is_full(fb)) {
36442 return;
36443 }
36444
36445 /* terminal type: no depth check */
36446
36447 if (!h) {
36448 duk_fb_put_cstring(fb, "NULL");
36449 return;
36450 }
36451
36452 if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
36453 if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
36455 duk_fb_sprintf(fb, "buffer:external:%p:%ld",
36458 } else {
36460 duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
36463 }
36464 } else {
36465 duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
36466 }
36467
36468#ifdef DUK_USE_REFERENCE_COUNTING
36469 duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
36470#endif
36471
36472 if (st->hexdump) {
36473 duk_fb_sprintf(fb, "=[");
36474 n = DUK_HBUFFER_GET_SIZE(h);
36475 p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
36476 for (i = 0; i < n; i++) {
36477 duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
36478 }
36479 duk_fb_sprintf(fb, "]");
36480 }
36481}
36482
36483DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
36484 duk_fixedbuffer *fb = st->fb;
36485
36486 if (duk_fb_is_full(fb)) {
36487 return;
36488 }
36489
36490 if (!h) {
36491 duk_fb_put_cstring(fb, "NULL");
36492 return;
36493 }
36494
36495 switch (DUK_HEAPHDR_GET_TYPE(h)) {
36496 case DUK_HTYPE_STRING:
36497 duk__print_hstring(st, (duk_hstring *) h, 1);
36498 break;
36499 case DUK_HTYPE_OBJECT:
36500 duk__print_hobject(st, (duk_hobject *) h);
36501 break;
36502 case DUK_HTYPE_BUFFER:
36503 duk__print_hbuffer(st, (duk_hbuffer *) h);
36504 break;
36505 default:
36506 duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
36507 break;
36508 }
36509}
36510
36511DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
36512 duk_fixedbuffer *fb = st->fb;
36513
36514 if (duk_fb_is_full(fb)) {
36515 return;
36516 }
36517
36518 /* depth check is done when printing an actual type */
36519
36520 if (st->heavy) {
36521 duk_fb_sprintf(fb, "(%p)", (void *) tv);
36522 }
36523
36524 if (!tv) {
36525 duk_fb_put_cstring(fb, "NULL");
36526 return;
36527 }
36528
36529 if (st->binary) {
36530 duk_size_t i;
36531 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
36532 for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
36533 duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
36534 }
36535 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
36536 }
36537
36538 if (st->heavy) {
36539 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
36540 }
36541 switch (DUK_TVAL_GET_TAG(tv)) {
36542 case DUK_TAG_UNDEFINED: {
36543 duk_fb_put_cstring(fb, "undefined");
36544 break;
36545 }
36546 case DUK_TAG_UNUSED: {
36547 duk_fb_put_cstring(fb, "unused");
36548 break;
36549 }
36550 case DUK_TAG_NULL: {
36551 duk_fb_put_cstring(fb, "null");
36552 break;
36553 }
36554 case DUK_TAG_BOOLEAN: {
36555 duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
36556 break;
36557 }
36558 case DUK_TAG_STRING: {
36559 /* Note: string is a terminal heap object, so no depth check here */
36560 duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
36561 break;
36562 }
36563 case DUK_TAG_OBJECT: {
36564 duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
36565 break;
36566 }
36567 case DUK_TAG_BUFFER: {
36568 duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
36569 break;
36570 }
36571 case DUK_TAG_POINTER: {
36572 duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
36573 break;
36574 }
36575 case DUK_TAG_LIGHTFUNC: {
36576 duk_c_function func;
36577 duk_small_uint_t lf_flags;
36578
36579 DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
36580 duk_fb_sprintf(fb, "lightfunc:");
36581 duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
36582 duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
36583 break;
36584 }
36585#if defined(DUK_USE_FASTINT)
36586 case DUK_TAG_FASTINT:
36587#endif
36588 default: {
36589 /* IEEE double is approximately 16 decimal digits; print a couple extra */
36592 duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
36593 break;
36594 }
36595 }
36596 if (st->heavy) {
36597 duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
36598 }
36599}
36600
36601DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
36602 duk_fixedbuffer *fb = st->fb;
36603 duk_small_int_t op;
36604 const char *op_name;
36605 const char *extraop_name;
36606
36607 op = (duk_small_int_t) DUK_DEC_OP(ins);
36608 op_name = duk__bc_optab[op];
36609
36610 /* XXX: option to fix opcode length so it lines up nicely */
36611
36612 if (op == DUK_OP_EXTRA) {
36613 extraop_name = duk__bc_extraoptab[DUK_DEC_A(ins)];
36614
36615 duk_fb_sprintf(fb, "%s %ld, %ld",
36616 (const char *) extraop_name, (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
36617 } else if (op == DUK_OP_JUMP) {
36618 duk_int_t diff1 = DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS; /* from next pc */
36619 duk_int_t diff2 = diff1 + 1; /* from curr pc */
36620
36621 duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
36622 (const char *) op_name, (long) diff1,
36623 (int) (diff2 >= 0 ? '+' : '-'), /* char format: use int */
36624 (long) (diff2 >= 0 ? diff2 : -diff2));
36625 } else {
36626 duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
36627 (const char *) op_name, (long) DUK_DEC_A(ins),
36628 (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
36629 }
36630}
36631
36632DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
36633 duk_fixedbuffer *fb = st->fb;
36634
36635 if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
36636 duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
36637 } else {
36638 duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
36639 }
36640}
36641
36642DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
36643 duk_fixedbuffer fb;
36644 const char *p = format;
36645 const char *p_end = p + DUK_STRLEN(format);
36646 duk_int_t retval;
36647
36648 DUK_MEMZERO(&fb, sizeof(fb));
36649 fb.buffer = (duk_uint8_t *) str;
36650 fb.length = size;
36651 fb.offset = 0;
36652 fb.truncated = 0;
36653
36654 while (p < p_end) {
36655 char ch = *p++;
36656 const char *p_begfmt = NULL;
36657 duk_bool_t got_exclamation = 0;
36658 duk_bool_t got_long = 0; /* %lf, %ld etc */
36659 duk__dprint_state st;
36660
36661 if (ch != DUK_ASC_PERCENT) {
36662 duk_fb_put_byte(&fb, (duk_uint8_t) ch);
36663 continue;
36664 }
36665
36666 /*
36667 * Format tag parsing. Since we don't understand all the
36668 * possible format tags allowed, we just scan for a terminating
36669 * specifier and keep track of relevant modifiers that we do
36670 * understand. See man 3 printf.
36671 */
36672
36673 DUK_MEMZERO(&st, sizeof(st));
36674 st.fb = &fb;
36675 st.depth = 0;
36676 st.depth_limit = 1;
36677 st.loop_stack_index = 0;
36678 st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
36679
36680 p_begfmt = p - 1;
36681 while (p < p_end) {
36682 ch = *p++;
36683
36684 if (ch == DUK_ASC_STAR) {
36685 /* unsupported: would consume multiple args */
36686 goto error;
36687 } else if (ch == DUK_ASC_PERCENT) {
36688 duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
36689 break;
36690 } else if (ch == DUK_ASC_EXCLAMATION) {
36691 got_exclamation = 1;
36692 } else if (!got_exclamation && ch == DUK_ASC_LC_L) {
36693 got_long = 1;
36694 } else if (got_exclamation && ch == DUK_ASC_LC_D) {
36695 st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
36696 } else if (got_exclamation && ch == DUK_ASC_LC_P) {
36697 st.follow_proto = 1;
36698 } else if (got_exclamation && ch == DUK_ASC_LC_I) {
36699 st.internal = 1;
36700 } else if (got_exclamation && ch == DUK_ASC_LC_X) {
36701 st.hexdump = 1;
36702 } else if (got_exclamation && ch == DUK_ASC_LC_H) {
36703 st.heavy = 1;
36704 } else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
36705 st.pointer = 1;
36706 } else if (got_exclamation && ch == DUK_ASC_HASH) {
36707 st.binary = 1;
36708 } else if (got_exclamation && ch == DUK_ASC_UC_T) {
36709 duk_tval *t = va_arg(ap, duk_tval *);
36710 if (st.pointer && !st.heavy) {
36711 duk_fb_sprintf(&fb, "(%p)", (void *) t);
36712 }
36713 duk__print_tval(&st, t);
36714 break;
36715 } else if (got_exclamation && ch == DUK_ASC_UC_O) {
36716 duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
36717 if (st.pointer && !st.heavy) {
36718 duk_fb_sprintf(&fb, "(%p)", (void *) t);
36719 }
36720 duk__print_heaphdr(&st, t);
36721 break;
36722 } else if (got_exclamation && ch == DUK_ASC_UC_I) {
36723 duk_instr_t t = va_arg(ap, duk_instr_t);
36724 duk__print_instr(&st, t);
36725 break;
36726 } else if (got_exclamation && ch == DUK_ASC_UC_C) {
36727 long t = va_arg(ap, long);
36728 duk__print_opcode(&st, (duk_small_int_t) t);
36729 break;
36730 } else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
36731 char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
36732 duk_size_t fmtlen;
36733
36734 DUK_ASSERT(p >= p_begfmt);
36735 fmtlen = (duk_size_t) (p - p_begfmt);
36736 if (fmtlen >= sizeof(fmtbuf)) {
36737 /* format is too large, abort */
36738 goto error;
36739 }
36740 DUK_MEMZERO(fmtbuf, sizeof(fmtbuf));
36741 DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);
36742
36743 /* assume exactly 1 arg, which is why '*' is forbidden; arg size still
36744 * depends on type though.
36745 */
36746
36747 if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
36748 /* %f and %lf both consume a 'long' */
36749 double arg = va_arg(ap, double);
36750 duk_fb_sprintf(&fb, fmtbuf, arg);
36751 } else if (ch == DUK_ASC_LC_D && got_long) {
36752 /* %ld */
36753 long arg = va_arg(ap, long);
36754 duk_fb_sprintf(&fb, fmtbuf, arg);
36755 } else if (ch == DUK_ASC_LC_D) {
36756 /* %d; only 16 bits are guaranteed */
36757 int arg = va_arg(ap, int);
36758 duk_fb_sprintf(&fb, fmtbuf, arg);
36759 } else if (ch == DUK_ASC_LC_U && got_long) {
36760 /* %lu */
36761 unsigned long arg = va_arg(ap, unsigned long);
36762 duk_fb_sprintf(&fb, fmtbuf, arg);
36763 } else if (ch == DUK_ASC_LC_U) {
36764 /* %u; only 16 bits are guaranteed */
36765 unsigned int arg = va_arg(ap, unsigned int);
36766 duk_fb_sprintf(&fb, fmtbuf, arg);
36767 } else if (ch == DUK_ASC_LC_X && got_long) {
36768 /* %lx */
36769 unsigned long arg = va_arg(ap, unsigned long);
36770 duk_fb_sprintf(&fb, fmtbuf, arg);
36771 } else if (ch == DUK_ASC_LC_X) {
36772 /* %x; only 16 bits are guaranteed */
36773 unsigned int arg = va_arg(ap, unsigned int);
36774 duk_fb_sprintf(&fb, fmtbuf, arg);
36775 } else if (ch == DUK_ASC_LC_S) {
36776 /* %s */
36777 const char *arg = va_arg(ap, const char *);
36778 if (arg == NULL) {
36779 /* '%s' and NULL is not portable, so special case
36780 * it for debug printing.
36781 */
36782 duk_fb_sprintf(&fb, "NULL");
36783 } else {
36784 duk_fb_sprintf(&fb, fmtbuf, arg);
36785 }
36786 } else if (ch == DUK_ASC_LC_P) {
36787 /* %p */
36788 void *arg = va_arg(ap, void *);
36789 if (arg == NULL) {
36790 /* '%p' and NULL is portable, but special case it
36791 * anyway to get a standard NULL marker in logs.
36792 */
36793 duk_fb_sprintf(&fb, "NULL");
36794 } else {
36795 duk_fb_sprintf(&fb, fmtbuf, arg);
36796 }
36797 } else if (ch == DUK_ASC_LC_C) {
36798 /* '%c', passed concretely as int */
36799 int arg = va_arg(ap, int);
36800 duk_fb_sprintf(&fb, fmtbuf, arg);
36801 } else {
36802 /* Should not happen. */
36803 duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
36804 }
36805 break;
36806 } else {
36807 /* ignore */
36808 }
36809 }
36810 }
36811 goto done;
36812
36813 error:
36814 duk_fb_put_cstring(&fb, "FMTERR");
36815 /* fall through */
36816
36817 done:
36818 retval = (duk_int_t) fb.offset;
36819 duk_fb_put_byte(&fb, (duk_uint8_t) 0);
36820
36821 /* return total chars written excluding terminator */
36822 return retval;
36823}
36824
36825#if 0 /*unused*/
36826DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
36827 duk_int_t retval;
36828 va_list ap;
36829 va_start(ap, format);
36830 retval = duk_debug_vsnprintf(str, size, format, ap);
36831 va_end(ap);
36832 return retval;
36833}
36834#endif
36835
36836/* Formatting function pointers is tricky: there is no standard pointer for
36837 * function pointers and the size of a function pointer may depend on the
36838 * specific pointer type. This helper formats a function pointer based on
36839 * its memory layout to get something useful on most platforms.
36840 */
36841DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
36842 duk_size_t i;
36843 duk_uint8_t *p = (duk_uint8_t *) buf;
36844 duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
36845
36846 DUK_MEMZERO(buf, buf_size);
36847
36848 for (i = 0; i < fptr_size; i++) {
36849 duk_int_t left = (duk_int_t) (p_end - p);
36850 duk_uint8_t ch;
36851 if (left <= 0) {
36852 break;
36853 }
36854
36855 /* Quite approximate but should be useful for little and big endian. */
36856#ifdef DUK_USE_INTEGER_BE
36857 ch = fptr[i];
36858#else
36859 ch = fptr[fptr_size - 1 - i];
36860#endif
36861 p += DUK_SNPRINTF((char *) p, left, "%02lx", (unsigned long) ch);
36862 }
36863}
36864
36865#endif /* DUK_USE_DEBUG */
36866#line 1 "duk_debugger.c"
36867/*
36868 * Duktape debugger
36869 */
36870
36871/* include removed: duk_internal.h */
36872
36873#if defined(DUK_USE_DEBUGGER_SUPPORT)
36874
36875/*
36876 * Helper structs
36877 */
36878
36879typedef union {
36880 void *p;
36881 duk_uint_t b[1];
36882 /* Use b[] to access the size of the union, which is strictly not
36883 * correct. Can't use fixed size unless there's feature detection
36884 * for pointer byte size.
36885 */
36886} duk__ptr_union;
36887
36888/*
36889 * Detach handling
36890 */
36891
36892#define DUK__SET_CONN_BROKEN(thr,reason) do { \
36893 /* For now shared handler is fine. */ \
36894 duk__debug_do_detach1((thr)->heap, (reason)); \
36895 } while (0)
36896
36897DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
36898 /* Can be called multiple times with no harm. Mark the transport
36899 * bad (dbg_read_cb == NULL) and clear state except for the detached
36900 * callback and the udata field. The detached callback is delayed
36901 * to the message loop so that it can be called between messages;
36902 * this avoids corner cases related to immediate debugger reattach
36903 * inside the detached callback.
36904 */
36905
36906 if (heap->dbg_detaching) {
36907 DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
36908 return;
36909 }
36910
36911 DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
36912
36913 heap->dbg_detaching = 1; /* prevent multiple in-progress detaches */
36914
36915 if (heap->dbg_write_cb != NULL) {
36916 duk_hthread *thr;
36917
36918 thr = heap->heap_thread;
36919 DUK_ASSERT(thr != NULL);
36920
36921 duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
36922 duk_debug_write_int(thr, reason);
36923 duk_debug_write_eom(thr);
36924 }
36925
36926 heap->dbg_read_cb = NULL;
36927 heap->dbg_write_cb = NULL;
36928 heap->dbg_peek_cb = NULL;
36929 heap->dbg_read_flush_cb = NULL;
36930 heap->dbg_write_flush_cb = NULL;
36931 heap->dbg_request_cb = NULL;
36932 /* heap->dbg_detached_cb: keep */
36933 /* heap->dbg_udata: keep */
36934 /* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
36935 heap->dbg_paused = 0;
36936 heap->dbg_state_dirty = 0;
36937 heap->dbg_force_restart = 0;
36938 heap->dbg_step_type = 0;
36939 heap->dbg_step_thread = NULL;
36940 heap->dbg_step_csindex = 0;
36941 heap->dbg_step_startline = 0;
36942 heap->dbg_have_next_byte = 0;
36943
36944 /* Ensure there are no stale active breakpoint pointers.
36945 * Breakpoint list is currently kept - we could empty it
36946 * here but we'd need to handle refcounts correctly, and
36947 * we'd need a 'thr' reference for that.
36948 *
36949 * XXX: clear breakpoint on either attach or detach?
36950 */
36951 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
36952}
36953
36954DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
36955 duk_debug_detached_function detached_cb;
36956 void *detached_udata;
36957
36958 /* Safe to call multiple times. */
36959
36960 detached_cb = heap->dbg_detached_cb;
36961 detached_udata = heap->dbg_udata;
36962 heap->dbg_detached_cb = NULL;
36963 heap->dbg_udata = NULL;
36964
36965 if (detached_cb) {
36966 /* Careful here: state must be wiped before the call
36967 * so that we can cleanly handle a re-attach from
36968 * inside the callback.
36969 */
36970 DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
36971 detached_cb(detached_udata);
36972 }
36973
36974 heap->dbg_detaching = 0;
36975}
36976
36977DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
36978 duk__debug_do_detach1(heap, 0);
36979 duk__debug_do_detach2(heap);
36980}
36981
36982/* Called on a read/write error: NULL all callbacks except the detached
36983 * callback so that we never accidentally call them after a read/write
36984 * error has been indicated. This is especially important for the transport
36985 * I/O callbacks to fulfill guaranteed callback semantics.
36986 */
36987DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
36988 duk_heap *heap;
36989 heap = thr->heap;
36990 DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
36991 heap->dbg_read_cb = NULL;
36992 heap->dbg_write_cb = NULL; /* this is especially critical to avoid another write call in detach1() */
36993 heap->dbg_peek_cb = NULL;
36994 heap->dbg_read_flush_cb = NULL;
36995 heap->dbg_write_flush_cb = NULL;
36996 heap->dbg_request_cb = NULL;
36997 /* keep heap->dbg_detached_cb */
36998}
36999
37000/*
37001 * Debug connection peek and flush primitives
37002 */
37003
37004DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
37005 duk_heap *heap;
37006
37007 DUK_ASSERT(thr != NULL);
37008 heap = thr->heap;
37009 DUK_ASSERT(heap != NULL);
37010
37011 if (heap->dbg_read_cb == NULL) {
37012 DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
37013 return 0;
37014 }
37015 if (heap->dbg_peek_cb == NULL) {
37016 DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
37017 return 0;
37018 }
37019
37020 return (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
37021}
37022
37023DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
37024 duk_heap *heap;
37025
37026 DUK_ASSERT(thr != NULL);
37027 heap = thr->heap;
37028 DUK_ASSERT(heap != NULL);
37029
37030 if (heap->dbg_read_cb == NULL) {
37031 DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
37032 return;
37033 }
37034 if (heap->dbg_read_flush_cb == NULL) {
37035 DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
37036 return;
37037 }
37038
37039 heap->dbg_read_flush_cb(heap->dbg_udata);
37040}
37041
37042DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
37043 duk_heap *heap;
37044
37045 DUK_ASSERT(thr != NULL);
37046 heap = thr->heap;
37047 DUK_ASSERT(heap != NULL);
37048
37049 if (heap->dbg_read_cb == NULL) {
37050 DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
37051 return;
37052 }
37053 if (heap->dbg_write_flush_cb == NULL) {
37054 DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
37055 return;
37056 }
37057
37058 heap->dbg_write_flush_cb(heap->dbg_udata);
37059}
37060
37061/*
37062 * Debug connection skip primitives
37063 */
37064
37065/* Skip fully. */
37066DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
37067 duk_uint8_t dummy[64];
37068 duk_size_t now;
37069
37070 DUK_ASSERT(thr != NULL);
37071
37072 while (length > 0) {
37073 now = (length > sizeof(dummy) ? sizeof(dummy) : length);
37074 duk_debug_read_bytes(thr, dummy, now);
37075 length -= now;
37076 }
37077}
37078
37079DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
37080 DUK_ASSERT(thr != NULL);
37081
37082 (void) duk_debug_read_byte(thr);
37083}
37084
37085/*
37086 * Debug connection read primitives
37087 */
37088
37089/* Peek ahead in the stream one byte. */
37090DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
37091 /* It is important not to call this if the last byte read was an EOM.
37092 * Reading ahead in this scenario would cause unnecessary blocking if
37093 * another message is not available.
37094 */
37095
37096 duk_uint8_t x;
37097
37098 x = duk_debug_read_byte(thr);
37099 thr->heap->dbg_have_next_byte = 1;
37100 thr->heap->dbg_next_byte = x;
37101 return x;
37102}
37103
37104/* Read fully. */
37105DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
37106 duk_heap *heap;
37107 duk_uint8_t *p;
37109 duk_size_t got;
37110
37111 DUK_ASSERT(thr != NULL);
37112 heap = thr->heap;
37113 DUK_ASSERT(heap != NULL);
37114
37115 if (heap->dbg_read_cb == NULL) {
37116 DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
37117 goto fail;
37118 }
37119
37120 /* NOTE: length may be zero */
37121 p = data;
37122 if (length >= 1 && heap->dbg_have_next_byte) {
37123 heap->dbg_have_next_byte = 0;
37124 *p++ = heap->dbg_next_byte;
37125 }
37126 for (;;) {
37127 left = (duk_size_t) ((data + length) - p);
37128 if (left == 0) {
37129 break;
37130 }
37131 DUK_ASSERT(heap->dbg_read_cb != NULL);
37132 DUK_ASSERT(left >= 1);
37133#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
37134 left = 1;
37135#endif
37136 got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
37137 if (got == 0 || got > left) {
37138 DUK_D(DUK_DPRINT("connection error during read, return zero data"));
37139 duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
37140 DUK__SET_CONN_BROKEN(thr, 1);
37141 goto fail;
37142 }
37143 p += got;
37144 }
37145 return;
37146
37147 fail:
37148 DUK_MEMZERO((void *) data, (size_t) length);
37149}
37150
37151DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
37152 duk_uint8_t x;
37153
37154 x = 0; /* just in case callback is broken and won't write 'x' */
37155 duk_debug_read_bytes(thr, &x, 1);
37156 return x;
37157}
37158
37159DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
37160 duk_uint8_t buf[4];
37161
37162 DUK_ASSERT(thr != NULL);
37163
37164 duk_debug_read_bytes(thr, buf, 4);
37165 return ((duk_uint32_t) buf[0] << 24) |
37166 ((duk_uint32_t) buf[1] << 16) |
37167 ((duk_uint32_t) buf[2] << 8) |
37168 (duk_uint32_t) buf[3];
37169}
37170
37171DUK_LOCAL duk_uint32_t duk__debug_read_int32_raw(duk_hthread *thr) {
37172 return (duk_int32_t) duk__debug_read_uint32_raw(thr);
37173}
37174
37175DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
37176 duk_uint8_t buf[2];
37177
37178 DUK_ASSERT(thr != NULL);
37179
37180 duk_debug_read_bytes(thr, buf, 2);
37181 return ((duk_uint16_t) buf[0] << 8) |
37182 (duk_uint16_t) buf[1];
37183}
37184
37185DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
37188
37189 DUK_ASSERT(thr != NULL);
37190
37191 x = duk_debug_read_byte(thr);
37192 if (x >= 0xc0) {
37193 t = duk_debug_read_byte(thr);
37194 return (duk_int32_t) (((x - 0xc0) << 8) + t);
37195 } else if (x >= 0x80) {
37196 return (duk_int32_t) (x - 0x80);
37197 } else if (x == DUK_DBG_IB_INT4) {
37198 return (duk_int32_t) duk__debug_read_uint32_raw(thr);
37199 }
37200
37201 DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
37202 DUK__SET_CONN_BROKEN(thr, 1);
37203 return 0;
37204}
37205
37206DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
37207 duk_context *ctx = (duk_context *) thr;
37208 duk_uint8_t buf[31];
37209 duk_uint8_t *p;
37210
37211 if (len <= sizeof(buf)) {
37212 duk_debug_read_bytes(thr, buf, (duk_size_t) len);
37213 duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len);
37214 } else {
37215 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
37216 DUK_ASSERT(p != NULL);
37217 duk_debug_read_bytes(thr, p, (duk_size_t) len);
37218 duk_to_string(ctx, -1);
37219 }
37220
37221 return duk_require_hstring(ctx, -1);
37222}
37223
37224DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
37225 duk_context *ctx = (duk_context *) thr;
37227 duk_uint32_t len;
37228
37229 DUK_ASSERT(thr != NULL);
37230
37231 x = duk_debug_read_byte(thr);
37232 if (x >= 0x60 && x <= 0x7f) {
37233 /* For short strings, use a fixed temp buffer. */
37234 len = (duk_uint32_t) (x - 0x60);
37235 } else if (x == DUK_DBG_IB_STR2) {
37236 len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
37237 } else if (x == DUK_DBG_IB_STR4) {
37238 len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
37239 } else {
37240 goto fail;
37241 }
37242
37243 return duk__debug_read_hstring_raw(thr, len);
37244
37245 fail:
37246 DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
37247 DUK__SET_CONN_BROKEN(thr, 1);
37248 duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING); /* always push some string */
37249 return duk_require_hstring(ctx, -1);
37250}
37251
37252DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
37253 duk_context *ctx = (duk_context *) thr;
37254 duk_uint8_t *p;
37255
37256 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
37257 DUK_ASSERT(p != NULL);
37258 duk_debug_read_bytes(thr, p, (duk_size_t) len);
37259
37260 return duk_require_hbuffer(ctx, -1);
37261}
37262
37263DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
37265 duk__ptr_union pu;
37266
37267 DUK_ASSERT(thr != NULL);
37268
37269 x = duk_debug_read_byte(thr);
37270 if (x != sizeof(pu)) {
37271 goto fail;
37272 }
37273 duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
37274#if defined(DUK_USE_INTEGER_LE)
37275 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37276#endif
37277 return (void *) pu.p;
37278
37279 fail:
37280 DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
37281 DUK__SET_CONN_BROKEN(thr, 1);
37282 return (void *) NULL;
37283}
37284
37285DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
37287
37288 DUK_ASSERT(sizeof(du.uc) == 8);
37289 duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
37291 return du.d;
37292}
37293
37294#if 0
37295DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
37297
37298 DUK_ASSERT(thr != NULL);
37299
37300 x = duk_debug_read_byte(thr);
37301 if (x != DUK_DBG_IB_HEAPPTR) {
37302 goto fail;
37303 }
37304
37305 return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37306
37307 fail:
37308 DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
37309 DUK__SET_CONN_BROKEN(thr, 1);
37310 return NULL;
37311}
37312#endif
37313
37314DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
37316
37317 DUK_ASSERT(thr != NULL);
37318
37319 x = duk_debug_read_byte(thr);
37320 switch (x) {
37321 case DUK_DBG_IB_OBJECT:
37322 case DUK_DBG_IB_POINTER:
37323 case DUK_DBG_IB_HEAPPTR:
37324 /* Accept any pointer-like value; for 'object' dvalue, read
37325 * and ignore the class number.
37326 */
37327 if (x == DUK_DBG_IB_OBJECT) {
37328 duk_debug_skip_byte(thr);
37329 }
37330 break;
37331 default:
37332 goto fail;
37333 }
37334
37335 return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37336
37337 fail:
37338 DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
37339 DUK__SET_CONN_BROKEN(thr, 1);
37340 return NULL;
37341}
37342
37343DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
37344 duk_context *ctx = (duk_context *) thr;
37345 duk_uint8_t x;
37346 duk_uint_t t;
37347 duk_uint32_t len;
37348
37349 DUK_ASSERT(thr != NULL);
37350
37351 x = duk_debug_read_byte(thr);
37352
37353 if (x >= 0xc0) {
37354 t = (duk_uint_t) (x - 0xc0);
37355 t = (t << 8) + duk_debug_read_byte(thr);
37356 duk_push_uint(ctx, (duk_uint_t) t);
37357 goto return_ptr;
37358 }
37359 if (x >= 0x80) {
37360 duk_push_uint(ctx, (duk_uint_t) (x - 0x80));
37361 goto return_ptr;
37362 }
37363 if (x >= 0x60) {
37364 len = (duk_uint32_t) (x - 0x60);
37365 duk__debug_read_hstring_raw(thr, len);
37366 goto return_ptr;
37367 }
37368
37369 switch (x) {
37370 case DUK_DBG_IB_INT4: {
37371 duk_int32_t i = duk__debug_read_int32_raw(thr);
37372 duk_push_i32(ctx, i);
37373 break;
37374 }
37375 case DUK_DBG_IB_STR4: {
37376 len = duk__debug_read_uint32_raw(thr);
37377 duk__debug_read_hstring_raw(thr, len);
37378 break;
37379 }
37380 case DUK_DBG_IB_STR2: {
37381 len = duk__debug_read_uint16_raw(thr);
37382 duk__debug_read_hstring_raw(thr, len);
37383 break;
37384 }
37385 case DUK_DBG_IB_BUF4: {
37386 len = duk__debug_read_uint32_raw(thr);
37387 duk__debug_read_hbuffer_raw(thr, len);
37388 break;
37389 }
37390 case DUK_DBG_IB_BUF2: {
37391 len = duk__debug_read_uint16_raw(thr);
37392 duk__debug_read_hbuffer_raw(thr, len);
37393 break;
37394 }
37395 case DUK_DBG_IB_UNDEFINED: {
37396 duk_push_undefined(ctx);
37397 break;
37398 }
37399 case DUK_DBG_IB_NULL: {
37400 duk_push_null(ctx);
37401 break;
37402 }
37403 case DUK_DBG_IB_TRUE: {
37404 duk_push_true(ctx);
37405 break;
37406 }
37407 case DUK_DBG_IB_FALSE: {
37408 duk_push_false(ctx);
37409 break;
37410 }
37411 case DUK_DBG_IB_NUMBER: {
37412 duk_double_t d;
37413 d = duk__debug_read_double_raw(thr);
37414 duk_push_number(ctx, d);
37415 break;
37416 }
37417 case DUK_DBG_IB_OBJECT: {
37418 duk_heaphdr *h;
37419 duk_debug_skip_byte(thr);
37420 h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37421 duk_push_heapptr(thr, (void *) h);
37422 break;
37423 }
37424 case DUK_DBG_IB_POINTER: {
37425 void *ptr;
37426 ptr = duk__debug_read_pointer_raw(thr);
37427 duk_push_pointer(thr, ptr);
37428 break;
37429 }
37430 case DUK_DBG_IB_LIGHTFUNC: {
37431 /* XXX: Not needed for now, so not implemented. Note that
37432 * function pointers may have different size/layout than
37433 * a void pointer.
37434 */
37435 DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
37436 goto fail;
37437 }
37438 case DUK_DBG_IB_HEAPPTR: {
37439 duk_heaphdr *h;
37440 h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37441 duk_push_heapptr(thr, (void *) h);
37442 break;
37443 }
37444 case DUK_DBG_IB_UNUSED: /* unused: not accepted in inbound messages */
37445 default:
37446 goto fail;
37447 }
37448
37449 return_ptr:
37450 return DUK_GET_TVAL_NEGIDX(thr, -1);
37451
37452 fail:
37453 DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
37454 DUK__SET_CONN_BROKEN(thr, 1);
37455 return NULL;
37456}
37457
37458/*
37459 * Debug connection write primitives
37460 */
37461
37462/* Write fully. */
37463DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
37464 duk_heap *heap;
37465 const duk_uint8_t *p;
37467 duk_size_t got;
37468
37469 DUK_ASSERT(thr != NULL);
37470 DUK_ASSERT(length == 0 || data != NULL);
37471 heap = thr->heap;
37472 DUK_ASSERT(heap != NULL);
37473
37474 if (heap->dbg_write_cb == NULL) {
37475 DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
37476 return;
37477 }
37478 if (length == 0) {
37479 /* Avoid doing an actual write callback with length == 0,
37480 * because that's reserved for a write flush.
37481 */
37482 return;
37483 }
37484 DUK_ASSERT(data != NULL);
37485
37486 p = data;
37487 for (;;) {
37488 left = (duk_size_t) ((data + length) - p);
37489 if (left == 0) {
37490 break;
37491 }
37492 DUK_ASSERT(heap->dbg_write_cb != NULL);
37493 DUK_ASSERT(left >= 1);
37494#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
37495 left = 1;
37496#endif
37497 got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
37498 if (got == 0 || got > left) {
37499 duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
37500 DUK_D(DUK_DPRINT("connection error during write"));
37501 DUK__SET_CONN_BROKEN(thr, 1);
37502 return;
37503 }
37504 p += got;
37505 }
37506}
37507
37508DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
37509 duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
37510}
37511
37512DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
37513 duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
37514}
37515
37516DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
37517 duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
37518}
37519
37520#if defined(DUK_USE_DEBUGGER_INSPECT)
37521DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
37522 duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
37523}
37524#endif
37525
37526DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
37527 duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
37528}
37529
37530/* Write signed 32-bit integer. */
37531DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
37532 duk_uint8_t buf[5];
37533 duk_size_t len;
37534
37535 DUK_ASSERT(thr != NULL);
37536
37537 if (x >= 0 && x <= 0x3fL) {
37538 buf[0] = (duk_uint8_t) (0x80 + x);
37539 len = 1;
37540 } else if (x >= 0 && x <= 0x3fffL) {
37541 buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
37542 buf[1] = (duk_uint8_t) (x & 0xff);
37543 len = 2;
37544 } else {
37545 /* Signed integers always map to 4 bytes now. */
37546 buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
37547 buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
37548 buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
37549 buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
37550 buf[4] = (duk_uint8_t) (x & 0xff);
37551 len = 5;
37552 }
37553 duk_debug_write_bytes(thr, buf, len);
37554}
37555
37556/* Write unsigned 32-bit integer. */
37557DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
37558 /* The debugger protocol doesn't support a plain integer encoding for
37559 * the full 32-bit unsigned range (only 32-bit signed). For now,
37560 * unsigned 32-bit values simply written as signed ones. This is not
37561 * a concrete issue except for 32-bit heaphdr fields. Proper solutions
37562 * would be to (a) write such integers as IEEE doubles or (b) add an
37563 * unsigned 32-bit dvalue.
37564 */
37565 if (x >= 0x80000000UL) {
37566 DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
37567 (long) x));
37568 }
37569 duk_debug_write_int(thr, (duk_int32_t) x);
37570}
37571
37572DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
37573 duk_uint8_t buf[5];
37574 duk_size_t buflen;
37575
37576 DUK_ASSERT(thr != NULL);
37577 DUK_ASSERT(length == 0 || data != NULL);
37578
37579 if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
37580 /* For strings, special form for short lengths. */
37581 buf[0] = (duk_uint8_t) (0x60 + length);
37582 buflen = 1;
37583 } else if (length <= 0xffffUL) {
37584 buf[0] = (duk_uint8_t) (marker_base + 1);
37585 buf[1] = (duk_uint8_t) (length >> 8);
37586 buf[2] = (duk_uint8_t) (length & 0xff);
37587 buflen = 3;
37588 } else {
37589 buf[0] = (duk_uint8_t) marker_base;
37590 buf[1] = (duk_uint8_t) (length >> 24);
37591 buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
37592 buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
37593 buf[4] = (duk_uint8_t) (length & 0xff);
37594 buflen = 5;
37595 }
37596
37597 duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
37598 duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
37599}
37600
37601DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
37602 duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
37603}
37604
37605DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
37606 DUK_ASSERT(thr != NULL);
37607
37608 duk_debug_write_string(thr,
37609 data,
37610 data ? DUK_STRLEN(data) : 0);
37611}
37612
37613DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
37614 DUK_ASSERT(thr != NULL);
37615
37616 /* XXX: differentiate null pointer from empty string? */
37617 duk_debug_write_string(thr,
37618 (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
37619 (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
37620}
37621
37622DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
37623 duk_context *ctx = (duk_context *) thr;
37624 duk_debug_write_hstring(thr, duk_safe_to_hstring(ctx, -1));
37625}
37626
37627DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
37628 duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
37629}
37630
37631DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
37632 DUK_ASSERT(thr != NULL);
37633
37634 duk_debug_write_buffer(thr,
37635 (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
37636 (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
37637}
37638
37639DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
37640 duk_uint8_t buf[2];
37641 duk__ptr_union pu;
37642
37643 DUK_ASSERT(thr != NULL);
37644 DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
37645 /* ptr may be NULL */
37646
37647 buf[0] = ibyte;
37648 buf[1] = sizeof(pu);
37649 duk_debug_write_bytes(thr, buf, 2);
37650 pu.p = (void *) ptr;
37651#if defined(DUK_USE_INTEGER_LE)
37652 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37653#endif
37654 duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
37655}
37656
37657DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
37658 duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
37659}
37660
37661#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
37662DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
37663 duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
37664}
37665#endif /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
37666
37667DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
37668 duk_uint8_t buf[3];
37669 duk__ptr_union pu;
37670
37671 DUK_ASSERT(thr != NULL);
37672 DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
37673 DUK_ASSERT(obj != NULL);
37674
37675 buf[0] = DUK_DBG_IB_OBJECT;
37676 buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
37677 buf[2] = sizeof(pu);
37678 duk_debug_write_bytes(thr, buf, 3);
37679 pu.p = (void *) obj;
37680#if defined(DUK_USE_INTEGER_LE)
37681 duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37682#endif
37683 duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
37684}
37685
37686DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
37687 duk_c_function lf_func;
37688 duk_small_uint_t lf_flags;
37689 duk_uint8_t buf[4];
37690 duk_double_union du1;
37691 duk_double_union du2;
37692 duk_int32_t i32;
37693
37694 DUK_ASSERT(thr != NULL);
37695 DUK_ASSERT(tv != NULL);
37696
37697 switch (DUK_TVAL_GET_TAG(tv)) {
37698 case DUK_TAG_UNDEFINED:
37699 duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
37700 break;
37701 case DUK_TAG_UNUSED:
37702 duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
37703 break;
37704 case DUK_TAG_NULL:
37705 duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
37706 break;
37707 case DUK_TAG_BOOLEAN:
37709 DUK_TVAL_GET_BOOLEAN(tv) == 1);
37710 duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
37711 break;
37712 case DUK_TAG_POINTER:
37713 duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
37714 break;
37715 case DUK_TAG_LIGHTFUNC:
37716 DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
37717 buf[0] = DUK_DBG_IB_LIGHTFUNC;
37718 buf[1] = (duk_uint8_t) (lf_flags >> 8);
37719 buf[2] = (duk_uint8_t) (lf_flags & 0xff);
37720 buf[3] = sizeof(lf_func);
37721 duk_debug_write_bytes(thr, buf, 4);
37722 duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
37723 break;
37724 case DUK_TAG_STRING:
37725 duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
37726 break;
37727 case DUK_TAG_OBJECT:
37728 duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
37729 break;
37730 case DUK_TAG_BUFFER:
37731 duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
37732 break;
37733#if defined(DUK_USE_FASTINT)
37734 case DUK_TAG_FASTINT:
37735#endif
37736 default:
37737 /* Numbers are normalized to big (network) endian. We can
37738 * (but are not required) to use integer dvalues when there's
37739 * no loss of precision.
37740 *
37741 * XXX: share check with other code; this check is slow but
37742 * reliable and doesn't require careful exponent/mantissa
37743 * mask tricks as in the fastint downgrade code.
37744 */
37747 du1.d = DUK_TVAL_GET_NUMBER(tv);
37748 i32 = (duk_int32_t) du1.d;
37749 du2.d = (duk_double_t) i32;
37750
37751 DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
37752 "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
37753 (long) i32,
37754 (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
37755 (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
37756 (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
37757 (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
37758 (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
37759 (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
37760 (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
37761 (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
37762
37763 if (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
37764 duk_debug_write_int(thr, i32);
37765 } else {
37766 DUK_DBLUNION_DOUBLE_HTON(&du1);
37767 duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
37768 duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
37769 }
37770 }
37771}
37772
37773#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
37774/* Variant for writing duk_tvals so that any heap allocated values are
37775 * written out as tagged heap pointers.
37776 */
37777DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
37780 duk_debug_write_heapptr(thr, h);
37781 } else {
37782 duk_debug_write_tval(thr, tv);
37783 }
37784}
37785#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
37786
37787/*
37788 * Debug connection message write helpers
37789 */
37790
37791#if 0 /* unused */
37792DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
37793 duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
37794 duk_debug_write_int(thr, command);
37795}
37796#endif
37797
37798DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
37799 duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
37800}
37801
37802DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
37803 /* Allow NULL 'msg' */
37804 duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
37805 duk_debug_write_int(thr, (duk_int32_t) err_code);
37806 duk_debug_write_cstring(thr, msg);
37807 duk_debug_write_eom(thr);
37808}
37809
37810DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
37811 duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
37812 duk_debug_write_int(thr, command);
37813}
37814
37815DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
37816 duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
37817
37818 /* As an initial implementation, write flush after every EOM (and the
37819 * version identifier). A better implementation would flush only when
37820 * Duktape is finished processing messages so that a flush only happens
37821 * after all outbound messages are finished on that occasion.
37822 */
37823 duk_debug_write_flush(thr);
37824}
37825
37826/*
37827 * Status message and helpers
37828 */
37829
37830DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
37831 duk_context *ctx = (duk_context *) thr;
37832 duk_activation *act;
37833 duk_uint_fast32_t line;
37835
37836 act = duk_hthread_get_current_activation(thr); /* may be NULL */
37837 if (act == NULL) {
37838 return 0;
37839 }
37840
37841 /* We're conceptually between two opcodes; act->pc indicates the next
37842 * instruction to be executed. This is usually the correct pc/line to
37843 * indicate in Status. (For the 'debugger' statement this now reports
37844 * the pc/line after the debugger statement because the debugger opcode
37845 * has already been executed.)
37846 */
37847
37848 pc = duk_hthread_get_act_curr_pc(thr, act);
37849
37850 /* XXX: this should be optimized to be a raw query and avoid valstack
37851 * operations if possible.
37852 */
37853 duk_push_tval(ctx, &act->tv_func);
37854 line = duk_hobject_pc2line_query(ctx, -1, pc);
37855 duk_pop(ctx);
37856 return line;
37857}
37858
37859DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
37860 duk_context *ctx = (duk_context *) thr;
37861 duk_activation *act;
37862
37863 duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
37864 duk_debug_write_int(thr, thr->heap->dbg_paused);
37865
37866 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* unsigned */
37867 if (thr->callstack_top == 0) {
37868 duk_debug_write_undefined(thr);
37869 duk_debug_write_undefined(thr);
37870 duk_debug_write_int(thr, 0);
37871 duk_debug_write_int(thr, 0);
37872 } else {
37873 act = thr->callstack + thr->callstack_top - 1;
37874 duk_push_tval(ctx, &act->tv_func);
37875 duk_get_prop_string(ctx, -1, "fileName");
37876 duk__debug_write_hstring_safe_top(thr);
37877 duk_get_prop_string(ctx, -2, "name");
37878 duk__debug_write_hstring_safe_top(thr);
37879 duk_pop_3(ctx);
37880 /* Report next pc/line to be executed. */
37881 duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
37882 duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
37883 }
37884
37885 duk_debug_write_eom(thr);
37886}
37887
37888#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
37889DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
37890 /*
37891 * NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
37892 */
37893
37894 duk_context *ctx = (duk_context *) thr;
37895 duk_activation *act;
37896 duk_uint32_t pc;
37897
37898 DUK_ASSERT(thr->valstack_top > thr->valstack); /* At least: ... [err] */
37899
37900 duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
37901 duk_debug_write_int(thr, fatal);
37902
37903 /* Report thrown value to client coerced to string */
37904 duk_dup(ctx, -1);
37905 duk__debug_write_hstring_safe_top(thr);
37906 duk_pop(ctx);
37907
37908 if (duk_is_error(ctx, -1)) {
37909 /* Error instance, use augmented error data directly */
37911 duk__debug_write_hstring_safe_top(thr);
37913 duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
37914 } else {
37915 /* For anything other than an Error instance, we calculate the error
37916 * location directly from the current activation.
37917 */
37918 act = thr->callstack + thr->callstack_top - 1;
37919 duk_push_tval(ctx, &act->tv_func);
37920 duk_get_prop_string(ctx, -1, "fileName");
37921 duk__debug_write_hstring_safe_top(thr);
37922 pc = duk_hthread_get_act_prev_pc(thr, act);
37923 duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
37924 }
37925 duk_pop_2(ctx); /* shared pop */
37926
37927 duk_debug_write_eom(thr);
37928}
37929#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY */
37930
37931/*
37932 * Debug message processing
37933 */
37934
37935/* Skip dvalue. */
37936DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
37937 duk_uint8_t x;
37938 duk_uint32_t len;
37939
37940 x = duk_debug_read_byte(thr);
37941
37942 if (x >= 0xc0) {
37943 duk_debug_skip_byte(thr);
37944 return 0;
37945 }
37946 if (x >= 0x80) {
37947 return 0;
37948 }
37949 if (x >= 0x60) {
37950 duk_debug_skip_bytes(thr, x - 0x60);
37951 return 0;
37952 }
37953 switch(x) {
37954 case DUK_DBG_IB_EOM:
37955 return 1; /* Return 1: got EOM */
37956 case DUK_DBG_IB_REQUEST:
37957 case DUK_DBG_IB_REPLY:
37958 case DUK_DBG_IB_ERROR:
37959 case DUK_DBG_IB_NOTIFY:
37960 break;
37961 case DUK_DBG_IB_INT4:
37962 (void) duk__debug_read_uint32_raw(thr);
37963 break;
37964 case DUK_DBG_IB_STR4:
37965 case DUK_DBG_IB_BUF4:
37966 len = duk__debug_read_uint32_raw(thr);
37967 duk_debug_skip_bytes(thr, len);
37968 break;
37969 case DUK_DBG_IB_STR2:
37970 case DUK_DBG_IB_BUF2:
37971 len = duk__debug_read_uint16_raw(thr);
37972 duk_debug_skip_bytes(thr, len);
37973 break;
37974 case DUK_DBG_IB_UNUSED:
37976 case DUK_DBG_IB_NULL:
37977 case DUK_DBG_IB_TRUE:
37978 case DUK_DBG_IB_FALSE:
37979 break;
37980 case DUK_DBG_IB_NUMBER:
37981 duk_debug_skip_bytes(thr, 8);
37982 break;
37983 case DUK_DBG_IB_OBJECT:
37984 duk_debug_skip_byte(thr);
37985 len = duk_debug_read_byte(thr);
37986 duk_debug_skip_bytes(thr, len);
37987 break;
37988 case DUK_DBG_IB_POINTER:
37989 case DUK_DBG_IB_HEAPPTR:
37990 len = duk_debug_read_byte(thr);
37991 duk_debug_skip_bytes(thr, len);
37992 break;
37994 duk_debug_skip_bytes(thr, 2);
37995 len = duk_debug_read_byte(thr);
37996 duk_debug_skip_bytes(thr, len);
37997 break;
37998 default:
37999 goto fail;
38000 }
38001
38002 return 0;
38003
38004 fail:
38005 DUK__SET_CONN_BROKEN(thr, 1);
38006 return 1; /* Pretend like we got EOM */
38007}
38008
38009/* Skip dvalues to EOM. */
38010DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
38011 for (;;) {
38012 if (duk__debug_skip_dvalue(thr)) {
38013 break;
38014 }
38015 }
38016}
38017
38018/*
38019 * Simple commands
38020 */
38021
38022DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
38023 DUK_UNREF(heap);
38024 DUK_D(DUK_DPRINT("debug command Version"));
38025
38026 duk_debug_write_reply(thr);
38027 duk_debug_write_int(thr, DUK_VERSION);
38028 duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
38029 duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
38030#if defined(DUK_USE_DOUBLE_LE)
38031 duk_debug_write_int(thr, 1);
38032#elif defined(DUK_USE_DOUBLE_ME)
38033 duk_debug_write_int(thr, 2);
38034#elif defined(DUK_USE_DOUBLE_BE)
38035 duk_debug_write_int(thr, 3);
38036#else
38037 duk_debug_write_int(thr, 0);
38038#endif
38039 duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
38040 duk_debug_write_eom(thr);
38041}
38042
38043DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
38044 DUK_UNREF(heap);
38045 DUK_D(DUK_DPRINT("debug command TriggerStatus"));
38046
38047 duk_debug_write_reply(thr);
38048 duk_debug_write_eom(thr);
38049 heap->dbg_state_dirty = 1;
38050}
38051
38052DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
38053 DUK_D(DUK_DPRINT("debug command Pause"));
38054
38055 DUK_HEAP_SET_PAUSED(heap);
38056 duk_debug_write_reply(thr);
38057 duk_debug_write_eom(thr);
38058}
38059
38060DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
38061 DUK_D(DUK_DPRINT("debug command Resume"));
38062
38063 DUK_HEAP_CLEAR_PAUSED(heap);
38064 duk_debug_write_reply(thr);
38065 duk_debug_write_eom(thr);
38066}
38067
38068DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
38069 duk_small_uint_t step_type;
38070 duk_uint_fast32_t line;
38071
38072 DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
38073
38074 if (cmd == DUK_DBG_CMD_STEPINTO) {
38075 step_type = DUK_STEP_TYPE_INTO;
38076 } else if (cmd == DUK_DBG_CMD_STEPOVER) {
38077 step_type = DUK_STEP_TYPE_OVER;
38078 } else {
38080 step_type = DUK_STEP_TYPE_OUT;
38081 }
38082
38083 line = duk_debug_curr_line(thr);
38084 if (line > 0) {
38085 heap->dbg_paused = 0;
38086 heap->dbg_step_type = step_type;
38087 heap->dbg_step_thread = thr;
38088 heap->dbg_step_csindex = thr->callstack_top - 1;
38089 heap->dbg_step_startline = line;
38090 heap->dbg_state_dirty = 1;
38091 } else {
38092 DUK_D(DUK_DPRINT("cannot determine current line, stepinto/stepover/stepout ignored"));
38093 }
38094 duk_debug_write_reply(thr);
38095 duk_debug_write_eom(thr);
38096}
38097
38098DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
38100
38101 DUK_D(DUK_DPRINT("debug command ListBreak"));
38102 duk_debug_write_reply(thr);
38103 for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
38104 duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
38105 duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
38106 }
38107 duk_debug_write_eom(thr);
38108}
38109
38110DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
38111 duk_hstring *filename;
38112 duk_uint32_t linenumber;
38113 duk_small_int_t idx;
38114
38115 DUK_UNREF(heap);
38116
38117 filename = duk_debug_read_hstring(thr);
38118 linenumber = (duk_uint32_t) duk_debug_read_int(thr);
38119 DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
38120 idx = duk_debug_add_breakpoint(thr, filename, linenumber);
38121 if (idx >= 0) {
38122 duk_debug_write_reply(thr);
38123 duk_debug_write_int(thr, (duk_int32_t) idx);
38124 duk_debug_write_eom(thr);
38125 } else {
38126 duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
38127 }
38128}
38129
38130DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
38131 duk_small_uint_t idx;
38132
38133 DUK_UNREF(heap);
38134
38135 DUK_D(DUK_DPRINT("debug command DelBreak"));
38136 idx = (duk_small_uint_t) duk_debug_read_int(thr);
38137 if (duk_debug_remove_breakpoint(thr, idx)) {
38138 duk_debug_write_reply(thr);
38139 duk_debug_write_eom(thr);
38140 } else {
38141 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
38142 }
38143}
38144
38145DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
38146 duk_context *ctx = (duk_context *) thr;
38147 duk_hstring *str;
38148 duk_bool_t rc;
38149 duk_int32_t level;
38150
38151 DUK_UNREF(heap);
38152 DUK_D(DUK_DPRINT("debug command GetVar"));
38153
38154 str = duk_debug_read_hstring(thr); /* push to stack */
38155 DUK_ASSERT(str != NULL);
38156 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38157 level = duk_debug_read_int(thr); /* optional callstack level */
38158 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38159 DUK_D(DUK_DPRINT("invalid callstack level for GetVar"));
38160 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38161 return;
38162 }
38163 } else {
38164 level = -1;
38165 }
38166
38167 if (thr->callstack_top > 0) {
38168 rc = duk_js_getvar_activation(thr,
38169 thr->callstack + thr->callstack_top + level,
38170 str,
38171 0);
38172 } else {
38173 /* No activation, no variable access. Could also pretend
38174 * we're in the global program context and read stuff off
38175 * the global object.
38176 */
38177 DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore getvar"));
38178 rc = 0;
38179 }
38180
38181 duk_debug_write_reply(thr);
38182 if (rc) {
38183 duk_debug_write_int(thr, 1);
38184 DUK_ASSERT(duk_get_tval(ctx, -2) != NULL);
38185 duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
38186 } else {
38187 duk_debug_write_int(thr, 0);
38188 duk_debug_write_unused(thr);
38189 }
38190 duk_debug_write_eom(thr);
38191}
38192
38193DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
38194 duk_hstring *str;
38195 duk_tval *tv;
38196 duk_int32_t level;
38197
38198 DUK_UNREF(heap);
38199 DUK_D(DUK_DPRINT("debug command PutVar"));
38200
38201 str = duk_debug_read_hstring(thr); /* push to stack */
38202 DUK_ASSERT(str != NULL);
38203 tv = duk_debug_read_tval(thr);
38204 if (tv == NULL) {
38205 /* detached */
38206 return;
38207 }
38208 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38209 level = duk_debug_read_int(thr); /* optional callstack level */
38210 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38211 DUK_D(DUK_DPRINT("invalid callstack level for PutVar"));
38212 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38213 return;
38214 }
38215 } else {
38216 level = -1;
38217 }
38218
38219 if (thr->callstack_top > 0) {
38221 thr->callstack + thr->callstack_top + level,
38222 str,
38223 tv,
38224 0);
38225 } else {
38226 DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore putvar"));
38227 }
38228
38229 /* XXX: Current putvar implementation doesn't have a success flag,
38230 * add one and send to debug client?
38231 */
38232 duk_debug_write_reply(thr);
38233 duk_debug_write_eom(thr);
38234}
38235
38236DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
38237 duk_context *ctx = (duk_context *) thr;
38238 duk_hthread *curr_thr = thr;
38239 duk_activation *curr_act;
38241 duk_uint_fast32_t line;
38242 duk_size_t i;
38243
38244 DUK_ASSERT(thr != NULL);
38245 DUK_UNREF(heap);
38246
38247 duk_debug_write_reply(thr);
38248 while (curr_thr != NULL) {
38249 i = curr_thr->callstack_top;
38250 while (i > 0) {
38251 i--;
38252 curr_act = curr_thr->callstack + i;
38253
38254 /* PC/line semantics here are:
38255 * - For callstack top we're conceptually between two
38256 * opcodes and current PC indicates next line to
38257 * execute, so report that (matches Status).
38258 * - For other activations we're conceptually still
38259 * executing the instruction at PC-1, so report that
38260 * (matches error stacktrace behavior).
38261 * - See: https://github.com/svaarala/duktape/issues/281
38262 */
38263
38264 /* XXX: optimize to use direct reads, i.e. avoid
38265 * value stack operations.
38266 */
38267 duk_push_tval(ctx, &curr_act->tv_func);
38269 duk__debug_write_hstring_safe_top(thr);
38271 duk__debug_write_hstring_safe_top(thr);
38272 pc = duk_hthread_get_act_curr_pc(thr, curr_act);
38273 if (i != curr_thr->callstack_top - 1 && pc > 0) {
38274 pc--;
38275 }
38276 line = duk_hobject_pc2line_query(ctx, -3, pc);
38277 duk_debug_write_uint(thr, (duk_uint32_t) line);
38278 duk_debug_write_uint(thr, (duk_uint32_t) pc);
38279 duk_pop_3(ctx);
38280 }
38281 curr_thr = curr_thr->resumer;
38282 }
38283 /* SCANBUILD: warning about 'thr' potentially being NULL here,
38284 * warning is incorrect because thr != NULL always here.
38285 */
38286 duk_debug_write_eom(thr);
38287}
38288
38289DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
38290 duk_context *ctx = (duk_context *) thr;
38291 duk_activation *curr_act;
38292 duk_int32_t level;
38293 duk_hstring *varname;
38294
38295 DUK_UNREF(heap);
38296
38297 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38298 level = duk_debug_read_int(thr); /* optional callstack level */
38299 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38300 DUK_D(DUK_DPRINT("invalid callstack level for GetLocals"));
38301 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38302 return;
38303 }
38304 duk_debug_write_reply(thr);
38305 } else {
38306 duk_debug_write_reply(thr);
38307 if (thr->callstack_top == 0) {
38308 goto callstack_empty;
38309 }
38310 level = -1;
38311 }
38312
38313 curr_act = thr->callstack + thr->callstack_top + level;
38314
38315 /* XXX: several nice-to-have improvements here:
38316 * - Use direct reads avoiding value stack operations
38317 * - Avoid triggering getters, indicate getter values to debug client
38318 * - If side effects are possible, add error catching
38319 */
38320
38321 duk_push_tval(ctx, &curr_act->tv_func);
38323 if (duk_is_object(ctx, -1)) {
38324 duk_enum(ctx, -1, 0 /*enum_flags*/);
38325 while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
38326 varname = duk_get_hstring(ctx, -1);
38327 DUK_ASSERT(varname != NULL);
38328
38329 duk_js_getvar_activation(thr, curr_act, varname, 0 /*throw_flag*/);
38330 /* [ ... func varmap enum key value this ] */
38331 duk_debug_write_hstring(thr, duk_get_hstring(ctx, -3));
38332 duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
38333 duk_pop_3(ctx); /* -> [ ... func varmap enum ] */
38334 }
38335 } else {
38336 DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
38337 }
38338
38339 callstack_empty:
38340 duk_debug_write_eom(thr);
38341}
38342
38343DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
38344 duk_context *ctx = (duk_context *) thr;
38345 duk_small_uint_t call_flags;
38346 duk_int_t call_ret;
38347 duk_small_int_t eval_err;
38348 duk_int32_t level;
38349
38350 DUK_UNREF(heap);
38351
38352 DUK_D(DUK_DPRINT("debug command Eval"));
38353
38354 /* The eval code is executed within the lexical environment of a specified
38355 * activation. For now, use global object eval() function, with the eval
38356 * considered a 'direct call to eval'.
38357 *
38358 * Callstack level for debug commands only affects scope -- the callstack
38359 * as seen by, e.g. Duktape.act() will be the same regardless.
38360 */
38361
38362 /* nargs == 2 so we can pass a callstack level to eval(). */
38364 duk_push_undefined(ctx); /* 'this' binding shouldn't matter here */
38365
38366 (void) duk_debug_read_hstring(thr);
38367 if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38368 level = duk_debug_read_int(thr); /* optional callstack level */
38369 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38370 DUK_D(DUK_DPRINT("invalid callstack level for Eval"));
38371 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38372 return;
38373 }
38374 }
38375 else {
38376 level = -1;
38377 }
38378 DUK_ASSERT(level < 0 && -level <= (duk_int32_t) thr->callstack_top);
38379 duk_push_int(ctx, level - 1); /* compensate for eval() call */
38380
38381 /* [ ... eval "eval" eval_input level ] */
38382
38383 call_flags = 0;
38384 if (thr->callstack_top >= (duk_size_t) -level) {
38385 duk_activation *act;
38386 duk_hobject *fun;
38387
38388 act = thr->callstack + thr->callstack_top + level;
38389 fun = DUK_ACT_GET_FUNC(act);
38390 if (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(fun)) {
38391 /* Direct eval requires that there's a current
38392 * activation and it is an Ecmascript function.
38393 * When Eval is executed from e.g. cooperate API
38394 * call we'll need to do an indirect eval instead.
38395 */
38396 call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
38397 }
38398 }
38399
38400 call_ret = duk_handle_call_protected(thr, 2 /*num_stack_args*/, call_flags);
38401
38402 if (call_ret == DUK_EXEC_SUCCESS) {
38403 eval_err = 0;
38404 /* Use result value as is. */
38405 } else {
38406 /* For errors a string coerced result is most informative
38407 * right now, as the debug client doesn't have the capability
38408 * to traverse the error object.
38409 */
38410 eval_err = 1;
38411 duk_safe_to_string(ctx, -1);
38412 }
38413
38414 /* [ ... result ] */
38415
38416 duk_debug_write_reply(thr);
38417 duk_debug_write_int(thr, (duk_int32_t) eval_err);
38418 DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
38419 duk_debug_write_tval(thr, duk_get_tval(ctx, -1));
38420 duk_debug_write_eom(thr);
38421}
38422
38423DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
38424 DUK_UNREF(heap);
38425 DUK_D(DUK_DPRINT("debug command Detach"));
38426
38427 duk_debug_write_reply(thr);
38428 duk_debug_write_eom(thr);
38429
38430 DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
38431 DUK__SET_CONN_BROKEN(thr, 0); /* not an error */
38432}
38433
38434DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
38435 duk_context *ctx = (duk_context *) thr;
38436 duk_idx_t old_top;
38437
38438 DUK_D(DUK_DPRINT("debug command AppRequest"));
38439
38440 old_top = duk_get_top(ctx); /* save stack top */
38441
38442 if (heap->dbg_request_cb != NULL) {
38443 duk_idx_t nrets;
38444 duk_idx_t nvalues = 0;
38445 duk_idx_t top, idx;
38446
38447 /* Read tvals from the message and push them onto the valstack,
38448 * then call the request callback to process the request.
38449 */
38450 while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38451 duk_tval *tv;
38452 if (!duk_check_stack(ctx, 1)) {
38453 DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
38454 goto fail;
38455 }
38456 tv = duk_debug_read_tval(thr); /* push to stack */
38457 if (tv == NULL) {
38458 /* detached */
38459 return;
38460 }
38461 nvalues++;
38462 }
38463 DUK_ASSERT(duk_get_top(ctx) == old_top + nvalues);
38464
38465 /* Request callback should push values for reply to client onto valstack */
38466 DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
38467 (long) nvalues, (long) old_top, (long) duk_get_top(ctx)));
38468 nrets = heap->dbg_request_cb(ctx, heap->dbg_udata, nvalues);
38469 DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
38470 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(ctx)));
38471 if (nrets >= 0) {
38472 DUK_ASSERT(duk_get_top(ctx) >= old_top + nrets);
38473 if (duk_get_top(ctx) < old_top + nrets) {
38474 DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
38475 "top=%ld < old_top=%ld + nrets=%ld; "
38476 "this might mean it's unsafe to continue!",
38477 (long) duk_get_top(ctx), (long) old_top, (long) nrets));
38478 goto fail;
38479 }
38480
38481 /* Reply with tvals pushed by request callback */
38482 duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
38483 top = duk_get_top(ctx);
38484 for (idx = top - nrets; idx < top; idx++) {
38485 duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(ctx, idx));
38486 }
38487 duk_debug_write_eom(thr);
38488 } else {
38489 DUK_ASSERT(duk_get_top(ctx) >= old_top + 1);
38490 if (duk_get_top(ctx) < old_top + 1) {
38491 DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
38492 goto fail;
38493 }
38494 duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(ctx, -1));
38495 }
38496
38497 duk_set_top(ctx, old_top); /* restore stack top */
38498 } else {
38499 DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
38500 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
38501 }
38502
38503 return;
38504
38505 fail:
38506 duk_set_top(ctx, old_top); /* restore stack top */
38507 DUK__SET_CONN_BROKEN(thr, 1);
38508}
38509
38510/*
38511 * DumpHeap command
38512 */
38513
38514#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
38515/* XXX: this has some overlap with object inspection; remove this and make
38516 * DumpHeap return lists of heapptrs instead?
38517 */
38518DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
38519 DUK_UNREF(heap);
38520
38521 duk_debug_write_heapptr(thr, hdr);
38522 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
38523 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
38524#if defined(DUK_USE_REFERENCE_COUNTING)
38525 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
38526#else
38527 duk_debug_write_int(thr, (duk_int32_t) -1);
38528#endif
38529
38530 switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
38531 case DUK_HTYPE_STRING: {
38532 duk_hstring *h = (duk_hstring *) hdr;
38533
38534 duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_BYTELEN(h));
38535 duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_CHARLEN(h));
38536 duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_HASH(h));
38537 duk_debug_write_hstring(thr, h);
38538 break;
38539 }
38540 case DUK_HTYPE_OBJECT: {
38541 duk_hobject *h = (duk_hobject *) hdr;
38542 duk_hstring *k;
38544
38545 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
38546 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
38547 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
38548 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
38549 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
38550 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
38551
38552 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
38553 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
38554 k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
38555 duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
38556 if (k == NULL) {
38557 duk_debug_write_int(thr, 0); /* isAccessor */
38558 duk_debug_write_unused(thr);
38559 continue;
38560 }
38561 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
38562 duk_debug_write_int(thr, 1); /* isAccessor */
38563 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
38564 duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
38565 } else {
38566 duk_debug_write_int(thr, 0); /* isAccessor */
38567
38568 duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
38569 }
38570 }
38571
38572 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
38573 /* Note: array dump will include elements beyond
38574 * 'length'.
38575 */
38576 duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
38577 }
38578 break;
38579 }
38580 case DUK_HTYPE_BUFFER: {
38581 duk_hbuffer *h = (duk_hbuffer *) hdr;
38582
38583 duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
38584 duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
38585 break;
38586 }
38587 default: {
38588 DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
38589 }
38590 }
38591}
38592
38593DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
38594 duk_heaphdr *hdr;
38595
38596 hdr = heap->heap_allocated;
38597 while (hdr != NULL) {
38598 duk__debug_dump_heaphdr(thr, heap, hdr);
38599 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
38600 }
38601}
38602
38603#if defined(DUK_USE_STRTAB_CHAIN)
38604DUK_LOCAL void duk__debug_dump_strtab_chain(duk_hthread *thr, duk_heap *heap) {
38605 duk_uint_fast32_t i, j;
38607#if defined(DUK_USE_HEAPPTR16)
38608 duk_uint16_t *lst;
38609#else
38610 duk_hstring **lst;
38611#endif
38612 duk_hstring *h;
38613
38614 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
38615 e = heap->strtable + i;
38616 if (e->listlen > 0) {
38617#if defined(DUK_USE_HEAPPTR16)
38618 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
38619#else
38620 lst = e->u.strlist;
38621#endif
38622 DUK_ASSERT(lst != NULL);
38623
38624 for (j = 0; j < e->listlen; j++) {
38625#if defined(DUK_USE_HEAPPTR16)
38626 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
38627#else
38628 h = lst[j];
38629#endif
38630 if (h != NULL) {
38631 duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38632 }
38633 }
38634 } else {
38635#if defined(DUK_USE_HEAPPTR16)
38636 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
38637#else
38638 h = e->u.str;
38639#endif
38640 if (h != NULL) {
38641 duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38642 }
38643 }
38644 }
38645}
38646#endif /* DUK_USE_STRTAB_CHAIN */
38647
38648#if defined(DUK_USE_STRTAB_PROBE)
38649DUK_LOCAL void duk__debug_dump_strtab_probe(duk_hthread *thr, duk_heap *heap) {
38650 duk_uint32_t i;
38651 duk_hstring *h;
38652
38653 for (i = 0; i < heap->st_size; i++) {
38654#if defined(DUK_USE_HEAPPTR16)
38655 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
38656#else
38657 h = heap->strtable[i];
38658#endif
38659 if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
38660 continue;
38661 }
38662
38663 duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38664 }
38665}
38666#endif /* DUK_USE_STRTAB_PROBE */
38667
38668DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
38669 DUK_D(DUK_DPRINT("debug command DumpHeap"));
38670
38671 duk_debug_write_reply(thr);
38672 duk__debug_dump_heap_allocated(thr, heap);
38673#if defined(DUK_USE_STRTAB_CHAIN)
38674 duk__debug_dump_strtab_chain(thr, heap);
38675#endif
38676#if defined(DUK_USE_STRTAB_PROBE)
38677 duk__debug_dump_strtab_probe(thr, heap);
38678#endif
38679 duk_debug_write_eom(thr);
38680}
38681#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
38682
38683DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
38684 duk_activation *act;
38686 duk_size_t i, n;
38687 duk_tval *tv;
38688 duk_hobject **fn;
38689 duk_int32_t level = -1;
38690 duk_uint8_t ibyte;
38691
38692 DUK_UNREF(heap);
38693
38694 DUK_D(DUK_DPRINT("debug command GetBytecode"));
38695
38696 ibyte = duk_debug_peek_byte(thr);
38697 if (ibyte != DUK_DBG_IB_EOM) {
38698 tv = duk_debug_read_tval(thr);
38699 if (tv == NULL) {
38700 /* detached */
38701 return;
38702 }
38703 if (DUK_TVAL_IS_OBJECT(tv)) {
38704 /* tentative, checked later */
38706 DUK_ASSERT(fun != NULL);
38707 } else if (DUK_TVAL_IS_NUMBER(tv)) {
38708 level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
38709 } else {
38710 DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
38711 goto fail_args;
38712 }
38713 }
38714
38715 if (fun == NULL) {
38716 if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38717 DUK_D(DUK_DPRINT("invalid callstack level for GetBytecode"));
38718 goto fail_level;
38719 }
38720 act = thr->callstack + thr->callstack_top + level;
38722 }
38723
38724 if (fun == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)) {
38725 DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
38726 goto fail_args;
38727 }
38729
38730 duk_debug_write_reply(thr);
38732 duk_debug_write_int(thr, (duk_int32_t) n);
38734 for (i = 0; i < n; i++) {
38735 duk_debug_write_tval(thr, tv);
38736 tv++;
38737 }
38739 duk_debug_write_int(thr, (duk_int32_t) n);
38741 for (i = 0; i < n; i++) {
38742 duk_debug_write_hobject(thr, *fn);
38743 fn++;
38744 }
38745 duk_debug_write_string(thr,
38746 (const char *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap, fun),
38748 duk_debug_write_eom(thr);
38749 return;
38750
38751 fail_args:
38752 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
38753 return;
38754
38755 fail_level:
38756 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38757 return;
38758}
38759
38760/*
38761 * Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
38762 * GetObjPropDescRange
38763 */
38764
38765#if defined(DUK_USE_DEBUGGER_INSPECT)
38766
38767#if 0 /* pruned */
38768DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
38769 "reachable",
38770 "temproot",
38771 "finalizable",
38772 "finalized",
38773 "readonly"
38774 /* NULL not needed here */
38775};
38776DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
38782 0 /* terminator */
38783};
38784#endif
38785DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
38786#if 0
38787 "arridx",
38788 "internal",
38789 "reserved_word",
38790 "strict_reserved_word",
38791 "eval_or_arguments",
38792#endif
38793 "extdata"
38794 /* NULL not needed here */
38795};
38796DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
38797#if 0
38803#endif
38805 0 /* terminator */
38806};
38807DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
38808 "extensible",
38809 "constructable",
38810 "bound",
38811 "compiledfunction",
38812 "nativefunction",
38813 "bufferobject",
38814 "thread",
38815 "array_part",
38816 "strict",
38817 "notail",
38818 "newenv",
38819 "namebinding",
38820 "createargs",
38821 "envrecclosed",
38822 "exotic_array",
38823 "exotic_stringobj",
38824 "exotic_arguments",
38825 "exotic_dukfunc",
38826 "exotic_proxyobj"
38827 /* NULL not needed here */
38828};
38829DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
38849 0 /* terminator */
38850};
38851DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
38852 "dynamic",
38853 "external"
38854 /* NULL not needed here */
38855};
38856DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
38859 0 /* terminator */
38860};
38861
38862DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
38863 duk_debug_write_uint(thr, 0);
38864 duk_debug_write_cstring(thr, key);
38865}
38866
38867DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
38868 duk_debug_write_uint(thr, 0);
38869 duk_debug_write_cstring(thr, key);
38870 duk_debug_write_uint(thr, val);
38871}
38872
38873DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
38874 duk_debug_write_uint(thr, 0);
38875 duk_debug_write_cstring(thr, key);
38876 duk_debug_write_int(thr, val);
38877}
38878
38879DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
38880 duk_debug_write_uint(thr, 0);
38881 duk_debug_write_cstring(thr, key);
38882 duk_debug_write_boolean(thr, val);
38883}
38884
38885DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
38886 const char *key;
38888
38889 for (;;) {
38890 mask = *masks++;
38891 if (!mask) {
38892 break;
38893 }
38894 key = *keys++;
38895 DUK_ASSERT(key != NULL);
38896
38897 DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
38898 duk__debug_getinfo_prop_bool(thr, key, flags & mask);
38899 }
38900}
38901
38902/* Inspect a property using a virtual index into a conceptual property list
38903 * consisting of (1) all array part items from [0,a_size[ (even when above
38904 * .length) and (2) all entry part items from [0,e_next[. Unused slots are
38905 * indicated using dvalue 'unused'.
38906 */
38907DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
38908 duk_uint_t a_size;
38909 duk_tval *tv;
38910 duk_hstring *h_key;
38911 duk_hobject *h_getset;
38912 duk_uint_t flags;
38913
38914 DUK_UNREF(heap);
38915
38916 a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
38917 if (idx < a_size) {
38918 duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
38919 duk_debug_write_uint(thr, idx);
38920 tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
38921 duk_debug_write_tval(thr, tv);
38922 return 1;
38923 }
38924
38925 idx -= a_size;
38926 if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
38927 return 0;
38928 }
38929
38930 h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
38931 if (h_key == NULL) {
38932 duk_debug_write_uint(thr, 0);
38933 duk_debug_write_null(thr);
38934 duk_debug_write_unused(thr);
38935 return 1;
38936 }
38937
38938 flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
38939 if (DUK_HSTRING_HAS_INTERNAL(h_key)) {
38941 }
38942 duk_debug_write_uint(thr, flags);
38943 duk_debug_write_hstring(thr, h_key);
38944 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
38945 h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
38946 if (h_getset) {
38947 duk_debug_write_hobject(thr, h_getset);
38948 } else {
38949 duk_debug_write_null(thr);
38950 }
38951 h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
38952 if (h_getset) {
38953 duk_debug_write_hobject(thr, h_getset);
38954 } else {
38955 duk_debug_write_null(thr);
38956 }
38957 } else {
38958 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
38959 duk_debug_write_tval(thr, tv);
38960 }
38961 return 1;
38962}
38963
38964DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
38965 duk_heaphdr *h;
38966
38967 DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
38968 DUK_UNREF(heap);
38969
38970 h = duk_debug_read_any_ptr(thr);
38971 if (!h) {
38972 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
38973 return;
38974 }
38975
38976 duk_debug_write_reply(thr);
38977
38978 /* As with all inspection code, we rely on the debug client providing
38979 * a valid, non-stale pointer: there's no portable way to safely
38980 * validate the pointer here.
38981 */
38982
38983 duk__debug_getinfo_flags_key(thr, "heapptr");
38984 duk_debug_write_heapptr(thr, h);
38985
38986 /* XXX: comes out as signed now */
38987 duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
38988 duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
38989#if defined(DUK_USE_REFERENCE_COUNTING)
38990 duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
38991#endif
38992#if 0 /* pruned */
38993 duk__debug_getinfo_bitmask(thr,
38994 duk__debug_getinfo_heaphdr_keys,
38995 duk__debug_getinfo_heaphdr_masks,
38997#endif
38998
38999 switch (DUK_HEAPHDR_GET_TYPE(h)) {
39000 case DUK_HTYPE_STRING: {
39001 duk_hstring *h_str;
39002
39003 h_str = (duk_hstring *) h;
39004 duk__debug_getinfo_bitmask(thr,
39005 duk__debug_getinfo_hstring_keys,
39006 duk__debug_getinfo_hstring_masks,
39008 duk__debug_getinfo_prop_uint(thr, "bytelen", DUK_HSTRING_GET_BYTELEN(h_str));
39009 duk__debug_getinfo_prop_uint(thr, "charlen", DUK_HSTRING_GET_CHARLEN(h_str));
39010 duk__debug_getinfo_prop_uint(thr, "hash", DUK_HSTRING_GET_HASH(h_str));
39011 duk__debug_getinfo_flags_key(thr, "data");
39012 duk_debug_write_hstring(thr, h_str);
39013 break;
39014 }
39015 case DUK_HTYPE_OBJECT: {
39016 duk_hobject *h_obj;
39017 duk_hobject *h_proto;
39018
39019 h_obj = (duk_hobject *) h;
39020 h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
39021
39022 /* duk_hobject specific fields. */
39023 duk__debug_getinfo_bitmask(thr,
39024 duk__debug_getinfo_hobject_keys,
39025 duk__debug_getinfo_hobject_masks,
39027 duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
39028 duk__debug_getinfo_flags_key(thr, "class_name");
39029 duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
39030 duk__debug_getinfo_flags_key(thr, "prototype");
39031 if (h_proto != NULL) {
39032 duk_debug_write_hobject(thr, h_proto);
39033 } else {
39034 duk_debug_write_null(thr);
39035 }
39036 duk__debug_getinfo_flags_key(thr, "props");
39037 duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
39038 duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
39039 duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
39040 duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
39041 duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
39042
39043 /* duk_hnativefunction specific fields. */
39044 if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
39045 duk_hnativefunction *h_fun;
39046 h_fun = (duk_hnativefunction *) h_obj;
39047
39048 duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
39049 duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
39050 duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATIVEFUNCTION_NARGS_VARARGS);
39051 /* Native function pointer may be different from a void pointer,
39052 * and we serialize it from memory directly now (no byte swapping etc).
39053 */
39054 duk__debug_getinfo_flags_key(thr, "funcptr");
39055 duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
39056 }
39057
39059 duk_hcompiledfunction *h_fun;
39060 duk_hbuffer *h_buf;
39061 h_fun = (duk_hcompiledfunction *) h_obj;
39062
39063 duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
39064 duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
39065 duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
39066 duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
39067 h_buf = (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun);
39068 if (h_buf != NULL) {
39069 duk__debug_getinfo_flags_key(thr, "data");
39070 duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
39071 }
39072 }
39073
39074 if (DUK_HOBJECT_IS_THREAD(h_obj)) {
39075 /* XXX: Currently no inspection of threads, e.g. value stack, call
39076 * stack, catch stack, etc.
39077 */
39078 duk_hthread *h_thr;
39079 h_thr = (duk_hthread *) h_obj;
39080 DUK_UNREF(h_thr);
39081 }
39082
39083 if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
39084 duk_hbufferobject *h_bufobj;
39085 h_bufobj = (duk_hbufferobject *) h_obj;
39086
39087 duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
39088 duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
39089 duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
39090 duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
39091 duk__debug_getinfo_prop_bool(thr, "is_view", (duk_uint_t) h_bufobj->is_view);
39092 if (h_bufobj->buf != NULL) {
39093 duk__debug_getinfo_flags_key(thr, "buffer");
39094 duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
39095 }
39096 }
39097 break;
39098 }
39099 case DUK_HTYPE_BUFFER: {
39100 duk_hbuffer *h_buf;
39101
39102 h_buf = (duk_hbuffer *) h;
39103 duk__debug_getinfo_bitmask(thr,
39104 duk__debug_getinfo_hbuffer_keys,
39105 duk__debug_getinfo_hbuffer_masks,
39107 duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
39108 duk__debug_getinfo_flags_key(thr, "dataptr");
39109 duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
39110 duk__debug_getinfo_flags_key(thr, "data");
39111 duk_debug_write_hbuffer(thr, h_buf); /* tolerates NULL h_buf */
39112 break;
39113 }
39114 default: {
39115 /* Since we already started writing the reply, just emit nothing. */
39116 DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
39117 }
39118 }
39119
39120 duk_debug_write_eom(thr);
39121}
39122
39123DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
39124 duk_heaphdr *h;
39125 duk_hobject *h_obj;
39126 duk_hstring *h_key;
39127 duk_propdesc desc;
39128
39129 DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
39130 DUK_UNREF(heap);
39131
39132 h = duk_debug_read_any_ptr(thr);
39133 if (!h) {
39134 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
39135 return;
39136 }
39137 h_key = duk_debug_read_hstring(thr);
39138 if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
39139 goto fail_args;
39140 }
39141 h_obj = (duk_hobject *) h;
39142
39143 if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
39144 duk_int_t virtual_idx;
39145 duk_bool_t rc;
39146
39147 /* To use the shared helper need the virtual index. */
39148 DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
39149 virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
39150 (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
39151
39152 duk_debug_write_reply(thr);
39153 rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
39154 DUK_ASSERT(rc == 1);
39155 DUK_UNREF(rc);
39156 duk_debug_write_eom(thr);
39157 } else {
39158 duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
39159 }
39160 return;
39161
39162 fail_args:
39163 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
39164}
39165
39166DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
39167 duk_heaphdr *h;
39168 duk_hobject *h_obj;
39169 duk_uint_t idx, idx_start, idx_end;
39170
39171 DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
39172 DUK_UNREF(heap);
39173
39174 h = duk_debug_read_any_ptr(thr);
39175 idx_start = duk_debug_read_int(thr);
39176 idx_end = duk_debug_read_int(thr);
39177 if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
39178 goto fail_args;
39179 }
39180 h_obj = (duk_hobject *) h;
39181
39182 /* The index range space is conceptually the array part followed by the
39183 * entry part. Unlike normal enumeration all slots are exposed here as
39184 * is and return 'unused' if the slots are not in active use. In particular
39185 * the array part is included for the full a_size regardless of what the
39186 * array .length is.
39187 */
39188
39189 duk_debug_write_reply(thr);
39190 for (idx = idx_start; idx < idx_end; idx++) {
39191 if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
39192 break;
39193 }
39194 }
39195 duk_debug_write_eom(thr);
39196 return;
39197
39198 fail_args:
39199 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
39200}
39201
39202#endif /* DUK_USE_DEBUGGER_INSPECT */
39203
39204/*
39205 * Process incoming debug requests
39206 *
39207 * Individual request handlers can push temporaries on the value stack and
39208 * rely on duk__debug_process_message() to restore the value stack top
39209 * automatically.
39210 */
39211
39212/* Process one debug message. Automatically restore value stack top to its
39213 * entry value, so that individual message handlers don't need exact value
39214 * stack handling which is convenient.
39215 */
39216DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
39217 duk_context *ctx = (duk_context *) thr;
39218 duk_heap *heap;
39219 duk_uint8_t x;
39220 duk_int32_t cmd;
39221 duk_idx_t entry_top;
39222
39223 DUK_ASSERT(thr != NULL);
39224 heap = thr->heap;
39225 DUK_ASSERT(heap != NULL);
39226 DUK_UNREF(ctx);
39227
39228 entry_top = duk_get_top(ctx);
39229
39230 x = duk_debug_read_byte(thr);
39231 switch (x) {
39232 case DUK_DBG_IB_REQUEST: {
39233 cmd = duk_debug_read_int(thr);
39234 switch (cmd) {
39235 case DUK_DBG_CMD_BASICINFO: {
39236 duk__debug_handle_basic_info(thr, heap);
39237 break;
39238 }
39240 duk__debug_handle_trigger_status(thr, heap);
39241 break;
39242 }
39243 case DUK_DBG_CMD_PAUSE: {
39244 duk__debug_handle_pause(thr, heap);
39245 break;
39246 }
39247 case DUK_DBG_CMD_RESUME: {
39248 duk__debug_handle_resume(thr, heap);
39249 break;
39250 }
39253 case DUK_DBG_CMD_STEPOUT: {
39254 duk__debug_handle_step(thr, heap, cmd);
39255 break;
39256 }
39257 case DUK_DBG_CMD_LISTBREAK: {
39258 duk__debug_handle_list_break(thr, heap);
39259 break;
39260 }
39261 case DUK_DBG_CMD_ADDBREAK: {
39262 duk__debug_handle_add_break(thr, heap);
39263 break;
39264 }
39265 case DUK_DBG_CMD_DELBREAK: {
39266 duk__debug_handle_del_break(thr, heap);
39267 break;
39268 }
39269 case DUK_DBG_CMD_GETVAR: {
39270 duk__debug_handle_get_var(thr, heap);
39271 break;
39272 }
39273 case DUK_DBG_CMD_PUTVAR: {
39274 duk__debug_handle_put_var(thr, heap);
39275 break;
39276 }
39278 duk__debug_handle_get_call_stack(thr, heap);
39279 break;
39280 }
39281 case DUK_DBG_CMD_GETLOCALS: {
39282 duk__debug_handle_get_locals(thr, heap);
39283 break;
39284 }
39285 case DUK_DBG_CMD_EVAL: {
39286 duk__debug_handle_eval(thr, heap);
39287 break;
39288 }
39289 case DUK_DBG_CMD_DETACH: {
39290 /* The actual detached_cb call is postponed to message loop so
39291 * we don't need any special precautions here (just skip to EOM
39292 * on the already closed connection).
39293 */
39294 duk__debug_handle_detach(thr, heap);
39295 break;
39296 }
39297#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
39298 case DUK_DBG_CMD_DUMPHEAP: {
39299 duk__debug_handle_dump_heap(thr, heap);
39300 break;
39301 }
39302#endif /* DUK_USE_DEBUGGER_DUMPHEAP */
39304 duk__debug_handle_get_bytecode(thr, heap);
39305 break;
39306 }
39308 duk__debug_handle_apprequest(thr, heap);
39309 break;
39310 }
39311#if defined(DUK_USE_DEBUGGER_INSPECT)
39313 duk__debug_handle_get_heap_obj_info(thr, heap);
39314 break;
39315 }
39317 duk__debug_handle_get_obj_prop_desc(thr, heap);
39318 break;
39319 }
39321 duk__debug_handle_get_obj_prop_desc_range(thr, heap);
39322 break;
39323 }
39324#endif /* DUK_USE_DEBUGGER_INSPECT */
39325 default: {
39326 DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
39327 duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
39328 }
39329 } /* switch cmd */
39330 break;
39331 }
39332 case DUK_DBG_IB_REPLY: {
39333 DUK_D(DUK_DPRINT("debug reply, skipping"));
39334 break;
39335 }
39336 case DUK_DBG_IB_ERROR: {
39337 DUK_D(DUK_DPRINT("debug error, skipping"));
39338 break;
39339 }
39340 case DUK_DBG_IB_NOTIFY: {
39341 DUK_D(DUK_DPRINT("debug notify, skipping"));
39342 break;
39343 }
39344 default: {
39345 DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
39346 goto fail;
39347 }
39348 } /* switch initial byte */
39349
39350 DUK_ASSERT(duk_get_top(ctx) >= entry_top);
39351 duk_set_top(ctx, entry_top);
39352 duk__debug_skip_to_eom(thr);
39353 return;
39354
39355 fail:
39356 DUK_ASSERT(duk_get_top(ctx) >= entry_top);
39357 duk_set_top(ctx, entry_top);
39358 DUK__SET_CONN_BROKEN(thr, 1);
39359 return;
39360}
39361
39362DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
39363 if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
39364 duk_debug_send_status(thr);
39365 thr->heap->dbg_state_dirty = 0;
39366 }
39367}
39368
39369DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
39370 duk_context *ctx = (duk_context *) thr;
39371#if defined(DUK_USE_ASSERTIONS)
39372 duk_idx_t entry_top;
39373#endif
39374 duk_bool_t retval = 0;
39375
39376 DUK_ASSERT(thr != NULL);
39377 DUK_UNREF(ctx);
39378 DUK_ASSERT(thr->heap != NULL);
39379#if defined(DUK_USE_ASSERTIONS)
39380 entry_top = duk_get_top(ctx);
39381#endif
39382
39383 DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
39384 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
39385 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
39386 DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(ctx)));
39387
39388 /* thr->heap->dbg_detaching may be != 0 if a debugger write outside
39389 * the message loop caused a transport error and detach1() to run.
39390 */
39391 DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
39392 DUK_ASSERT(thr->heap->dbg_processing == 0);
39393 thr->heap->dbg_processing = 1;
39394
39395 /* Ensure dirty state causes a Status even if never process any
39396 * messages. This is expected by the bytecode executor when in
39397 * the running state.
39398 */
39399 duk__check_resend_status(thr);
39400
39401 for (;;) {
39402 /* Process messages until we're no longer paused or we peek
39403 * and see there's nothing to read right now.
39404 */
39405 DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(ctx)));
39406 DUK_ASSERT(thr->heap->dbg_processing == 1);
39407
39408 while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
39409 /* Detach is pending; can be triggered from outside the
39410 * debugger loop (e.g. Status notify write error) or by
39411 * previous message handling. Call detached callback
39412 * here, in a controlled state, to ensure a possible
39413 * reattach inside the detached_cb is handled correctly.
39414 *
39415 * Recheck for detach in a while loop: an immediate
39416 * reattach involves a call to duk_debugger_attach()
39417 * which writes a debugger handshake line immediately
39418 * inside the API call. If the transport write fails
39419 * for that handshake, we can immediately end up in a
39420 * "transport broken, detaching" case several times here.
39421 * Loop back until we're either cleanly attached or
39422 * fully detached.
39423 *
39424 * NOTE: Reset dbg_processing = 1 forcibly, in case we
39425 * re-attached; duk_debugger_attach() sets dbg_processing
39426 * to 0 at the moment.
39427 */
39428
39429 DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
39430
39431 duk__debug_do_detach2(thr->heap);
39432 thr->heap->dbg_processing = 1; /* may be set to 0 by duk_debugger_attach() inside callback */
39433
39434 DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
39435 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
39436 }
39437 DUK_ASSERT(thr->heap->dbg_detaching == 0); /* true even with reattach */
39438 DUK_ASSERT(thr->heap->dbg_processing == 1); /* even after a detach and possible reattach */
39439
39440 if (thr->heap->dbg_read_cb == NULL) {
39441 DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
39442 break;
39443 }
39444
39445 if (!thr->heap->dbg_paused || no_block) {
39446 if (!duk_debug_read_peek(thr)) {
39447 /* Note: peek cannot currently trigger a detach
39448 * so the dbg_detaching == 0 assert outside the
39449 * loop is correct.
39450 */
39451 DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
39452 break;
39453 }
39454 DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
39455 } else {
39456 DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
39457 }
39458
39459 duk__check_resend_status(thr);
39460 duk__debug_process_message(thr);
39461 duk__check_resend_status(thr);
39462
39463 retval = 1; /* processed one or more messages */
39464 }
39465
39466 DUK_ASSERT(thr->heap->dbg_detaching == 0);
39467 DUK_ASSERT(thr->heap->dbg_processing == 1);
39468 thr->heap->dbg_processing = 0;
39469
39470 /* As an initial implementation, read flush after exiting the message
39471 * loop. If transport is broken, this is a no-op (with debug logs).
39472 */
39473 duk_debug_read_flush(thr); /* this cannot initiate a detach */
39474 DUK_ASSERT(thr->heap->dbg_detaching == 0);
39475
39476 DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(ctx)));
39477
39478#if defined(DUK_USE_ASSERTIONS)
39479 /* Easy to get wrong, so assert for it. */
39480 DUK_ASSERT(entry_top == duk_get_top(ctx));
39481#endif
39482
39483 return retval;
39484}
39485
39486/*
39487 * Halt execution helper
39488 */
39489
39490/* Halt execution and enter a debugger message loop until execution is resumed
39491 * by the client. PC for the current activation may be temporarily decremented
39492 * so that the "current" instruction will be shown by the client. This helper
39493 * is callable from anywhere, also outside bytecode executor.
39494 */
39495
39496DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
39497 duk_activation *act;
39499 duk_instr_t *old_pc = NULL;
39500
39501 DUK_ASSERT(thr != NULL);
39502 DUK_ASSERT(thr->heap != NULL);
39503 DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39504 DUK_ASSERT(thr->heap->dbg_processing == 0);
39505
39506 DUK_HEAP_SET_PAUSED(thr->heap);
39507
39509
39510 /* NOTE: act may be NULL if an error is thrown outside of any activation,
39511 * which may happen in the case of, e.g. syntax errors.
39512 */
39513
39514 /* Decrement PC if that was requested, this requires a PC sync. */
39515 if (act != NULL) {
39517 old_pc = act->curr_pc;
39519
39520 /* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
39521 * guaranteed to be a non-NULL Ecmascript function.
39522 */
39523 DUK_ASSERT(act->curr_pc == NULL ||
39524 (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)));
39525 if (use_prev_pc &&
39526 act->curr_pc != NULL &&
39528 act->curr_pc--;
39529 }
39530 }
39531
39532 /* Process debug messages until we are no longer paused. */
39533
39534 /* NOTE: This is a bit fragile. It's important to ensure that
39535 * duk_debug_process_messages() never throws an error or
39536 * act->curr_pc will never be reset.
39537 */
39538
39539 thr->heap->dbg_state_dirty = 1;
39540 while (thr->heap->dbg_paused) {
39541 DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39542 DUK_ASSERT(thr->heap->dbg_processing);
39543 duk_debug_process_messages(thr, 0 /*no_block*/);
39544 }
39545
39546 /* XXX: Decrementing and restoring act->curr_pc works now, but if the
39547 * debugger message loop gains the ability to adjust the current PC
39548 * (e.g. a forced jump) restoring the PC here will break. Another
39549 * approach would be to use a state flag for the "decrement 1 from
39550 * topmost activation's PC" and take it into account whenever dealing
39551 * with PC values.
39552 */
39553 if (act != NULL) {
39554 act->curr_pc = old_pc; /* restore PC */
39555 }
39556}
39557
39558/*
39559 * Breakpoint management
39560 */
39561
39562DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
39563 duk_heap *heap;
39564 duk_breakpoint *b;
39565
39566 /* Caller must trigger recomputation of active breakpoint list. To
39567 * ensure stale values are not used if that doesn't happen, clear the
39568 * active breakpoint list here.
39569 */
39570
39571 DUK_ASSERT(thr != NULL);
39572 DUK_ASSERT(filename != NULL);
39573 heap = thr->heap;
39574 DUK_ASSERT(heap != NULL);
39575
39576 if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
39577 DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
39578 (duk_heaphdr *) filename, (long) line));
39579 return -1;
39580 }
39581 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
39582 b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
39583 b->filename = filename;
39584 b->line = line;
39585 DUK_HSTRING_INCREF(thr, filename);
39586
39587 return heap->dbg_breakpoint_count - 1; /* index */
39588}
39589
39590DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
39591 duk_heap *heap;
39592 duk_hstring *h;
39593 duk_breakpoint *b;
39594 duk_size_t move_size;
39595
39596 /* Caller must trigger recomputation of active breakpoint list. To
39597 * ensure stale values are not used if that doesn't happen, clear the
39598 * active breakpoint list here.
39599 */
39600
39601 DUK_ASSERT(thr != NULL);
39602 heap = thr->heap;
39603 DUK_ASSERT(heap != NULL);
39604 DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39605 DUK_ASSERT_DISABLE(breakpoint_index >= 0); /* unsigned */
39606
39607 if (breakpoint_index >= heap->dbg_breakpoint_count) {
39608 DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
39609 return 0;
39610 }
39611 b = heap->dbg_breakpoints + breakpoint_index;
39612
39613 h = b->filename;
39614 DUK_ASSERT(h != NULL);
39615
39616 move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
39617 if (move_size > 0) {
39618 DUK_MEMMOVE((void *) b,
39619 (const void *) (b + 1),
39620 (size_t) move_size);
39621 }
39622 heap->dbg_breakpoint_count--;
39623 heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
39624
39625 DUK_HSTRING_DECREF(thr, h); /* side effects */
39626 DUK_UNREF(h); /* w/o refcounting */
39627
39628 /* Breakpoint entries above the used area are left as garbage. */
39629
39630 return 1;
39631}
39632
39633#undef DUK__SET_CONN_BROKEN
39634
39635#else /* DUK_USE_DEBUGGER_SUPPORT */
39636
39637/* No debugger support. */
39638
39639#endif /* DUK_USE_DEBUGGER_SUPPORT */
39640#line 1 "duk_error_augment.c"
39641/*
39642 * Augmenting errors at their creation site and their throw site.
39643 *
39644 * When errors are created, traceback data is added by built-in code
39645 * and a user error handler (if defined) can process or replace the
39646 * error. Similarly, when errors are thrown, a user error handler
39647 * (if defined) can process or replace the error.
39648 *
39649 * Augmentation and other processing at error creation time is nice
39650 * because an error is only created once, but it may be thrown and
39651 * rethrown multiple times. User error handler registered for processing
39652 * an error at its throw site must be careful to handle rethrowing in
39653 * a useful manner.
39654 *
39655 * Error augmentation may throw an internal error (e.g. alloc error).
39656 *
39657 * Ecmascript allows throwing any values, so all values cannot be
39658 * augmented. Currently, the built-in augmentation at error creation
39659 * only augments error values which are Error instances (= have the
39660 * built-in Error.prototype in their prototype chain) and are also
39661 * extensible. User error handlers have no limitations in this respect.
39662 */
39663
39664/* include removed: duk_internal.h */
39665
39666/*
39667 * Helper for calling a user error handler.
39668 *
39669 * 'thr' must be the currently active thread; the error handler is called
39670 * in its context. The valstack of 'thr' must have the error value on
39671 * top, and will be replaced by another error value based on the return
39672 * value of the error handler.
39673 *
39674 * The helper calls duk_handle_call() recursively in protected mode.
39675 * Before that call happens, no longjmps should happen; as a consequence,
39676 * we must assume that the valstack contains enough temporary space for
39677 * arguments and such.
39678 *
39679 * While the error handler runs, any errors thrown will not trigger a
39680 * recursive error handler call (this is implemented using a heap level
39681 * flag which will "follow" through any coroutines resumed inside the
39682 * error handler). If the error handler is not callable or throws an
39683 * error, the resulting error replaces the original error (for Duktape
39684 * internal errors, duk_error_throw.c further substitutes this error with
39685 * a DoubleError which is not ideal). This would be easy to change and
39686 * even signal to the caller.
39687 *
39688 * The user error handler is stored in 'Duktape.errCreate' or
39689 * 'Duktape.errThrow' depending on whether we're augmenting the error at
39690 * creation or throw time. There are several alternatives to this approach,
39691 * see doc/error-objects.rst for discussion.
39692 *
39693 * Note: since further longjmp()s may occur while calling the error handler
39694 * (for many reasons, e.g. a labeled 'break' inside the handler), the
39695 * caller can make no assumptions on the thr->heap->lj state after the
39696 * call (this affects especially duk_error_throw.c). This is not an issue
39697 * as long as the caller writes to the lj state only after the error handler
39698 * finishes.
39699 */
39700
39701#if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
39703 duk_context *ctx = (duk_context *) thr;
39704 duk_tval *tv_hnd;
39705 duk_small_uint_t call_flags;
39706 duk_int_t rc;
39707
39708 DUK_ASSERT(thr != NULL);
39709 DUK_ASSERT(thr->heap != NULL);
39710 DUK_ASSERT_DISABLE(stridx_cb >= 0); /* unsigned */
39711 DUK_ASSERT(stridx_cb < DUK_HEAP_NUM_STRINGS);
39712
39714 DUK_DD(DUK_DDPRINT("recursive call to error handler, ignore"));
39715 return;
39716 }
39717
39718 /*
39719 * Check whether or not we have an error handler.
39720 *
39721 * We must be careful of not triggering an error when looking up the
39722 * property. For instance, if the property is a getter, we don't want
39723 * to call it, only plain values are allowed. The value, if it exists,
39724 * is not checked. If the value is not a function, a TypeError happens
39725 * when it is called and that error replaces the original one.
39726 */
39727
39728 DUK_ASSERT_VALSTACK_SPACE(thr, 4); /* 3 entries actually needed below */
39729
39730 /* [ ... errval ] */
39731
39732 if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
39733 /* When creating built-ins, some of the built-ins may not be set
39734 * and we want to tolerate that when throwing errors.
39735 */
39736 DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
39737 return;
39738 }
39741 DUK_HTHREAD_GET_STRING(thr, stridx_cb));
39742 if (tv_hnd == NULL) {
39743 DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
39744 (duk_tval *) tv_hnd));
39745 return;
39746 }
39747 DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
39748 (duk_tval *) tv_hnd));
39749 duk_push_tval(ctx, tv_hnd);
39750
39751 /* [ ... errval errhandler ] */
39752
39753 duk_insert(ctx, -2); /* -> [ ... errhandler errval ] */
39754 duk_push_undefined(ctx);
39755 duk_insert(ctx, -2); /* -> [ ... errhandler undefined(= this) errval ] */
39756
39757 /* [ ... errhandler undefined errval ] */
39758
39759 /*
39760 * DUK_CALL_FLAG_IGNORE_RECLIMIT causes duk_handle_call() to ignore C
39761 * recursion depth limit (and won't increase it either). This is
39762 * dangerous, but useful because it allows the error handler to run
39763 * even if the original error is caused by C recursion depth limit.
39764 *
39765 * The heap level DUK_HEAP_FLAG_ERRHANDLER_RUNNING is set for the
39766 * duration of the error handler and cleared afterwards. This flag
39767 * prevents the error handler from running recursively. The flag is
39768 * heap level so that the flag properly controls even coroutines
39769 * launched by an error handler. Since the flag is heap level, it is
39770 * critical to restore it correctly.
39771 *
39772 * We ignore errors now: a success return and an error value both
39773 * replace the original error value. (This would be easy to change.)
39774 */
39775
39776 DUK_ASSERT(!DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap)); /* since no recursive error handler calls */
39778
39779 call_flags = DUK_CALL_FLAG_IGNORE_RECLIMIT; /* ignore reclimit, not constructor */
39780
39782 1, /* num args */
39783 call_flags); /* call_flags */
39784 DUK_UNREF(rc); /* no need to check now: both success and error are OK */
39785
39788
39789 /* [ ... errval ] */
39790}
39791#endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
39792
39793/*
39794 * Add ._Tracedata to an error on the stack top.
39795 */
39796
39797#if defined(DUK_USE_TRACEBACKS)
39798DUK_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) {
39799 duk_context *ctx = (duk_context *) thr;
39801 duk_int_t i, i_min;
39802 duk_uarridx_t arr_idx;
39803 duk_double_t d;
39804
39805 DUK_ASSERT(thr != NULL);
39806 DUK_ASSERT(thr_callstack != NULL);
39807 DUK_ASSERT(ctx != NULL);
39808
39809 /* [ ... error ] */
39810
39811 /*
39812 * The traceback format is pretty arcane in an attempt to keep it compact
39813 * and cheap to create. It may change arbitrarily from version to version.
39814 * It should be decoded/accessed through version specific accessors only.
39815 *
39816 * See doc/error-objects.rst.
39817 */
39818
39819 DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
39820 (duk_tval *) duk_get_tval(ctx, -1)));
39821
39822 duk_push_array(ctx); /* XXX: specify array size, as we know it */
39823 arr_idx = 0;
39824
39825 /* Compiler SyntaxErrors (and other errors) come first, and are
39826 * blamed by default (not flagged "noblame").
39827 */
39828 if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
39830 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39831 arr_idx++;
39832
39833 duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line); /* (flags<<32) + (line), flags = 0 */
39834 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39835 arr_idx++;
39836 }
39837
39838 /* Filename/line from C macros (__FILE__, __LINE__) are added as an
39839 * entry with a special format: (string, number). The number contains
39840 * the line and flags.
39841 */
39842
39843 /* XXX: optimize: allocate an array part to the necessary size (upwards
39844 * estimate) and fill in the values directly into the array part; finally
39845 * update 'length'.
39846 */
39847
39848 /* XXX: using duk_put_prop_index() would cause obscure error cases when Array.prototype
39849 * has write-protected array index named properties. This was seen as DoubleErrors
39850 * in e.g. some test262 test cases. Using duk_xdef_prop_index() is better but heavier.
39851 * The best fix is to fill in the tracedata directly into the array part. There are
39852 * no side effect concerns if the array part is allocated directly and only INCREFs
39853 * happen after that.
39854 */
39855
39856 /* [ ... error arr ] */
39857
39858 if (c_filename) {
39859 duk_push_string(ctx, c_filename);
39860 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39861 arr_idx++;
39862
39863 d = (noblame_fileline ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
39864 (duk_double_t) c_line;
39865 duk_push_number(ctx, d);
39866 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39867 arr_idx++;
39868 }
39869
39870 /* traceback depth doesn't take into account the filename/line
39871 * special handling above (intentional)
39872 */
39874 i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
39875 DUK_ASSERT(i_min >= 0);
39876
39877 /* [ ... error arr ] */
39878
39879 DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
39880 for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
39881 duk_uint32_t pc;
39882
39883 /*
39884 * Note: each API operation potentially resizes the callstack,
39885 * so be careful to re-lookup after every operation. Currently
39886 * these is no issue because we don't store a temporary 'act'
39887 * pointer at all. (This would be a non-issue if we operated
39888 * directly on the array part.)
39889 */
39890
39891 /* [... arr] */
39892
39893 DUK_ASSERT_DISABLE(thr_callstack->callstack[i].pc >= 0); /* unsigned */
39894
39895 /* Add function object. */
39896 duk_push_tval(ctx, &(thr_callstack->callstack + i)->tv_func);
39897 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39898 arr_idx++;
39899
39900 /* Add a number containing: pc, activation flags.
39901 *
39902 * PC points to next instruction, find offending PC. Note that
39903 * PC == 0 for native code.
39904 */
39905 pc = duk_hthread_get_act_prev_pc(thr_callstack, thr_callstack->callstack + i);
39906 DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
39907 DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
39908 d = ((duk_double_t) thr_callstack->callstack[i].flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
39909 duk_push_number(ctx, d); /* -> [... arr num] */
39910 duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39911 arr_idx++;
39912 }
39913
39914 /* XXX: set with duk_hobject_set_length() when tracedata is filled directly */
39915 duk_push_uint(ctx, (duk_uint_t) arr_idx);
39917
39918 /* [ ... error arr ] */
39919
39920 duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_TRACEDATA); /* -> [ ... error ] */
39921}
39922#endif /* DUK_USE_TRACEBACKS */
39923
39924/*
39925 * Add .fileName and .lineNumber to an error on the stack top.
39926 */
39927
39928#if !defined(DUK_USE_TRACEBACKS)
39929DUK_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) {
39930 duk_context *ctx;
39931#if defined(DUK_USE_ASSERTIONS)
39932 duk_int_t entry_top;
39933#endif
39934
39935 ctx = (duk_context *) thr;
39936#if defined(DUK_USE_ASSERTIONS)
39937 entry_top = duk_get_top(ctx);
39938#endif
39939
39940 /*
39941 * If tracebacks are disabled, 'fileName' and 'lineNumber' are added
39942 * as plain own properties. Since Error.prototype has accessors of
39943 * the same name, we need to define own properties directly (cannot
39944 * just use e.g. duk_put_prop_stridx). Existing properties are not
39945 * overwritten in case they already exist.
39946 */
39947
39948 if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
39949 /* Compiler SyntaxError (or other error) gets the primary blame.
39950 * Currently no flag to prevent blaming.
39951 */
39954 } else if (c_filename && !noblame_fileline) {
39955 /* C call site gets blamed next, unless flagged not to do so.
39956 * XXX: file/line is disabled in minimal builds, so disable this
39957 * too when appropriate.
39958 */
39959 duk_push_int(ctx, c_line);
39960 duk_push_string(ctx, c_filename);
39961 } else {
39962 /* Finally, blame the innermost callstack entry which has a
39963 * .fileName property.
39964 */
39966 duk_int_t i, i_min;
39967 duk_uint32_t ecma_line;
39968
39970 i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
39971 DUK_ASSERT(i_min >= 0);
39972
39973 DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
39974 for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
39975 duk_activation *act;
39976 duk_hobject *func;
39977 duk_uint32_t pc;
39978
39979 DUK_UNREF(pc);
39980 act = thr_callstack->callstack + i;
39981 DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
39982
39983 func = DUK_ACT_GET_FUNC(act);
39984 if (func == NULL) {
39985 /* Lightfunc, not blamed now. */
39986 continue;
39987 }
39988
39989 /* PC points to next instruction, find offending PC,
39990 * PC == 0 for native code.
39991 */
39992 pc = duk_hthread_get_act_prev_pc(thr, act); /* thr argument only used for thr->heap, so specific thread doesn't matter */
39993 DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
39994 DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
39995 act = NULL; /* invalidated by pushes, so get out of the way */
39996
39997 duk_push_hobject(ctx, func);
39998
39999 /* [ ... error func ] */
40000
40002 if (!duk_is_string(ctx, -1)) {
40003 duk_pop_2(ctx);
40004 continue;
40005 }
40006
40007 /* [ ... error func fileName ] */
40008
40009 ecma_line = 0;
40010#if defined(DUK_USE_PC2LINE)
40012 ecma_line = duk_hobject_pc2line_query(ctx, -2, (duk_uint_fast32_t) pc);
40013 } else {
40014 /* Native function, no relevant lineNumber. */
40015 }
40016#endif /* DUK_USE_PC2LINE */
40017 duk_push_u32(ctx, ecma_line);
40018
40019 /* [ ... error func fileName lineNumber ] */
40020
40021 duk_replace(ctx, -3);
40022
40023 /* [ ... error lineNumber fileName ] */
40024 goto define_props;
40025 }
40026
40027 /* No activation matches, use undefined for both .fileName and
40028 * .lineNumber (matches what we do with a _Tracedata based
40029 * no-match lookup.
40030 */
40031 duk_push_undefined(ctx);
40033 }
40034
40035 define_props:
40036 /* [ ... error lineNumber fileName ] */
40037#if defined(DUK_USE_ASSERTIONS)
40038 DUK_ASSERT(duk_get_top(ctx) == entry_top + 2);
40039#endif
40042}
40043#endif /* !DUK_USE_TRACEBACKS */
40044
40045/*
40046 * Add line number to a compiler error.
40047 */
40048
40050 duk_context *ctx;
40051
40052 /* Append a "(line NNN)" to the "message" property of any error
40053 * thrown during compilation. Usually compilation errors are
40054 * SyntaxErrors but they can also be out-of-memory errors and
40055 * the like.
40056 */
40057
40058 /* [ ... error ] */
40059
40060 ctx = (duk_context *) thr;
40061 DUK_ASSERT(duk_is_object(ctx, -1));
40062
40063 if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
40064 return;
40065 }
40066
40067 DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
40068 (duk_tval *) duk_get_tval(ctx, -1)));
40069
40071 duk_push_sprintf(ctx, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
40072 duk_concat(ctx, 2);
40074 } else {
40075 duk_pop(ctx);
40076 }
40077
40078 DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
40079 (duk_tval *) duk_get_tval(ctx, -1)));
40080}
40081
40082/*
40083 * Augment an error being created using Duktape specific properties
40084 * like _Tracedata or .fileName/.lineNumber.
40085 */
40086
40087#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
40088DUK_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) {
40089 duk_context *ctx = (duk_context *) thr;
40090#if defined(DUK_USE_ASSERTIONS)
40091 duk_int_t entry_top;
40092#endif
40093
40094#if defined(DUK_USE_ASSERTIONS)
40095 entry_top = duk_get_top(ctx);
40096#endif
40097 DUK_ASSERT(obj != NULL);
40098
40099 DUK_UNREF(obj); /* unreferenced w/o tracebacks */
40100 DUK_UNREF(ctx); /* unreferenced w/o asserts */
40101
40103
40104#if defined(DUK_USE_TRACEBACKS)
40105 /* If tracebacks are enabled, the '_Tracedata' property is the only
40106 * thing we need: 'fileName' and 'lineNumber' are virtual properties
40107 * which use '_Tracedata'.
40108 */
40110 DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
40111 } else {
40112 duk__add_traceback(thr, thr_callstack, c_filename, c_line, noblame_fileline);
40113 }
40114#else
40115 /* Without tracebacks the concrete .fileName and .lineNumber need
40116 * to be added directly.
40117 */
40118 duk__add_fileline(thr, thr_callstack, c_filename, c_line, noblame_fileline);
40119#endif
40120
40121#if defined(DUK_USE_ASSERTIONS)
40122 DUK_ASSERT(duk_get_top(ctx) == entry_top);
40123#endif
40124}
40125#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
40126
40127/*
40128 * Augment an error at creation time with _Tracedata/fileName/lineNumber
40129 * and allow a user error handler (if defined) to process/replace the error.
40130 * The error to be augmented is at the stack top.
40131 *
40132 * thr: thread containing the error value
40133 * thr_callstack: thread which should be used for generating callstack etc.
40134 * c_filename: C __FILE__ related to the error
40135 * c_line: C __LINE__ related to the error
40136 * noblame_fileline: if true, don't fileName/line as error source, otherwise use traceback
40137 * (needed because user code filename/line are reported but internal ones
40138 * are not)
40139 *
40140 * XXX: rename noblame_fileline to flags field; combine it to some existing
40141 * field (there are only a few call sites so this may not be worth it).
40142 */
40143
40144#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
40145DUK_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) {
40146 duk_context *ctx = (duk_context *) thr;
40147 duk_hobject *obj;
40148
40149 DUK_ASSERT(thr != NULL);
40150 DUK_ASSERT(thr_callstack != NULL);
40151 DUK_ASSERT(ctx != NULL);
40152
40153 /* [ ... error ] */
40154
40155 /*
40156 * Criteria for augmenting:
40157 *
40158 * - augmentation enabled in build (naturally)
40159 * - error value internal prototype chain contains the built-in
40160 * Error prototype object (i.e. 'val instanceof Error')
40161 *
40162 * Additional criteria for built-in augmenting:
40163 *
40164 * - error value is an extensible object
40165 */
40166
40167 obj = duk_get_hobject(ctx, -1);
40168 if (!obj) {
40169 DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
40170 return;
40171 }
40172 if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
40173 /* If the value has a prototype loop, it's critical not to
40174 * throw here. Instead, assume the value is not to be
40175 * augmented.
40176 */
40177 DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
40178 return;
40179 }
40180 if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
40181 DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
40182 duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, noblame_fileline, obj);
40183 } else {
40184 DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
40186
40187 /* [ ... error ] */
40188
40189#if defined(DUK_USE_ERRCREATE)
40191#endif
40192}
40193#endif /* DUK_USE_AUGMENT_ERROR_CREATE */
40194
40195/*
40196 * Augment an error at throw time; allow a user error handler (if defined)
40197 * to process/replace the error. The error to be augmented is at the
40198 * stack top.
40200
40201#if defined(DUK_USE_AUGMENT_ERROR_THROW)
40203#if defined(DUK_USE_ERRTHROW)
40205#endif /* DUK_USE_ERRTHROW */
40206}
40207#endif /* DUK_USE_AUGMENT_ERROR_THROW */
40208#line 1 "duk_error_longjmp.c"
40209/*
40210 * Do a longjmp call, calling the fatal error handler if no
40211 * catchpoint exists.
40212 */
40213
40214/* include removed: duk_internal.h */
40215
40217 DUK_ASSERT(thr != NULL);
40218
40219 DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
40220 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
40221 &thr->heap->lj.value1, &thr->heap->lj.value2));
40222
40223#if !defined(DUK_USE_CPP_EXCEPTIONS)
40224 /* If we don't have a jmpbuf_ptr, there is little we can do
40225 * except panic. The caller's expectation is that we never
40226 * return.
40227 *
40228 * With C++ exceptions we now just propagate an uncaught error
40229 * instead of invoking the fatal error handler. Because there's
40230 * a dummy jmpbuf for C++ exceptions now, this could be changed.
40231 */
40232 if (!thr->heap->lj.jmpbuf_ptr) {
40233
40234 DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
40235 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
40236 &thr->heap->lj.value1, &thr->heap->lj.value2));
40237
40238 duk_fatal((duk_context *) thr, DUK_ERR_UNCAUGHT_ERROR, "uncaught error");
40240 }
40241#endif /* DUK_USE_CPP_EXCEPTIONS */
40242
40243#if defined(DUK_USE_CPP_EXCEPTIONS)
40244 {
40245 duk_internal_exception exc; /* dummy */
40246 throw exc;
40247 }
40248#else /* DUK_USE_CPP_EXCEPTIONS */
40250#endif /* DUK_USE_CPP_EXCEPTIONS */
40251
40253}
40254#line 1 "duk_error_misc.c"
40255/*
40256 * Error helpers
40257 */
40258
40259/* include removed: duk_internal.h */
40260
40261/*
40262 * Helper to walk the thread chain and see if there is an active error
40263 * catcher. Protected calls or finally blocks aren't considered catching.
40264 */
40265
40266#if defined(DUK_USE_DEBUGGER_SUPPORT) && \
40267 (defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT))
40268DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
40269 /*
40270 * XXX: As noted above, a protected API call won't be counted as a
40271 * catcher. This is usually convenient, e.g. in the case of a top-
40272 * level duk_pcall(), but may not always be desirable. Perhaps add an
40273 * argument to treat them as catchers?
40274 */
40275
40276 duk_size_t i;
40277
40278 DUK_ASSERT(thr != NULL);
40279
40280 while (thr != NULL) {
40281 for (i = 0; i < thr->catchstack_top; i++) {
40282 duk_catcher *cat = thr->catchstack + i;
40283 if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
40284 return 1; /* all we need to know */
40285 }
40286 }
40287 thr = thr->resumer;
40288 }
40289 return 0;
40290}
40291#endif /* DUK_USE_DEBUGGER_SUPPORT && (DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) */
40292
40293/*
40294 * Get prototype object for an integer error code.
40295 */
40296
40298 switch (code) {
40299 case DUK_ERR_EVAL_ERROR:
40307 case DUK_ERR_TYPE_ERROR:
40309 case DUK_ERR_URI_ERROR:
40312 /* XXX: more specific error classes? */
40317 case DUK_ERR_API_ERROR:
40318 case DUK_ERR_ERROR:
40319 default:
40321 }
40322}
40323
40324/*
40325 * Exposed helper for setting up heap longjmp state.
40326 */
40327
40329#if defined(DUK_USE_DEBUGGER_SUPPORT)
40330 /* If something is thrown with the debugger attached and nobody will
40331 * catch it, execution is paused before the longjmp, turning over
40332 * control to the debug client. This allows local state to be examined
40333 * before the stack is unwound. Errors are not intercepted when debug
40334 * message loop is active (e.g. for Eval).
40335 */
40336
40337 /* XXX: Allow customizing the pause and notify behavior at runtime
40338 * using debugger runtime flags. For now the behavior is fixed using
40339 * config options.
40340 */
40341#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
40342 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) &&
40343 !thr->heap->dbg_processing &&
40344 lj_type == DUK_LJ_TYPE_THROW) {
40345 duk_context *ctx = (duk_context *) thr;
40347 duk_hobject *h_obj;
40348
40349 /* Don't intercept a DoubleError, we may have caused the initial double
40350 * fault and attempting to intercept it will cause us to be called
40351 * recursively and exhaust the C stack.
40352 */
40353 h_obj = duk_get_hobject(ctx, -1);
40354 if (h_obj == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
40355 DUK_D(DUK_DPRINT("built-in DoubleError instance thrown, not intercepting"));
40356 goto skip_throw_intercept;
40357 }
40358
40359 DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
40360
40361 fatal = !duk__have_active_catcher(thr);
40362
40363#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
40364 /* Report it to the debug client */
40365 duk_debug_send_throw(thr, fatal);
40366#endif
40367
40368#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
40369 if (fatal) {
40370 DUK_D(DUK_DPRINT("throw will be fatal, halt before longjmp"));
40371 duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
40372 }
40373#endif
40374 }
40375
40376 skip_throw_intercept:
40377#endif /* DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT */
40378#endif /* DUK_USE_DEBUGGER_SUPPORT */
40379
40380 thr->heap->lj.type = lj_type;
40381
40382 DUK_ASSERT(thr->valstack_top > thr->valstack);
40383 DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, thr->valstack_top - 1); /* side effects */
40384
40385 duk_pop((duk_context *) thr);
40386}
40387#line 1 "duk_error_throw.c"
40388/*
40389 * Create and throw an Ecmascript error object based on a code and a message.
40390 *
40391 * Used when we throw errors internally. Ecmascript generated error objects
40392 * are created by Ecmascript code, and the throwing is handled by the bytecode
40393 * executor.
40395
40396/* include removed: duk_internal.h */
40397
40398/*
40399 * Create and throw an error (originating from Duktape internally)
40400 *
40401 * Push an error object on top of the stack, possibly throw augmenting
40402 * the error, and finally longjmp.
40403 *
40404 * If an error occurs while we're dealing with the current error, we might
40405 * enter an infinite recursion loop. This is prevented by detecting a
40406 * "double fault" through the heap->handling_error flag; the recursion
40407 * then stops at the second level.
40408 */
40409
40410#ifdef DUK_USE_VERBOSE_ERRORS
40411DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {
40412#else
40414#endif
40415 duk_context *ctx = (duk_context *) thr;
40416 duk_bool_t double_error = thr->heap->handling_error;
40417
40418#ifdef DUK_USE_VERBOSE_ERRORS
40419 DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
40420 (long) code, (const char *) msg,
40421 (const char *) filename, (long) line));
40422#else
40423 DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
40424#endif
40425
40426 DUK_ASSERT(thr != NULL);
40427 DUK_ASSERT(ctx != NULL);
40428
40429 thr->heap->handling_error = 1;
40430
40431 if (!double_error) {
40432 /* Allow headroom for calls during error handling (see GH-191).
40433 * We allow space for 10 additional recursions, with one extra
40434 * for, e.g. a print() call at the deepest level.
40435 */
40438 }
40439
40440 DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11); /* just making sure */
40441
40442 /* Sync so that augmentation sees up-to-date activations, NULL
40443 * thr->ptr_curr_pc so that it's not used if side effects occur
40444 * in augmentation or longjmp handling.
40445 */
40447
40448 /*
40449 * Create and push an error object onto the top of stack.
40450 * If a "double error" occurs, use a fixed error instance
40451 * to avoid further trouble.
40452 */
40453
40454 /* XXX: if attempt to push beyond allocated valstack, this double fault
40455 * handling fails miserably. We should really write the double error
40456 * directly to thr->heap->lj.value1 and avoid valstack use entirely.
40457 */
40458
40459 if (double_error) {
40460 if (thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
40461 DUK_D(DUK_DPRINT("double fault detected -> push built-in fixed 'double error' instance"));
40463 } else {
40464 DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
40465 "-> push the error code as a number"));
40466 duk_push_int(ctx, (duk_int_t) code);
40467 }
40468 } else {
40469 /* Error object is augmented at its creation here. */
40470 duk_require_stack(ctx, 1);
40471 /* XXX: unnecessary '%s' formatting here, but cannot use
40472 * 'msg' as a format string directly.
40473 */
40474#ifdef DUK_USE_VERBOSE_ERRORS
40477 filename,
40478 line,
40479 "%s",
40480 (const char *) msg);
40481#else
40484 NULL,
40485 0,
40486 NULL);
40487#endif
40488 }
40489
40490 /*
40491 * Augment error (throw time), unless alloc/double error
40492 */
40493
40494 if (double_error || code == DUK_ERR_ALLOC_ERROR) {
40495 DUK_D(DUK_DPRINT("alloc or double error: skip throw augmenting to avoid further trouble"));
40496 } else {
40497#if defined(DUK_USE_AUGMENT_ERROR_THROW)
40498 DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
40499 (duk_tval *) duk_get_tval(ctx, -1)));
40501#endif
40502 }
40503
40504 /*
40505 * Finally, longjmp
40506 */
40509
40510 thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX; /* reset callstack limit */
40511 thr->heap->handling_error = 0;
40512
40513 DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
40514 (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
40515
40516 duk_err_longjmp(thr);
40518}
40519
40520/*
40521 * Helper for C function call negative return values.
40522 */
40523
40525 duk_context *ctx = (duk_context *) thr;
40526 const char *msg;
40527 duk_errcode_t code;
40528
40529 DUK_ASSERT(thr != NULL);
40530 DUK_ASSERT(rc < 0);
40531
40532 /* XXX: this generates quite large code - perhaps select the error
40533 * class based on the code and then just use the error 'name'?
40534 */
40535 /* XXX: shared strings */
40536
40537 code = -rc;
40538
40539 switch (rc) {
40540 case DUK_RET_UNIMPLEMENTED_ERROR: msg = "unimplemented"; break;
40541 case DUK_RET_UNSUPPORTED_ERROR: msg = "unsupported"; break;
40542 case DUK_RET_INTERNAL_ERROR: msg = "internal"; break;
40543 case DUK_RET_ALLOC_ERROR: msg = "alloc"; break;
40544 case DUK_RET_ASSERTION_ERROR: msg = "assertion"; break;
40545 case DUK_RET_API_ERROR: msg = "api"; break;
40546 case DUK_RET_UNCAUGHT_ERROR: msg = "uncaught"; break;
40547 case DUK_RET_ERROR: msg = "error"; break;
40548 case DUK_RET_EVAL_ERROR: msg = "eval"; break;
40549 case DUK_RET_RANGE_ERROR: msg = "range"; break;
40550 case DUK_RET_REFERENCE_ERROR: msg = "reference"; break;
40551 case DUK_RET_SYNTAX_ERROR: msg = "syntax"; break;
40552 case DUK_RET_TYPE_ERROR: msg = "type"; break;
40553 case DUK_RET_URI_ERROR: msg = "uri"; break;
40554 default: msg = "unknown"; break;
40555 }
40556
40557 DUK_ASSERT(msg != NULL);
40558
40559 /*
40560 * The __FILE__ and __LINE__ information is intentionally not used in the
40561 * creation of the error object, as it isn't useful in the tracedata. The
40562 * tracedata still contains the function which returned the negative return
40563 * code, and having the file/line of this function isn't very useful.
40564 */
40565
40566 duk_error_raw(ctx, code, NULL, 0, "%s error (rc %ld)", (const char *) msg, (long) rc);
40568}
40569#line 1 "duk_hbuffer_alloc.c"
40570/*
40571 * duk_hbuffer allocation and freeing.
40572 */
40573
40574/* include removed: duk_internal.h */
40575
40576/* Allocate a new duk_hbuffer of a certain type and return a pointer to it
40577 * (NULL on error). Write buffer data pointer to 'out_bufdata' (only if
40578 * allocation successful).
40579 */
40580DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
40581 duk_hbuffer *res = NULL;
40582 duk_size_t header_size;
40583 duk_size_t alloc_size;
40584
40585 DUK_ASSERT(heap != NULL);
40586 DUK_ASSERT(out_bufdata != NULL);
40587
40588 DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
40589
40590 /* Size sanity check. Should not be necessary because caller is
40591 * required to check this, but we don't want to cause a segfault
40592 * if the size wraps either in duk_size_t computation or when
40593 * storing the size in a 16-bit field.
40594 */
40595 if (size > DUK_HBUFFER_MAX_BYTELEN) {
40596 DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
40597 return NULL; /* no need to write 'out_bufdata' */
40598 }
40599
40600 if (flags & DUK_BUF_FLAG_EXTERNAL) {
40601 header_size = sizeof(duk_hbuffer_external);
40602 alloc_size = sizeof(duk_hbuffer_external);
40603 } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
40604 header_size = sizeof(duk_hbuffer_dynamic);
40605 alloc_size = sizeof(duk_hbuffer_dynamic);
40606 } else {
40607 header_size = sizeof(duk_hbuffer_fixed);
40608 alloc_size = sizeof(duk_hbuffer_fixed) + size;
40609 DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed)); /* no wrapping */
40610 }
40611
40612 res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
40613 if (!res) {
40614 goto error;
40615 }
40616
40617 /* zero everything unless requested not to do so */
40618#if defined(DUK_USE_ZERO_BUFFER_DATA)
40619 DUK_MEMZERO((void *) res,
40620 (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
40621#else
40622 DUK_MEMZERO((void *) res, header_size);
40623#endif
40624
40625 if (flags & DUK_BUF_FLAG_EXTERNAL) {
40627 h = (duk_hbuffer_external *) res;
40628 DUK_UNREF(h);
40629 *out_bufdata = NULL;
40630#if defined(DUK_USE_EXPLICIT_NULL_INIT)
40631#if defined(DUK_USE_HEAPPTR16)
40632/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
40633#else
40635#endif
40636#endif
40638 } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
40640 void *ptr;
40641
40642 if (size > 0) {
40643 DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL)); /* alloc external with size zero */
40644 DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
40645#ifdef DUK_USE_ZERO_BUFFER_DATA
40646 ptr = DUK_ALLOC_ZEROED(heap, size);
40647#else
40648 ptr = DUK_ALLOC(heap, size);
40649#endif
40650 if (!ptr) {
40651 /* Because size > 0, NULL check is correct */
40652 goto error;
40653 }
40654 *out_bufdata = ptr;
40655
40657 } else {
40658 *out_bufdata = NULL;
40659#if defined(DUK_USE_EXPLICIT_NULL_INIT)
40660#if defined(DUK_USE_HEAPPTR16)
40661/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
40662#else
40664#endif
40665#endif
40667 }
40668 } else {
40669 *out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);
40670 }
40671
40672 DUK_HBUFFER_SET_SIZE(res, size);
40673
40675 if (flags & DUK_BUF_FLAG_DYNAMIC) {
40677 if (flags & DUK_BUF_FLAG_EXTERNAL) {
40679 }
40680 } else {
40682 }
40683 DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
40684
40685 DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
40686 return res;
40687
40688 error:
40689 DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
40690
40691 DUK_FREE(heap, res);
40692 return NULL; /* no need to write 'out_bufdata' */
40693}
40694
40695/* For indirect allocs. */
40696
40697DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
40699 DUK_UNREF(heap);
40700 return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
40701}
40702#line 1 "duk_hbuffer_ops.c"
40704 * duk_hbuffer operations such as resizing and inserting/appending data to
40705 * a dynamic buffer.
40706 *
40707 * Append operations append to the end of the buffer and they are relatively
40708 * efficient: the buffer is grown with a "spare" part relative to the buffer
40709 * size to minimize reallocations. Insert operations need to move existing
40710 * data forward in the buffer with memmove() and are not very efficient.
40711 * They are used e.g. by the regexp compiler to "backpatch" regexp bytecode.
40712 */
40713
40714/* include removed: duk_internal.h */
40715
40716/*
40717 * Resizing
40718 */
40719
40721 void *res;
40722 duk_size_t prev_size;
40723
40724 DUK_ASSERT(thr != NULL);
40725 DUK_ASSERT(buf != NULL);
40728
40729 /*
40730 * Maximum size check
40731 */
40732
40733 if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
40734 DUK_ERROR_RANGE(thr, "buffer too long");
40735 }
40736
40737 /*
40738 * Note: use indirect realloc variant just in case mark-and-sweep
40739 * (finalizers) might resize this same buffer during garbage
40740 * collection.
40741 */
40742
40743 res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
40744 if (res != NULL || new_size == 0) {
40745 /* 'res' may be NULL if new allocation size is 0. */
40746
40747 DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
40748 (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
40749 (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
40750 (void *) res,
40751 (long) new_size));
40752
40753 /*
40754 * The entire allocated buffer area, regardless of actual used
40755 * size, is kept zeroed in resizes for simplicity. If the buffer
40756 * is grown, zero the new part.
40757 */
40758
40759 prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
40760 if (new_size > prev_size) {
40761 DUK_ASSERT(new_size - prev_size > 0);
40762#ifdef DUK_USE_ZERO_BUFFER_DATA
40763 DUK_MEMZERO((void *) ((char *) res + prev_size),
40764 (duk_size_t) (new_size - prev_size));
40765#endif
40766 }
40767
40768 DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
40769 DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
40770 } else {
40773
40774 DUK_ASSERT(res != NULL || new_size == 0);
40775}
40776
40778 DUK_ASSERT(thr != NULL);
40779 DUK_ASSERT(buf != NULL);
40782
40783 duk_hbuffer_resize(thr, buf, 0);
40784}
40785/* include removed: duk_internal.h */
40786#line 2 "duk_hbufferobject_misc.c"
40787
40788#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
40790 duk_uint_t buf_size;
40791 duk_uint_t buf_avail;
40792
40793 DUK_ASSERT(h_bufobj != NULL);
40794 DUK_ASSERT(h_bufobj->buf != NULL);
40795
40796 buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
40797 if (h_bufobj->offset > buf_size) {
40798 /* Slice starting point is beyond current length. */
40799 return 0;
40801 buf_avail = buf_size - h_bufobj->offset;
40803 return buf_avail >= len ? len : buf_avail;
40804}
40805#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
40806#line 1 "duk_heap_alloc.c"
40807/*
40808 * duk_heap allocation and freeing.
40809 */
40810
40811/* include removed: duk_internal.h */
40812
40813/* Constants for built-in string data depacking. */
40814#define DUK__BITPACK_LETTER_LIMIT 26
40815#define DUK__BITPACK_UNDERSCORE 26
40816#define DUK__BITPACK_FF 27
40817#define DUK__BITPACK_SWITCH1 29
40818#define DUK__BITPACK_SWITCH 30
40819#define DUK__BITPACK_SEVENBIT 31
40820
40821#if defined(DUK_USE_ROM_STRINGS)
40822/* Fixed seed value used with ROM strings. */
40823#define DUK__FIXED_HASH_SEED 0xabcd1234
40824#endif
40825
40826/*
40827 * Free a heap object.
40828 *
40829 * Free heap object and its internal (non-heap) pointers. Assumes that
40830 * caller has removed the object from heap allocated list or the string
40831 * intern table, and any weak references (which strings may have) have
40832 * been already dealt with.
40833 */
40834
40836 DUK_ASSERT(heap != NULL);
40837 DUK_ASSERT(h != NULL);
40838
40839 DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
40840
40843 DUK_UNREF(f);
40844 /* Currently nothing to free; 'data' is a heap object */
40845 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
40847 DUK_UNREF(f);
40848 /* Currently nothing to free */
40849 } else if (DUK_HOBJECT_IS_THREAD(h)) {
40850 duk_hthread *t = (duk_hthread *) h;
40851 DUK_FREE(heap, t->valstack);
40852 DUK_FREE(heap, t->callstack);
40853 DUK_FREE(heap, t->catchstack);
40854 /* Don't free h->resumer because it exists in the heap.
40855 * Callstack entries also contain function pointers which
40856 * are not freed for the same reason.
40857 */
40858
40859 /* XXX: with 'caller' property the callstack would need
40860 * to be unwound to update the 'caller' properties of
40861 * functions in the callstack.
40862 */
40863 }
40864}
40865
40867 DUK_ASSERT(heap != NULL);
40868 DUK_ASSERT(h != NULL);
40869
40872 DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
40874 }
40875}
40878 DUK_ASSERT(heap != NULL);
40879 DUK_ASSERT(h != NULL);
40880
40881 DUK_UNREF(heap);
40882 DUK_UNREF(h);
40883
40884#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
40885 if (DUK_HSTRING_HAS_EXTDATA(h)) {
40886 DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
40887 h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
40888 DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
40889 }
40890#endif
40891}
40892
40894 DUK_ASSERT(heap);
40895 DUK_ASSERT(hdr);
40896
40897 DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
40898
40899 switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
40900 case DUK_HTYPE_STRING:
40901 duk_free_hstring_inner(heap, (duk_hstring *) hdr);
40902 break;
40903 case DUK_HTYPE_OBJECT:
40904 duk_free_hobject_inner(heap, (duk_hobject *) hdr);
40905 break;
40906 case DUK_HTYPE_BUFFER:
40907 duk_free_hbuffer_inner(heap, (duk_hbuffer *) hdr);
40908 break;
40909 default:
40911 }
40913 DUK_FREE(heap, hdr);
40914}
40915
40916/*
40917 * Free the heap.
40918 *
40919 * Frees heap-related non-heap-tracked allocations such as the
40920 * string intern table; then frees the heap allocated objects;
40921 * and finally frees the heap structure itself. Reference counts
40922 * and GC markers are ignored (and not updated) in this process,
40923 * and finalizers won't be called.
40924 *
40925 * The heap pointer and heap object pointers must not be used
40926 * after this call.
40927 */
40928
40930 duk_heaphdr *curr;
40932
40933 curr = heap->heap_allocated;
40934 while (curr) {
40935 /* We don't log or warn about freeing zero refcount objects
40936 * because they may happen with finalizer processing.
40937 */
40938
40939 DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
40940 (duk_heaphdr *) curr));
40941 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
40942 duk_heap_free_heaphdr_raw(heap, curr);
40943 curr = next;
40944 }
40945}
40946
40947#if defined(DUK_USE_REFERENCE_COUNTING)
40949 duk_heaphdr *curr;
40951
40952 curr = heap->refzero_list;
40953 while (curr) {
40954 DUK_DDD(DUK_DDDPRINT("FINALFREE (refzero_list): %!iO",
40955 (duk_heaphdr *) curr));
40956 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
40957 duk_heap_free_heaphdr_raw(heap, curr);
40958 curr = next;
40959 }
40960}
40961#endif
40963#if defined(DUK_USE_MARK_AND_SWEEP)
40965 duk_heaphdr *curr;
40968 curr = heap->finalize_list;
40969 while (curr) {
40970 DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
40971 (duk_heaphdr *) curr));
40972 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
40973 duk_heap_free_heaphdr_raw(heap, curr);
40974 curr = next;
40975 }
40976}
40977#endif
40978
40980 /* strings are only tracked by stringtable */
40982}
40983
40985 duk_hthread *thr;
40986 duk_heaphdr *curr;
40987 duk_uint_t round_no;
40988 duk_size_t count_all;
40989 duk_size_t count_finalized;
40990 duk_size_t curr_limit;
40991
40992 DUK_ASSERT(heap != NULL);
40993 DUK_ASSERT(heap->heap_thread != NULL);
40994
40995#if defined(DUK_USE_REFERENCE_COUNTING)
40996 DUK_ASSERT(heap->refzero_list == NULL); /* refzero not running -> must be empty */
40997#endif
40998#if defined(DUK_USE_MARK_AND_SWEEP)
40999 DUK_ASSERT(heap->finalize_list == NULL); /* mark-and-sweep not running -> must be empty */
41000#endif
41001
41002 /* XXX: here again finalizer thread is the heap_thread which needs
41003 * to be coordinated with finalizer thread fixes.
41004 */
41005 thr = heap->heap_thread;
41006 DUK_ASSERT(thr != NULL);
41007
41008 /* Prevent mark-and-sweep for the pending finalizers, also prevents
41009 * refzero handling from moving objects away from the heap_allocated
41010 * list. (The flag meaning is slightly abused here.)
41011 */
41014
41015 curr_limit = 0; /* suppress warning, not used */
41016 for (round_no = 0; ; round_no++) {
41017 curr = heap->heap_allocated;
41018 count_all = 0;
41019 count_finalized = 0;
41020 while (curr) {
41021 count_all++;
41023 /* Only objects in heap_allocated may have finalizers. Check that
41024 * the object itself has a _Finalizer property (own or inherited)
41025 * so that we don't execute finalizers for e.g. Proxy objects.
41026 */
41027 DUK_ASSERT(thr != NULL);
41028 DUK_ASSERT(curr != NULL);
41029
41031 if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
41032 DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)); /* maps to finalizer 2nd argument */
41034 count_finalized++;
41035 }
41036 }
41037 }
41038 curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
41039 }
41040
41041 /* Each round of finalizer execution may spawn new finalizable objects
41042 * which is normal behavior for some applications. Allow multiple
41043 * rounds of finalization, but use a shrinking limit based on the
41044 * first round to detect the case where a runaway finalizer creates
41045 * an unbounded amount of new finalizable objects. Finalizer rescue
41046 * is not supported: the semantics are unclear because most of the
41047 * objects being finalized here are already reachable. The finalizer
41048 * is given a boolean to indicate that rescue is not possible.
41049 *
41050 * See discussion in: https://github.com/svaarala/duktape/pull/473
41051 */
41052
41053 if (round_no == 0) {
41054 /* Cannot wrap: each object is at least 8 bytes so count is
41055 * at most 1/8 of that.
41056 */
41057 curr_limit = count_all * 2;
41058 } else {
41059 curr_limit = (curr_limit * 3) / 4; /* Decrease by 25% every round */
41060 }
41061 DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
41062 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
41063
41064 if (count_finalized == 0) {
41065 DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
41066 break;
41067 }
41068 if (count_finalized >= curr_limit) {
41069 DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
41070 break;
41071 }
41072 }
41073
41076}
41077
41079 DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
41080
41081#if defined(DUK_USE_DEBUG)
41082 duk_heap_dump_strtab(heap);
41083#endif
41084
41085#if defined(DUK_USE_DEBUGGER_SUPPORT)
41086 /* Detach a debugger if attached (can be called multiple times)
41087 * safely.
41088 */
41089 /* XXX: Add a flag to reject an attempt to re-attach? Otherwise
41090 * the detached callback may immediately reattach.
41091 */
41092 duk_debug_do_detach(heap);
41093#endif
41094
41095 /* Execute finalizers before freeing the heap, even for reachable
41096 * objects, and regardless of whether or not mark-and-sweep is
41097 * enabled. This gives finalizers the chance to free any native
41098 * resources like file handles, allocations made outside Duktape,
41099 * etc. This is quite tricky to get right, so that all finalizer
41100 * guarantees are honored.
41101 *
41102 * XXX: this perhaps requires an execution time limit.
41103 */
41104 DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
41105#if defined(DUK_USE_MARK_AND_SWEEP)
41106 /* Run mark-and-sweep a few times just in case (unreachable object
41107 * finalizers run already here). The last round must rescue objects
41108 * from the previous round without running any more finalizers. This
41109 * ensures rescued objects get their FINALIZED flag cleared so that
41110 * their finalizer is called once more in forced finalization to
41111 * satisfy finalizer guarantees. However, we don't want to run any
41112 * more finalizer because that'd required one more loop, and so on.
41113 */
41114 DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
41115 duk_heap_mark_and_sweep(heap, 0);
41116 DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
41117 duk_heap_mark_and_sweep(heap, 0);
41118 DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
41119 duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS); /* skip finalizers; queue finalizable objects to heap_allocated */
41120#endif
41121
41122 DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* rescue no longer supported */
41124
41125 /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
41126 * are on the heap allocated list.
41127 */
41128
41129 DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap));
41130 duk__free_allocated(heap);
41131
41132#if defined(DUK_USE_REFERENCE_COUNTING)
41133 DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap));
41135#endif
41136
41137#if defined(DUK_USE_MARK_AND_SWEEP)
41138 DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap));
41140#endif
41141
41142 DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
41144
41145 DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
41146 heap->free_func(heap->heap_udata, heap);
41147}
41148
41149/*
41150 * Allocate a heap.
41151 *
41152 * String table is initialized with built-in strings from genbuiltins.py,
41153 * either by dynamically creating the strings or by referring to ROM strings.
41154 */
41155
41156#if defined(DUK_USE_ROM_STRINGS)
41158#if defined(DUK_USE_ASSERTIONS)
41160#endif
41161
41162 /* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
41163 * so nothing to initialize for strs[].
41165
41166#if defined(DUK_USE_ASSERTIONS)
41167 for (i = 0; i < sizeof(duk_rom_strings) / sizeof(const duk_hstring *); i++) {
41168 duk_uint32_t hash;
41169 const duk_hstring *h;
41170 h = duk_rom_strings[i];
41171 DUK_ASSERT(h != NULL);
41172 hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
41173 DUK_DD(DUK_DDPRINT("duk_rom_strings[%d] -> hash 0x%08lx, computed 0x%08lx",
41174 (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
41175 DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
41176 }
41177#endif
41178 return 1;
41179}
41180#else /* DUK_USE_ROM_STRINGS */
41182 duk_bitdecoder_ctx bd_ctx;
41183 duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
41184 duk_small_uint_t i, j;
41185
41186 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
41187 bd->data = (const duk_uint8_t *) duk_strings_data;
41189
41190 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
41191 duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
41192 duk_hstring *h;
41193 duk_small_uint_t len;
41194 duk_small_uint_t mode;
41196
41197 len = duk_bd_decode(bd, 5);
41198 mode = 32; /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
41199 for (j = 0; j < len; j++) {
41200 t = duk_bd_decode(bd, 5);
41201 if (t < DUK__BITPACK_LETTER_LIMIT) {
41202 t = t + DUK_ASC_UC_A + mode;
41203 } else if (t == DUK__BITPACK_UNDERSCORE) {
41205 } else if (t == DUK__BITPACK_FF) {
41206 /* Internal keys are prefixed with 0xFF in the stringtable
41207 * (which makes them invalid UTF-8 on purpose).
41208 */
41209 t = 0xff;
41210 } else if (t == DUK__BITPACK_SWITCH1) {
41211 t = duk_bd_decode(bd, 5);
41212 DUK_ASSERT_DISABLE(t >= 0); /* unsigned */
41213 DUK_ASSERT(t <= 25);
41214 t = t + DUK_ASC_UC_A + (mode ^ 32);
41215 } else if (t == DUK__BITPACK_SWITCH) {
41216 mode = mode ^ 32;
41217 t = duk_bd_decode(bd, 5);
41218 DUK_ASSERT_DISABLE(t >= 0);
41219 DUK_ASSERT(t <= 25);
41220 t = t + DUK_ASC_UC_A + mode;
41221 } else if (t == DUK__BITPACK_SEVENBIT) {
41222 t = duk_bd_decode(bd, 7);
41223 }
41224 tmp[j] = (duk_uint8_t) t;
41225 }
41226
41227 /* No need to length check string: it will never exceed even
41228 * the 16-bit length maximum.
41229 */
41230 DUK_ASSERT(len <= 0xffffUL);
41231 DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
41232 h = duk_heap_string_intern(heap, tmp, len);
41233 if (!h) {
41234 goto error;
41235 }
41237
41238 /* Special flags checks. Since these strings are always
41239 * reachable and a string cannot appear twice in the string
41240 * table, there's no need to check/set these flags elsewhere.
41241 * The 'internal' flag is set by string intern code.
41242 */
41243 if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
41245 }
41250 }
41251 }
41252
41253 DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
41254
41255 /* XXX: The incref macro takes a thread pointer but doesn't
41256 * use it right now.
41258 DUK_HSTRING_INCREF(_never_referenced_, h);
41259
41260#if defined(DUK_USE_HEAPPTR16)
41261 heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
41262#else
41263 heap->strs[i] = h;
41264#endif
41265 }
41266
41267 return 1;
41268
41269 error:
41270 return 0;
41271}
41272#endif /* DUK_USE_ROM_STRINGS */
41273
41275 duk_hthread *thr;
41276
41277 DUK_DD(DUK_DDPRINT("heap init: alloc heap thread"));
41278 thr = duk_hthread_alloc(heap,
41282 if (!thr) {
41283 DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
41284 return 0;
41285 }
41287#if defined(DUK_USE_ROM_STRINGS)
41288 /* No strs[] pointer. */
41289#else /* DUK_USE_ROM_STRINGS */
41290#if defined(DUK_USE_HEAPPTR16)
41291 thr->strs16 = heap->strs16;
41292#else
41293 thr->strs = heap->strs;
41294#endif
41295#endif /* DUK_USE_ROM_STRINGS */
41296
41297 heap->heap_thread = thr;
41298 DUK_HTHREAD_INCREF(thr, thr); /* Note: first argument not really used */
41299
41300 /* 'thr' is now reachable */
41301
41302 if (!duk_hthread_init_stacks(heap, thr)) {
41303 return 0;
41304 }
41305
41306 /* XXX: this may now fail, and is not handled correctly */
41308
41309 /* default prototype (Note: 'thr' must be reachable) */
41311
41312 return 1;
41313}
41314
41315#if defined(DUK_USE_DEBUG)
41316#define DUK__DUMPSZ(t) do { \
41317 DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
41318 } while (0)
41319
41320/* These is not 100% because format would need to be non-portable "long long".
41321 * Also print out as doubles to catch cases where the "long" type is not wide
41322 * enough; the limits will then not be printed accurately but the magnitude
41323 * will be correct.
41324 */
41325#define DUK__DUMPLM_SIGNED_RAW(t,a,b) do { \
41326 DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
41327 (long) (a), (long) (b), \
41328 (double) (a), (double) (b))); \
41329 } while (0)
41330#define DUK__DUMPLM_UNSIGNED_RAW(t,a,b) do { \
41331 DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
41332 (unsigned long) (a), (unsigned long) (b), \
41333 (double) (a), (double) (b))); \
41334 } while (0)
41335#define DUK__DUMPLM_SIGNED(t) do { \
41336 DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
41337 } while (0)
41338#define DUK__DUMPLM_UNSIGNED(t) do { \
41339 DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
41340 } while (0)
41341
41342DUK_LOCAL void duk__dump_type_sizes(void) {
41343 DUK_D(DUK_DPRINT("sizeof()"));
41344
41345 /* basic platform types */
41346 DUK__DUMPSZ(char);
41347 DUK__DUMPSZ(short);
41348 DUK__DUMPSZ(int);
41349 DUK__DUMPSZ(long);
41350 DUK__DUMPSZ(double);
41351 DUK__DUMPSZ(void *);
41352 DUK__DUMPSZ(size_t);
41353
41354 /* basic types from duk_features.h */
41355 DUK__DUMPSZ(duk_uint8_t);
41356 DUK__DUMPSZ(duk_int8_t);
41357 DUK__DUMPSZ(duk_uint16_t);
41358 DUK__DUMPSZ(duk_int16_t);
41359 DUK__DUMPSZ(duk_uint32_t);
41360 DUK__DUMPSZ(duk_int32_t);
41361 DUK__DUMPSZ(duk_uint64_t);
41362 DUK__DUMPSZ(duk_int64_t);
41363 DUK__DUMPSZ(duk_uint_least8_t);
41364 DUK__DUMPSZ(duk_int_least8_t);
41365 DUK__DUMPSZ(duk_uint_least16_t);
41366 DUK__DUMPSZ(duk_int_least16_t);
41367 DUK__DUMPSZ(duk_uint_least32_t);
41368 DUK__DUMPSZ(duk_int_least32_t);
41369#if defined(DUK_USE_64BIT_OPS)
41370 DUK__DUMPSZ(duk_uint_least64_t);
41371 DUK__DUMPSZ(duk_int_least64_t);
41372#endif
41373 DUK__DUMPSZ(duk_uint_fast8_t);
41374 DUK__DUMPSZ(duk_int_fast8_t);
41375 DUK__DUMPSZ(duk_uint_fast16_t);
41376 DUK__DUMPSZ(duk_int_fast16_t);
41377 DUK__DUMPSZ(duk_uint_fast32_t);
41378 DUK__DUMPSZ(duk_int_fast32_t);
41379#if defined(DUK_USE_64BIT_OPS)
41380 DUK__DUMPSZ(duk_uint_fast64_t);
41381 DUK__DUMPSZ(duk_int_fast64_t);
41382#endif
41383 DUK__DUMPSZ(duk_uintptr_t);
41384 DUK__DUMPSZ(duk_intptr_t);
41385 DUK__DUMPSZ(duk_uintmax_t);
41386 DUK__DUMPSZ(duk_intmax_t);
41387 DUK__DUMPSZ(duk_double_t);
41388
41389 /* important chosen base types */
41390 DUK__DUMPSZ(duk_int_t);
41391 DUK__DUMPSZ(duk_uint_t);
41392 DUK__DUMPSZ(duk_int_fast_t);
41393 DUK__DUMPSZ(duk_uint_fast_t);
41394 DUK__DUMPSZ(duk_small_int_t);
41395 DUK__DUMPSZ(duk_small_uint_t);
41396 DUK__DUMPSZ(duk_small_int_fast_t);
41397 DUK__DUMPSZ(duk_small_uint_fast_t);
41398
41399 /* some derived types */
41400 DUK__DUMPSZ(duk_codepoint_t);
41401 DUK__DUMPSZ(duk_ucodepoint_t);
41402 DUK__DUMPSZ(duk_idx_t);
41403 DUK__DUMPSZ(duk_errcode_t);
41404 DUK__DUMPSZ(duk_uarridx_t);
41405
41406 /* tval */
41407 DUK__DUMPSZ(duk_double_union);
41408 DUK__DUMPSZ(duk_tval);
41409
41410 /* structs from duk_forwdecl.h */
41411 DUK__DUMPSZ(duk_jmpbuf); /* just one 'int' for C++ exceptions */
41412 DUK__DUMPSZ(duk_heaphdr);
41413 DUK__DUMPSZ(duk_heaphdr_string);
41414 DUK__DUMPSZ(duk_hstring);
41415 DUK__DUMPSZ(duk_hstring_external);
41416 DUK__DUMPSZ(duk_hobject);
41417 DUK__DUMPSZ(duk_hcompiledfunction);
41418 DUK__DUMPSZ(duk_hnativefunction);
41419 DUK__DUMPSZ(duk_hthread);
41420 DUK__DUMPSZ(duk_hbuffer);
41421 DUK__DUMPSZ(duk_hbuffer_fixed);
41422 DUK__DUMPSZ(duk_hbuffer_dynamic);
41423 DUK__DUMPSZ(duk_hbuffer_external);
41424 DUK__DUMPSZ(duk_propaccessor);
41425 DUK__DUMPSZ(duk_propvalue);
41426 DUK__DUMPSZ(duk_propdesc);
41427 DUK__DUMPSZ(duk_heap);
41428#if defined(DUK_USE_STRTAB_CHAIN)
41429 DUK__DUMPSZ(duk_strtab_entry);
41430#endif
41431 DUK__DUMPSZ(duk_activation);
41432 DUK__DUMPSZ(duk_catcher);
41433 DUK__DUMPSZ(duk_strcache);
41434 DUK__DUMPSZ(duk_ljstate);
41435 DUK__DUMPSZ(duk_fixedbuffer);
41436 DUK__DUMPSZ(duk_bitdecoder_ctx);
41437 DUK__DUMPSZ(duk_bitencoder_ctx);
41438 DUK__DUMPSZ(duk_token);
41439 DUK__DUMPSZ(duk_re_token);
41440 DUK__DUMPSZ(duk_lexer_point);
41441 DUK__DUMPSZ(duk_lexer_ctx);
41442 DUK__DUMPSZ(duk_compiler_instr);
41443 DUK__DUMPSZ(duk_compiler_func);
41444 DUK__DUMPSZ(duk_compiler_ctx);
41445 DUK__DUMPSZ(duk_re_matcher_ctx);
41446 DUK__DUMPSZ(duk_re_compiler_ctx);
41447}
41448DUK_LOCAL void duk__dump_type_limits(void) {
41449 DUK_D(DUK_DPRINT("limits"));
41450
41451 /* basic types */
41452 DUK__DUMPLM_SIGNED(INT8);
41453 DUK__DUMPLM_UNSIGNED(UINT8);
41454 DUK__DUMPLM_SIGNED(INT_FAST8);
41455 DUK__DUMPLM_UNSIGNED(UINT_FAST8);
41456 DUK__DUMPLM_SIGNED(INT_LEAST8);
41457 DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
41458 DUK__DUMPLM_SIGNED(INT16);
41459 DUK__DUMPLM_UNSIGNED(UINT16);
41460 DUK__DUMPLM_SIGNED(INT_FAST16);
41461 DUK__DUMPLM_UNSIGNED(UINT_FAST16);
41462 DUK__DUMPLM_SIGNED(INT_LEAST16);
41463 DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
41464 DUK__DUMPLM_SIGNED(INT32);
41465 DUK__DUMPLM_UNSIGNED(UINT32);
41466 DUK__DUMPLM_SIGNED(INT_FAST32);
41467 DUK__DUMPLM_UNSIGNED(UINT_FAST32);
41468 DUK__DUMPLM_SIGNED(INT_LEAST32);
41469 DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
41470#if defined(DUK_USE_64BIT_OPS)
41471 DUK__DUMPLM_SIGNED(INT64);
41472 DUK__DUMPLM_UNSIGNED(UINT64);
41473 DUK__DUMPLM_SIGNED(INT_FAST64);
41474 DUK__DUMPLM_UNSIGNED(UINT_FAST64);
41475 DUK__DUMPLM_SIGNED(INT_LEAST64);
41476 DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
41477#endif
41478 DUK__DUMPLM_SIGNED(INTPTR);
41479 DUK__DUMPLM_UNSIGNED(UINTPTR);
41480 DUK__DUMPLM_SIGNED(INTMAX);
41481 DUK__DUMPLM_UNSIGNED(UINTMAX);
41482
41483 /* derived types */
41484 DUK__DUMPLM_SIGNED(INT);
41485 DUK__DUMPLM_UNSIGNED(UINT);
41486 DUK__DUMPLM_SIGNED(INT_FAST);
41487 DUK__DUMPLM_UNSIGNED(UINT_FAST);
41488 DUK__DUMPLM_SIGNED(SMALL_INT);
41489 DUK__DUMPLM_UNSIGNED(SMALL_UINT);
41490 DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
41491 DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
41492}
41493#undef DUK__DUMPSZ
41494#undef DUK__DUMPLM_SIGNED_RAW
41495#undef DUK__DUMPLM_UNSIGNED_RAW
41496#undef DUK__DUMPLM_SIGNED
41497#undef DUK__DUMPLM_UNSIGNED
41498
41499DUK_LOCAL void duk__dump_misc_options(void) {
41500 DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
41501 DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
41502 DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
41503 DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
41504 DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
41505#if defined(DUK_USE_PACKED_TVAL)
41506 DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
41507#else
41508 DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
41509#endif
41510#if defined(DUK_USE_VARIADIC_MACROS)
41511 DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
41512#else
41513 DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
41514#endif
41515#if defined(DUK_USE_INTEGER_LE)
41516 DUK_D(DUK_DPRINT("integer endianness: little"));
41517#elif defined(DUK_USE_INTEGER_ME)
41518 DUK_D(DUK_DPRINT("integer endianness: mixed"));
41519#elif defined(DUK_USE_INTEGER_BE)
41520 DUK_D(DUK_DPRINT("integer endianness: big"));
41521#else
41522 DUK_D(DUK_DPRINT("integer endianness: ???"));
41523#endif
41524#if defined(DUK_USE_DOUBLE_LE)
41525 DUK_D(DUK_DPRINT("IEEE double endianness: little"));
41526#elif defined(DUK_USE_DOUBLE_ME)
41527 DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
41528#elif defined(DUK_USE_DOUBLE_BE)
41529 DUK_D(DUK_DPRINT("IEEE double endianness: big"));
41530#else
41531 DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
41532#endif
41533}
41534#endif /* DUK_USE_DEBUG */
41535
41538 duk_realloc_function realloc_func,
41539 duk_free_function free_func,
41540 void *heap_udata,
41541 duk_fatal_function fatal_func) {
41542 duk_heap *res = NULL;
41543
41544 /* Silence a few global unused warnings here. */
41546
41547 DUK_D(DUK_DPRINT("allocate heap"));
41548
41549 /*
41550 * Debug dump type sizes
41551 */
41552
41553#if defined(DUK_USE_DEBUG)
41554 duk__dump_misc_options();
41555 duk__dump_type_sizes();
41556 duk__dump_type_limits();
41557#endif
41558
41559 /*
41560 * If selftests enabled, run them as early as possible
41561 */
41562#if defined(DUK_USE_SELF_TESTS)
41563 DUK_D(DUK_DPRINT("running self tests"));
41564 duk_selftest_run_tests();
41565 DUK_D(DUK_DPRINT("self tests passed"));
41566#endif
41567
41568 /*
41569 * Computed values (e.g. INFINITY)
41570 */
41571
41572#if defined(DUK_USE_COMPUTED_NAN)
41573 do {
41574 /* Workaround for some exotic platforms where NAN is missing
41575 * and the expression (0.0 / 0.0) does NOT result in a NaN.
41576 * Such platforms use the global 'duk_computed_nan' which must
41577 * be initialized at runtime. Use 'volatile' to ensure that
41578 * the compiler will actually do the computation and not try
41579 * to do constant folding which might result in the original
41580 * problem.
41581 */
41582 volatile double dbl1 = 0.0;
41583 volatile double dbl2 = 0.0;
41584 duk_computed_nan = dbl1 / dbl2;
41585 } while (0);
41586#endif
41587
41588#if defined(DUK_USE_COMPUTED_INFINITY)
41589 do {
41590 /* Similar workaround for INFINITY. */
41591 volatile double dbl1 = 1.0;
41592 volatile double dbl2 = 0.0;
41593 duk_computed_infinity = dbl1 / dbl2;
41594 } while (0);
41595#endif
41596
41597 /*
41598 * Allocate heap struct
41599 *
41600 * Use a raw call, all macros expect the heap to be initialized
41601 */
41602
41603 res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
41604 if (!res) {
41605 goto error;
41606 }
41607
41608 /*
41609 * Zero the struct, and start initializing roughly in order
41610 */
41611
41612 DUK_MEMZERO(res, sizeof(*res));
41613
41614 /* explicit NULL inits */
41615#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41616 res->heap_udata = NULL;
41617 res->heap_allocated = NULL;
41618#if defined(DUK_USE_REFERENCE_COUNTING)
41619 res->refzero_list = NULL;
41620 res->refzero_list_tail = NULL;
41621#endif
41622#if defined(DUK_USE_MARK_AND_SWEEP)
41623 res->finalize_list = NULL;
41624#endif
41625 res->heap_thread = NULL;
41626 res->curr_thread = NULL;
41627 res->heap_object = NULL;
41628#if defined(DUK_USE_STRTAB_CHAIN)
41629 /* nothing to NULL */
41630#elif defined(DUK_USE_STRTAB_PROBE)
41631#if defined(DUK_USE_HEAPPTR16)
41632 res->strtable16 = (duk_uint16_t *) NULL;
41633#else
41634 res->strtable = (duk_hstring **) NULL;
41635#endif
41636#endif
41637#if defined(DUK_USE_ROM_STRINGS)
41638 /* no res->strs[] */
41639#else /* DUK_USE_ROM_STRINGS */
41640#if defined(DUK_USE_HEAPPTR16)
41641 /* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
41642#else
41643 {
41645 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
41646 res->strs[i] = NULL;
41647 }
41648 }
41649#endif
41650#endif /* DUK_USE_ROM_STRINGS */
41651#if defined(DUK_USE_DEBUGGER_SUPPORT)
41652 res->dbg_read_cb = NULL;
41653 res->dbg_write_cb = NULL;
41654 res->dbg_peek_cb = NULL;
41655 res->dbg_read_flush_cb = NULL;
41656 res->dbg_write_flush_cb = NULL;
41657 res->dbg_request_cb = NULL;
41658 res->dbg_udata = NULL;
41659 res->dbg_step_thread = NULL;
41660#endif
41661#endif /* DUK_USE_EXPLICIT_NULL_INIT */
41662
41663 res->alloc_func = alloc_func;
41664 res->realloc_func = realloc_func;
41665 res->free_func = free_func;
41666 res->heap_udata = heap_udata;
41667 res->fatal_func = fatal_func;
41668
41669#if defined(DUK_USE_HEAPPTR16)
41670 /* XXX: zero assumption */
41671 res->heapptr_null16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) NULL);
41672 res->heapptr_deleted16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) DUK_STRTAB_DELETED_MARKER(res));
41673#endif
41674
41675 /* res->mark_and_sweep_trigger_counter == 0 -> now causes immediate GC; which is OK */
41676
41677 res->call_recursion_depth = 0;
41679
41680 /* XXX: use the pointer as a seed for now: mix in time at least */
41681
41682 /* The casts through duk_intr_pt is to avoid the following GCC warning:
41683 *
41684 * warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
41685 *
41686 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
41687 */
41688#if defined(DUK_USE_ROM_STRINGS)
41689 /* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
41690 DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
41691 res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
41692#else /* DUK_USE_ROM_STRINGS */
41693 res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
41694 res->rnd_state = (duk_uint32_t) (duk_intptr_t) res;
41695#if !defined(DUK_USE_STRHASH_DENSE)
41696 res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
41697#endif
41698#endif /* DUK_USE_ROM_STRINGS */
41699
41700#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41701 res->lj.jmpbuf_ptr = NULL;
41702#endif
41703 DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN); /* zero */
41704
41707
41708#if (DUK_STRTAB_INITIAL_SIZE < DUK_UTIL_MIN_HASH_PRIME)
41709#error initial heap stringtable size is defined incorrectly
41710#endif
41711
41712 /*
41713 * Init stringtable: fixed variant
41714 */
41715
41716#if defined(DUK_USE_STRTAB_CHAIN)
41718#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41719 {
41721 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
41722#if defined(DUK_USE_HEAPPTR16)
41723 res->strtable[i].u.str16 = res->heapptr_null16;
41724#else
41725 res->strtable[i].u.str = NULL;
41726#endif
41727 }
41728 }
41729#endif /* DUK_USE_EXPLICIT_NULL_INIT */
41730#endif /* DUK_USE_STRTAB_CHAIN */
41731
41732 /*
41733 * Init stringtable: probe variant
41734 */
41735
41736#if defined(DUK_USE_STRTAB_PROBE)
41737#if defined(DUK_USE_HEAPPTR16)
41738 res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
41739 if (!res->strtable16) {
41740 goto error;
41741 }
41742#else /* DUK_USE_HEAPPTR16 */
41743 res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
41744 if (!res->strtable) {
41745 goto error;
41746 }
41747#endif /* DUK_USE_HEAPPTR16 */
41749#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41750 {
41753 for (i = 0; i < DUK_STRTAB_INITIAL_SIZE; i++) {
41754#if defined(DUK_USE_HEAPPTR16)
41755 res->strtable16[i] = res->heapptr_null16;
41756#else
41757 res->strtable[i] = NULL;
41758#endif
41759 }
41760 }
41761#else /* DUK_USE_EXPLICIT_NULL_INIT */
41762#if defined(DUK_USE_HEAPPTR16)
41763 DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
41764#else
41766#endif
41767#endif /* DUK_USE_EXPLICIT_NULL_INIT */
41768#endif /* DUK_USE_STRTAB_PROBE */
41769
41770 /*
41771 * Init stringcache
41772 */
41773
41774#if defined(DUK_USE_EXPLICIT_NULL_INIT)
41775 {
41777 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
41778 res->strcache[i].h = NULL;
41779 }
41780 }
41781#endif
41782
41783 /* XXX: error handling is incomplete. It would be cleanest if
41784 * there was a setjmp catchpoint, so that all init code could
41785 * freely throw errors. If that were the case, the return code
41786 * passing here could be removed.
41787 */
41788
41789 /*
41790 * Init built-in strings
41791 */
41792
41793 DUK_DD(DUK_DDPRINT("HEAP: INIT STRINGS"));
41794 if (!duk__init_heap_strings(res)) {
41795 goto error;
41796 }
41797
41798 /*
41799 * Init the heap thread
41800 */
41801
41802 DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP THREAD"));
41803 if (!duk__init_heap_thread(res)) {
41804 goto error;
41805 }
41806
41807 /*
41808 * Init the heap object
41809 */
41810
41811 DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP OBJECT"));
41812 DUK_ASSERT(res->heap_thread != NULL);
41815 if (!res->heap_object) {
41816 goto error;
41817 }
41819
41820 /*
41821 * All done
41822 */
41823
41824 DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
41825 return res;
41826
41827 error:
41828 DUK_D(DUK_DPRINT("heap allocation failed"));
41829
41830 if (res) {
41831 /* assumes that allocated pointers and alloc funcs are valid
41832 * if res exists
41833 */
41834 DUK_ASSERT(res->alloc_func != NULL);
41835 DUK_ASSERT(res->realloc_func != NULL);
41836 DUK_ASSERT(res->free_func != NULL);
41837 duk_heap_free(res);
41838 }
41839 return NULL;
41840}
41841
41842#undef DUK__BITPACK_LETTER_LIMIT
41843#undef DUK__BITPACK_UNDERSCORE
41844#undef DUK__BITPACK_FF
41845#undef DUK__BITPACK_SWITCH1
41846#undef DUK__BITPACK_SWITCH
41847#undef DUK__BITPACK_SEVENBIT
41848#undef DUK__FIXED_HASH_SEED
41849#line 1 "duk_heap_hashstring.c"
41850/*
41851 * String hash computation (interning).
41852 *
41853 * String hashing is performance critical because a string hash is computed
41854 * for all new strings which are candidates to be added to the string table.
41855 * However, strings actually added to the string table go through a codepoint
41856 * length calculation which dominates performance because it goes through
41857 * every byte of the input string (but only for strings added).
41858 *
41859 * The string hash algorithm should be fast, but on the other hand provide
41860 * good enough hashes to ensure both string table and object property table
41861 * hash tables work reasonably well (i.e., there aren't too many collisions
41862 * with real world inputs). Unless the hash is cryptographic, it's always
41863 * possible to craft inputs with maximal hash collisions.
41864 *
41865 * NOTE: The hash algorithms must match src/dukutil.py:duk_heap_hashstring()
41866 * for ROM string support!
41867 */
41868
41869/* include removed: duk_internal.h */
41870
41871#if defined(DUK_USE_STRHASH_DENSE)
41872/* Constants for duk_hashstring(). */
41873#define DUK__STRHASH_SHORTSTRING 4096L
41874#define DUK__STRHASH_MEDIUMSTRING (256L * 1024L)
41875#define DUK__STRHASH_BLOCKSIZE 256L
41876
41877DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
41878 duk_uint32_t hash;
41879
41880 /* Use Murmurhash2 directly for short strings, and use "block skipping"
41881 * for long strings: hash an initial part and then sample the rest of
41882 * the string with reasonably sized chunks. An initial offset for the
41883 * sampling is computed based on a hash of the initial part of the string;
41884 * this is done to (usually) avoid the case where all long strings have
41885 * certain offset ranges which are never sampled.
41886 *
41887 * Skip should depend on length and bound the total time to roughly
41888 * logarithmic. With current values:
41889 *
41890 * 1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
41891 * 1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
41892 *
41893 * XXX: It would be better to compute the skip offset more "smoothly"
41894 * instead of having a few boundary values.
41895 */
41896
41897 /* note: mixing len into seed improves hashing when skipping */
41898 duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
41899
41900 if (len <= DUK__STRHASH_SHORTSTRING) {
41901 hash = duk_util_hashbytes(str, len, str_seed);
41902 } else {
41903 duk_size_t off;
41904 duk_size_t skip;
41905
41906 if (len <= DUK__STRHASH_MEDIUMSTRING) {
41907 skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
41908 } else {
41909 skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
41910 }
41911
41912 hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
41913 off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
41914
41915 /* XXX: inefficient loop */
41916 while (off < len) {
41917 duk_size_t left = len - off;
41918 duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
41919 hash ^= duk_util_hashbytes(str + off, now, str_seed);
41920 off += skip;
41921 }
41922 }
41923
41924#if defined(DUK_USE_STRHASH16)
41925 /* Truncate to 16 bits here, so that a computed hash can be compared
41926 * against a hash stored in a 16-bit field.
41927 */
41928 hash &= 0x0000ffffUL;
41929#endif
41930 return hash;
41931}
41932
41933#undef DUK__STRHASH_SHORTSTRING
41934#undef DUK__STRHASH_MEDIUMSTRING
41935#undef DUK__STRHASH_BLOCKSIZE
41936#else /* DUK_USE_STRHASH_DENSE */
41937DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
41938 duk_uint32_t hash;
41939 duk_size_t step;
41940 duk_size_t off;
41941
41942 /* Slightly modified "Bernstein hash" from:
41943 *
41944 * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
41945 *
41946 * Modifications: string skipping and reverse direction similar to
41947 * Lua 5.1.5, and different hash initializer.
41948 *
41949 * The reverse direction ensures last byte it always included in the
41950 * hash which is a good default as changing parts of the string are
41951 * more often in the suffix than in the prefix.
41952 */
41953
41954 hash = heap->hash_seed ^ ((duk_uint32_t) len); /* Bernstein hash init value is normally 5381 */
41955 step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
41956 for (off = len; off >= step; off -= step) {
41957 DUK_ASSERT(off >= 1); /* off >= step, and step >= 1 */
41958 hash = (hash * 33) + str[off - 1];
41959 }
41960
41961#if defined(DUK_USE_STRHASH16)
41962 /* Truncate to 16 bits here, so that a computed hash can be compared
41963 * against a hash stored in a 16-bit field.
41964 */
41965 hash &= 0x0000ffffUL;
41966#endif
41967 return hash;
41968}
41969#endif /* DUK_USE_STRHASH_DENSE */
41970#line 1 "duk_heap_markandsweep.c"
41971/*
41972 * Mark-and-sweep garbage collection.
41974
41975/* include removed: duk_internal.h */
41976
41977#ifdef DUK_USE_MARK_AND_SWEEP
41978
41981
41982/*
41983 * Misc
41985
41986/* Select a thread for mark-and-sweep use.
41987 *
41988 * XXX: This needs to change later.
41989 */
41991 if (heap->curr_thread) {
41992 return heap->curr_thread;
41993 }
41994 return heap->heap_thread; /* may be NULL, too */
41995}
41996
41997/*
41998 * Marking functions for heap types: mark children recursively
41999 */
42000
42002 DUK_UNREF(heap);
42003 DUK_UNREF(h);
42004
42005 DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
42006 DUK_ASSERT(h);
42007
42008 /* nothing to process */
42009}
42010
42013
42014 DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
42015
42016 DUK_ASSERT(h);
42017
42018 /* XXX: use advancing pointers instead of index macros -> faster and smaller? */
42019
42020 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
42021 duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
42022 if (!key) {
42023 continue;
42024 }
42025 duk__mark_heaphdr(heap, (duk_heaphdr *) key);
42026 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
42027 duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
42028 duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
42029 } else {
42030 duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
42031 }
42032 }
42033
42034 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
42036 }
42037
42038 /* hash part is a 'weak reference' and does not contribute */
42039
42041
42044 duk_tval *tv, *tv_end;
42045 duk_hobject **fn, **fn_end;
42046
42047 /* 'data' is reachable through every compiled function which
42048 * contains a reference.
42049 */
42050
42052
42053 if (DUK_HCOMPILEDFUNCTION_GET_DATA(heap, f) != NULL) {
42055 tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap, f);
42056 while (tv < tv_end) {
42057 duk__mark_tval(heap, tv);
42058 tv++;
42059 }
42060
42062 fn_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, f);
42063 while (fn < fn_end) {
42064 duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
42065 fn++;
42066 }
42067 } else {
42068 /* May happen in some out-of-memory corner cases. */
42069 DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping marking"));
42070 }
42071 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
42073 DUK_UNREF(f);
42074 /* nothing to mark */
42075 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
42077 duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
42078 } else if (DUK_HOBJECT_IS_THREAD(h)) {
42079 duk_hthread *t = (duk_hthread *) h;
42080 duk_tval *tv;
42081
42082 tv = t->valstack;
42083 while (tv < t->valstack_top) {
42084 duk__mark_tval(heap, tv);
42085 tv++;
42086 }
42087
42088 for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
42089 duk_activation *act = t->callstack + i;
42091 duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
42092 duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
42093#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
42094 duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
42095#endif
42096 }
42098#if 0 /* nothing now */
42099 for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
42100 duk_catcher *cat = t->catchstack + i;
42101 }
42102#endif
42103
42105
42106 /* XXX: duk_small_uint_t would be enough for this loop */
42107 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
42108 duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
42109 }
42110 }
42111}
42112
42113/* recursion tracking happens here only */
42115 DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
42116 (void *) h,
42117 (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
42118 if (!h) {
42119 return;
42120 }
42121#if defined(DUK_USE_ROM_OBJECTS)
42122 if (DUK_HEAPHDR_HAS_READONLY(h)) {
42123 DUK_DDD(DUK_DDDPRINT("readonly object %p, skip", (void *) h));
42124 return;
42125 }
42126#endif
42128 DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
42129 return;
42130 }
42132
42134 /* log this with a normal debug level because this should be relatively rare */
42135 DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
42138 return;
42139 }
42140
42142
42143 switch ((int) DUK_HEAPHDR_GET_TYPE(h)) {
42145 duk__mark_hstring(heap, (duk_hstring *) h);
42146 break;
42147 case DUK_HTYPE_OBJECT:
42148 duk__mark_hobject(heap, (duk_hobject *) h);
42149 break;
42150 case DUK_HTYPE_BUFFER:
42151 /* nothing to mark */
42152 break;
42153 default:
42154 DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
42156 }
42157
42159}
42160
42161DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
42162 DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
42163 if (!tv) {
42164 return;
42165 }
42168 }
42169}
42170
42171/*
42172 * Mark the heap.
42173 */
42174
42177
42178 DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
42179
42180 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
42181 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
42182
42183 for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
42184 duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
42185 duk__mark_heaphdr(heap, (duk_heaphdr *) h);
42186 }
42187
42188 duk__mark_tval(heap, &heap->lj.value1);
42189 duk__mark_tval(heap, &heap->lj.value2);
42190
42191#if defined(DUK_USE_DEBUGGER_SUPPORT)
42192 for (i = 0; i < heap->dbg_breakpoint_count; i++) {
42193 duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
42194 }
42195#endif
42196}
42197
42198/*
42199 * Mark refzero_list objects.
42200 *
42201 * Objects on the refzero_list have no inbound references. They might have
42202 * outbound references to objects that we might free, which would invalidate
42203 * any references held by the refzero objects. A refzero object might also
42204 * be rescued by refcount finalization. Refzero objects are treated as
42205 * reachability roots to ensure they (or anything they point to) are not
42206 * freed in mark-and-sweep.
42207 */
42208
42209#ifdef DUK_USE_REFERENCE_COUNTING
42211 duk_heaphdr *hdr;
42212
42213 DUK_DD(DUK_DDPRINT("duk__mark_refzero_list: %p", (void *) heap));
42214
42215 hdr = heap->refzero_list;
42216 while (hdr) {
42217 duk__mark_heaphdr(heap, hdr);
42218 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42219 }
42220}
42221#endif
42222
42223/*
42224 * Mark unreachable, finalizable objects.
42225 *
42226 * Such objects will be moved aside and their finalizers run later. They have
42227 * to be treated as reachability roots for their properties etc to remain
42228 * allocated. This marking is only done for unreachable values which would
42229 * be swept later (refzero_list is thus excluded).
42230 *
42231 * Objects are first marked FINALIZABLE and only then marked as reachability
42232 * roots; otherwise circular references might be handled inconsistently.
42233 */
42234
42236 duk_hthread *thr;
42237 duk_heaphdr *hdr;
42238 duk_size_t count_finalizable = 0;
42239
42240 DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
42241
42242 thr = duk__get_temp_hthread(heap);
42243 DUK_ASSERT(thr != NULL);
42244
42245 hdr = heap->heap_allocated;
42246 while (hdr) {
42247 /* A finalizer is looked up from the object and up its prototype chain
42248 * (which allows inherited finalizers). A prototype loop must not cause
42249 * an error to be thrown here; duk_hobject_hasprop_raw() will ignore a
42250 * prototype loop silently and indicate that the property doesn't exist.
42251 */
42252
42253 if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
42257
42258 /* heaphdr:
42259 * - is not reachable
42260 * - is an object
42261 * - is not a finalized object
42262 * - has a finalizer
42263 */
42264
42265 DUK_DD(DUK_DDPRINT("unreachable heap object will be "
42266 "finalized -> mark as finalizable "
42267 "and treat as a reachability root: %p",
42268 (void *) hdr));
42271 count_finalizable ++;
42272 }
42273
42274 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42275 }
42276
42277 if (count_finalizable == 0) {
42278 return;
42279 }
42280
42281 DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
42282 (long) count_finalizable));
42283
42284 hdr = heap->heap_allocated;
42285 while (hdr) {
42286 if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
42287 duk__mark_heaphdr(heap, hdr);
42288 }
42289
42290 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42291 }
42292
42293 /* Caller will finish the marking process if we hit a recursion limit. */
42294}
42295
42296/*
42297 * Mark objects on finalize_list.
42298 *
42299 */
42300
42302 duk_heaphdr *hdr;
42303#ifdef DUK_USE_DEBUG
42304 duk_size_t count_finalize_list = 0;
42305#endif
42306
42307 DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
42308
42309 hdr = heap->finalize_list;
42310 while (hdr) {
42311 duk__mark_heaphdr(heap, hdr);
42312 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42313#ifdef DUK_USE_DEBUG
42314 count_finalize_list++;
42315#endif
42316 }
42317
42318#ifdef DUK_USE_DEBUG
42319 if (count_finalize_list > 0) {
42320 DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
42321 (long) count_finalize_list));
42322 }
42323#endif
42324}
42325
42327 * Fallback marking handler if recursion limit is reached.
42328 *
42329 * Iterates 'temproots' until recursion limit is no longer hit. Note
42330 * that temproots may reside either in heap allocated list or the
42331 * refzero work list. This is a slow scan, but guarantees that we
42332 * finish with a bounded C stack.
42333 *
42334 * Note that nodes may have been marked as temproots before this
42335 * scan begun, OR they may have been marked during the scan (as
42336 * we process nodes recursively also during the scan). This is
42337 * intended behavior.
42338 */
42339
42340#ifdef DUK_USE_DEBUG
42342#else
42344#endif
42345 if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
42346 DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
42347 return;
42348 }
42349
42350 DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
42352 DUK_HEAPHDR_CLEAR_REACHABLE(hdr); /* done so that duk__mark_heaphdr() works correctly */
42353 duk__mark_heaphdr(heap, hdr);
42354
42355#ifdef DUK_USE_DEBUG
42356 (*count)++;
42357#endif
42358}
42359
42361 duk_heaphdr *hdr;
42362#ifdef DUK_USE_DEBUG
42363 duk_size_t count;
42364#endif
42365
42366 DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
42367
42369 DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
42370
42371#ifdef DUK_USE_DEBUG
42372 count = 0;
42373#endif
42375
42376 hdr = heap->heap_allocated;
42377 while (hdr) {
42378#ifdef DUK_USE_DEBUG
42379 duk__handle_temproot(heap, hdr, &count);
42380#else
42381 duk__handle_temproot(heap, hdr);
42382#endif
42383 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42384 }
42385
42386 /* must also check refzero_list */
42387#ifdef DUK_USE_REFERENCE_COUNTING
42388 hdr = heap->refzero_list;
42389 while (hdr) {
42390#ifdef DUK_USE_DEBUG
42391 duk__handle_temproot(heap, hdr, &count);
42392#else
42393 duk__handle_temproot(heap, hdr);
42394#endif
42395 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42396 }
42397#endif /* DUK_USE_REFERENCE_COUNTING */
42399#ifdef DUK_USE_DEBUG
42400 DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
42401#endif
42402 }
42403}
42404
42405/*
42406 * Finalize refcounts for heap elements just about to be freed.
42407 * This must be done for all objects before freeing to avoid any
42408 * stale pointer dereferences.
42409 *
42410 * Note that this must deduce the set of objects to be freed
42411 * identically to duk__sweep_heap().
42412 */
42413
42414#ifdef DUK_USE_REFERENCE_COUNTING
42416 duk_hthread *thr;
42417 duk_heaphdr *hdr;
42418
42419 thr = duk__get_temp_hthread(heap);
42420 DUK_ASSERT(thr != NULL);
42421
42422 DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p, hthread=%p",
42423 (void *) heap, (void *) thr));
42424
42425 hdr = heap->heap_allocated;
42426 while (hdr) {
42427 if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
42428 /*
42429 * Unreachable object about to be swept. Finalize target refcounts
42430 * (objects which the unreachable object points to) without doing
42431 * refzero processing. Recursive decrefs are also prevented when
42432 * refzero processing is disabled.
42433 *
42434 * Value cannot be a finalizable object, as they have been made
42435 * temporarily reachable for this round.
42436 */
42437
42438 DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
42440 }
42441
42442 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42443 }
42444}
42445#endif /* DUK_USE_REFERENCE_COUNTING */
42446
42447/*
42448 * Clear (reachable) flags of refzero work list.
42449 */
42450
42451#ifdef DUK_USE_REFERENCE_COUNTING
42453 duk_heaphdr *hdr;
42454
42455 DUK_DD(DUK_DDPRINT("duk__clear_refzero_list_flags: %p", (void *) heap));
42456
42457 hdr = heap->refzero_list;
42458 while (hdr) {
42463 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42464 }
42465}
42466#endif /* DUK_USE_REFERENCE_COUNTING */
42467
42468/*
42469 * Clear (reachable) flags of finalize_list
42470 *
42471 * We could mostly do in the sweep phase when we move objects from the
42472 * heap into the finalize_list. However, if a finalizer run is skipped
42473 * during a mark-and-sweep, the objects on the finalize_list will be marked
42474 * reachable during the next mark-and-sweep. Since they're already on the
42475 * finalize_list, no-one will be clearing their REACHABLE flag so we do it
42476 * here. (This now overlaps with the sweep handling in a harmless way.)
42477 */
42478
42480 duk_heaphdr *hdr;
42481
42482 DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
42483
42484 hdr = heap->finalize_list;
42485 while (hdr) {
42490 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42491 }
42492}
42493
42494/*
42495 * Sweep stringtable
42496 */
42497
42498#if defined(DUK_USE_STRTAB_CHAIN)
42499
42500/* XXX: skip count_free w/o debug? */
42501#if defined(DUK_USE_HEAPPTR16)
42502DUK_LOCAL void duk__sweep_string_chain16(duk_heap *heap, duk_uint16_t *slot, duk_size_t *count_keep, duk_size_t *count_free) {
42503 duk_uint16_t h16 = *slot;
42504 duk_hstring *h;
42505 duk_uint16_t null16 = heap->heapptr_null16;
42506
42507 if (h16 == null16) {
42508 /* nop */
42509 return;
42510 }
42511 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, h16);
42512 DUK_ASSERT(h != NULL);
42513
42516 (*count_keep)++;
42517 } else {
42518#if defined(DUK_USE_REFERENCE_COUNTING)
42520#endif
42521 /* deal with weak references first */
42523 *slot = null16;
42524
42525 /* free inner references (these exist e.g. when external
42526 * strings are enabled)
42527 */
42528 duk_free_hstring_inner(heap, h);
42529 DUK_FREE(heap, h);
42530 (*count_free)++;
42531 }
42532}
42533#else /* DUK_USE_HEAPPTR16 */
42534DUK_LOCAL void duk__sweep_string_chain(duk_heap *heap, duk_hstring **slot, duk_size_t *count_keep, duk_size_t *count_free) {
42535 duk_hstring *h = *slot;
42536
42537 if (h == NULL) {
42538 /* nop */
42539 return;
42540 }
42541
42544 (*count_keep)++;
42545 } else {
42546#if defined(DUK_USE_REFERENCE_COUNTING)
42548#endif
42549 /* deal with weak references first */
42551 *slot = NULL;
42552
42553 /* free inner references (these exist e.g. when external
42554 * strings are enabled)
42555 */
42556 duk_free_hstring_inner(heap, h);
42557 DUK_FREE(heap, h);
42558 (*count_free)++;
42559 }
42560}
42561#endif /* DUK_USE_HEAPPTR16 */
42562
42563DUK_LOCAL void duk__sweep_stringtable_chain(duk_heap *heap, duk_size_t *out_count_keep) {
42566 duk_size_t count_free = 0;
42567 duk_size_t count_keep = 0;
42568 duk_size_t j, n;
42569#if defined(DUK_USE_HEAPPTR16)
42570 duk_uint16_t *lst;
42571#else
42572 duk_hstring **lst;
42573#endif
42574
42575 DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
42576
42577 /* Non-zero refcounts should not happen for unreachable strings,
42578 * because we refcount finalize all unreachable objects which
42579 * should have decreased unreachable string refcounts to zero
42580 * (even for cycles).
42581 */
42582
42583 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
42584 e = heap->strtable + i;
42585 if (e->listlen == 0) {
42586#if defined(DUK_USE_HEAPPTR16)
42587 duk__sweep_string_chain16(heap, &e->u.str16, &count_keep, &count_free);
42588#else
42589 duk__sweep_string_chain(heap, &e->u.str, &count_keep, &count_free);
42590#endif
42591 } else {
42592#if defined(DUK_USE_HEAPPTR16)
42593 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
42594#else
42595 lst = e->u.strlist;
42596#endif
42597 for (j = 0, n = e->listlen; j < n; j++) {
42598#if defined(DUK_USE_HEAPPTR16)
42599 duk__sweep_string_chain16(heap, lst + j, &count_keep, &count_free);
42600#else
42601 duk__sweep_string_chain(heap, lst + j, &count_keep, &count_free);
42602#endif
42603 }
42604 }
42605 }
42606
42607 DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
42608 (long) count_free, (long) count_keep));
42609 *out_count_keep = count_keep;
42610}
42611#endif /* DUK_USE_STRTAB_CHAIN */
42612
42613#if defined(DUK_USE_STRTAB_PROBE)
42614DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep) {
42615 duk_hstring *h;
42617#ifdef DUK_USE_DEBUG
42618 duk_size_t count_free = 0;
42619#endif
42620 duk_size_t count_keep = 0;
42621
42622 DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
42623
42624 for (i = 0; i < heap->st_size; i++) {
42625#if defined(DUK_USE_HEAPPTR16)
42626 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
42627#else
42628 h = heap->strtable[i];
42629#endif
42630 if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
42631 continue;
42632 } else if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
42634 count_keep++;
42635 continue;
42636 }
42637
42638#ifdef DUK_USE_DEBUG
42639 count_free++;
42640#endif
42641
42642#if defined(DUK_USE_REFERENCE_COUNTING)
42643 /* Non-zero refcounts should not happen for unreachable strings,
42644 * because we refcount finalize all unreachable objects which
42645 * should have decreased unreachable string refcounts to zero
42646 * (even for cycles).
42647 */
42649#endif
42650
42651 DUK_DDD(DUK_DDDPRINT("sweep string, not reachable: %p", (void *) h));
42652
42653 /* deal with weak references first */
42655
42656 /* remove the string (mark DELETED), could also call
42657 * duk_heap_string_remove() but that would be slow and
42658 * pointless because we already know the slot.
42659 */
42660#if defined(DUK_USE_HEAPPTR16)
42661 heap->strtable16[i] = heap->heapptr_deleted16;
42662#else
42663 heap->strtable[i] = DUK_STRTAB_DELETED_MARKER(heap);
42664#endif
42665
42666 /* free inner references (these exist e.g. when external
42667 * strings are enabled)
42668 */
42671 /* finally free the struct itself */
42672 DUK_FREE(heap, h);
42673 }
42674
42675#ifdef DUK_USE_DEBUG
42676 DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
42677 (long) count_free, (long) count_keep));
42678#endif
42679 *out_count_keep = count_keep;
42680}
42681#endif /* DUK_USE_STRTAB_PROBE */
42682
42683/*
42684 * Sweep heap
42685 */
42686
42687DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep) {
42688 duk_heaphdr *prev; /* last element that was left in the heap */
42689 duk_heaphdr *curr;
42691#ifdef DUK_USE_DEBUG
42692 duk_size_t count_free = 0;
42693 duk_size_t count_finalize = 0;
42694 duk_size_t count_rescue = 0;
42695#endif
42696 duk_size_t count_keep = 0;
42697
42698 DUK_UNREF(flags);
42699 DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
42700
42701 prev = NULL;
42702 curr = heap->heap_allocated;
42703 heap->heap_allocated = NULL;
42704 while (curr) {
42705 /* Strings and ROM objects are never placed on the heap allocated list. */
42708
42709 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
42710
42711 if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
42712 /*
42713 * Reachable object, keep
42714 */
42715
42716 DUK_DDD(DUK_DDDPRINT("sweep, reachable: %p", (void *) curr));
42717
42718 if (DUK_HEAPHDR_HAS_FINALIZABLE(curr)) {
42719 /*
42720 * If object has been marked finalizable, move it to the
42721 * "to be finalized" work list. It will be collected on
42722 * the next mark-and-sweep if it is still unreachable
42723 * after running the finalizer.
42724 */
42725
42728 DUK_DDD(DUK_DDDPRINT("object has finalizer, move to finalization work list: %p", (void *) curr));
42729
42730#ifdef DUK_USE_DOUBLE_LINKED_HEAP
42731 if (heap->finalize_list) {
42732 DUK_HEAPHDR_SET_PREV(heap, heap->finalize_list, curr);
42733 }
42734 DUK_HEAPHDR_SET_PREV(heap, curr, NULL);
42735#endif
42736 DUK_HEAPHDR_SET_NEXT(heap, curr, heap->finalize_list);
42737 DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
42738 heap->finalize_list = curr;
42739#ifdef DUK_USE_DEBUG
42740 count_finalize++;
42741#endif
42742 } else {
42743 /*
42744 * Object will be kept; queue object back to heap_allocated (to tail)
42745 */
42746
42747 if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
42748 /*
42749 * Object's finalizer was executed on last round, and
42750 * object has been happily rescued.
42751 */
42752
42755 DUK_DD(DUK_DDPRINT("object rescued during mark-and-sweep finalization: %p", (void *) curr));
42756#ifdef DUK_USE_DEBUG
42757 count_rescue++;
42758#endif
42759 } else {
42760 /*
42761 * Plain, boring reachable object.
42762 */
42763 DUK_DD(DUK_DDPRINT("keep object: %!iO", curr));
42764 count_keep++;
42765 }
42766
42767 if (!heap->heap_allocated) {
42768 heap->heap_allocated = curr;
42769 }
42770 if (prev) {
42771 DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
42772 }
42773#ifdef DUK_USE_DOUBLE_LINKED_HEAP
42774 DUK_HEAPHDR_SET_PREV(heap, curr, prev);
42775#endif
42776 DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
42777 DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
42778 prev = curr;
42779 }
42780
42784
42788
42789 curr = next;
42790 } else {
42791 /*
42792 * Unreachable object, free
42793 */
42794
42795 DUK_DDD(DUK_DDDPRINT("sweep, not reachable: %p", (void *) curr));
42796
42797#if defined(DUK_USE_REFERENCE_COUNTING)
42798 /* Non-zero refcounts should not happen because we refcount
42799 * finalize all unreachable objects which should cancel out
42800 * refcounts (even for cycles).
42801 */
42803#endif
42805
42806 if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
42807 DUK_DDD(DUK_DDDPRINT("finalized object not rescued: %p", (void *) curr));
42808 }
42809
42810 /* Note: object cannot be a finalizable unreachable object, as
42811 * they have been marked temporarily reachable for this round,
42812 * and are handled above.
42813 */
42814
42815#ifdef DUK_USE_DEBUG
42816 count_free++;
42817#endif
42818
42819 /* weak refs should be handled here, but no weak refs for
42820 * any non-string objects exist right now.
42821 */
42822
42823 /* free object and all auxiliary (non-heap) allocs */
42824 duk_heap_free_heaphdr_raw(heap, curr);
42825
42826 curr = next;
42827 }
42829 if (prev) {
42830 DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
42831 }
42832 DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
42833
42834#ifdef DUK_USE_DEBUG
42835 DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
42836 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
42837#endif
42838 *out_count_keep = count_keep;
42839}
42840
42841/*
42842 * Run (object) finalizers in the "to be finalized" work list.
42843 */
42844
42846 duk_heaphdr *curr;
42848#ifdef DUK_USE_DEBUG
42849 duk_size_t count = 0;
42850#endif
42851 duk_hthread *thr;
42852
42853 DUK_DD(DUK_DDPRINT("duk__run_object_finalizers: %p", (void *) heap));
42854
42855 thr = duk__get_temp_hthread(heap);
42856 DUK_ASSERT(thr != NULL);
42857
42858 curr = heap->finalize_list;
42859 while (curr) {
42860 DUK_DDD(DUK_DDDPRINT("mark-and-sweep finalize: %p", (void *) curr));
42861
42862 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* only objects have finalizers */
42863 DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr)); /* flags have been already cleared */
42867 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr)); /* No finalizers for ROM objects */
42868
42869 if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
42870 /* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
42871 * Next mark-and-sweep will collect the object unless it has
42872 * become reachable (i.e. rescued). FINALIZED prevents the
42873 * finalizer from being executed again before that.
42874 */
42875 duk_hobject_run_finalizer(thr, (duk_hobject *) curr); /* must never longjmp */
42877 } else {
42878 /* Used during heap destruction: don't actually run finalizers
42879 * because we're heading into forced finalization. Instead,
42880 * queue finalizable objects back to the heap_allocated list.
42881 */
42882 DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
42884 }
42885
42886 /* queue back to heap_allocated */
42887 next = DUK_HEAPHDR_GET_NEXT(heap, curr);
42889
42890 curr = next;
42891#ifdef DUK_USE_DEBUG
42892 count++;
42893#endif
42894 }
42895
42896 /* finalize_list will always be processed completely */
42897 heap->finalize_list = NULL;
42898
42899#ifdef DUK_USE_DEBUG
42900 DUK_D(DUK_DPRINT("mark-and-sweep finalize objects: %ld finalizers called", (long) count));
42901#endif
42902}
42903
42904/*
42905 * Object compaction.
42906 *
42907 * Compaction is assumed to never throw an error.
42908 */
42909
42911 /* XXX: for threads, compact value stack, call stack, catch stack? */
42912
42913 duk_hobject *obj = duk_get_hobject(ctx, -1);
42914 DUK_ASSERT(obj != NULL);
42916 return 0;
42917}
42918
42919#ifdef DUK_USE_DEBUG
42920DUK_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) {
42921#else
42923#endif
42924 duk_heaphdr *curr;
42925#ifdef DUK_USE_DEBUG
42926 duk_size_t old_size, new_size;
42927#endif
42928 duk_hobject *obj;
42929
42930 DUK_UNREF(heap);
42931
42932 curr = start;
42933 while (curr) {
42934 DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
42935
42937 goto next;
42938 }
42939 obj = (duk_hobject *) curr;
42940
42941#ifdef DUK_USE_DEBUG
42945#endif
42946
42947 DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
42948 duk_push_hobject((duk_context *) thr, obj);
42949 /* XXX: disable error handlers for duration of compaction? */
42951
42952#ifdef DUK_USE_DEBUG
42956#endif
42957
42958#ifdef DUK_USE_DEBUG
42959 (*p_count_compact)++;
42960 (*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
42961#endif
42962
42963 next:
42964 curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
42965#ifdef DUK_USE_DEBUG
42966 (*p_count_check)++;
42967#endif
42968 }
42969}
42970
42972 /* XXX: which lists should participate? to be finalized? */
42973#ifdef DUK_USE_DEBUG
42974 duk_size_t count_check = 0;
42975 duk_size_t count_compact = 0;
42976 duk_size_t count_bytes_saved = 0;
42977#endif
42978 duk_hthread *thr;
42979
42980 DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
42981
42982 thr = duk__get_temp_hthread(heap);
42983 DUK_ASSERT(thr != NULL);
42984
42985#ifdef DUK_USE_DEBUG
42986 duk__compact_object_list(heap, thr, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
42987 duk__compact_object_list(heap, thr, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
42988#ifdef DUK_USE_REFERENCE_COUNTING
42989 duk__compact_object_list(heap, thr, heap->refzero_list, &count_check, &count_compact, &count_bytes_saved);
42990#endif
42991#else
42992 duk__compact_object_list(heap, thr, heap->heap_allocated);
42993 duk__compact_object_list(heap, thr, heap->finalize_list);
42994#ifdef DUK_USE_REFERENCE_COUNTING
42995 duk__compact_object_list(heap, thr, heap->refzero_list);
42996#endif
42997#endif
42998
42999#ifdef DUK_USE_DEBUG
43000 DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
43001 (long) count_check, (long) count_compact, (long) count_bytes_saved));
43002#endif
43003}
43004
43005/*
43006 * Assertion helpers.
43007 */
43008
43009#ifdef DUK_USE_ASSERTIONS
43010DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
43011 duk_heaphdr *hdr;
43012
43013 hdr = heap->heap_allocated;
43014 while (hdr) {
43018 /* may have FINALIZED */
43019 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43020 }
43021
43022#ifdef DUK_USE_REFERENCE_COUNTING
43023 hdr = heap->refzero_list;
43024 while (hdr) {
43029 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43030 }
43031#endif /* DUK_USE_REFERENCE_COUNTING */
43032}
43033
43034#ifdef DUK_USE_REFERENCE_COUNTING
43035DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
43036 duk_heaphdr *hdr = heap->heap_allocated;
43037 while (hdr) {
43038 if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
43040 /* An object may be in heap_allocated list with a zero
43041 * refcount if it has just been finalized and is waiting
43042 * to be collected by the next cycle.
43043 */
43044 } else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
43045 /* An object may be in heap_allocated list with a zero
43046 * refcount also if it is a temporary object created by
43047 * a finalizer; because finalization now runs inside
43048 * mark-and-sweep, such objects will not be queued to
43049 * refzero_list and will thus appear here with refcount
43050 * zero.
43051 */
43052#if 0 /* this case can no longer occur because refcount is unsigned */
43053 } else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) < 0) {
43054 DUK_D(DUK_DPRINT("invalid refcount: %ld, %p -> %!O",
43055 (hdr != NULL ? (long) DUK_HEAPHDR_GET_REFCOUNT(hdr) : (long) 0),
43056 (void *) hdr, (duk_heaphdr *) hdr));
43058#endif
43059 }
43060 hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43061 }
43062}
43063#endif /* DUK_USE_REFERENCE_COUNTING */
43064#endif /* DUK_USE_ASSERTIONS */
43065
43066/*
43067 * Finalizer torture. Do one fake finalizer call which causes side effects
43068 * similar to one or more finalizers on actual objects.
43069 */
43070
43071#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
43072DUK_LOCAL duk_ret_t duk__markandsweep_fake_finalizer(duk_context *ctx) {
43073 DUK_D(DUK_DPRINT("fake mark-and-sweep torture finalizer executed"));
43074
43075 /* Require a lot of stack to force a value stack grow/shrink.
43076 * Recursive mark-and-sweep is prevented by allocation macros
43077 * so this won't trigger another mark-and-sweep.
43078 */
43079 duk_require_stack(ctx, 100000);
43080
43081 /* XXX: do something to force a callstack grow/shrink, perhaps
43082 * just a manual forced resize or a forced relocating realloc?
43083 */
43084
43085 return 0;
43086}
43087
43088DUK_LOCAL void duk__markandsweep_torture_finalizer(duk_hthread *thr) {
43089 duk_context *ctx;
43090 duk_int_t rc;
43091
43092 DUK_ASSERT(thr != NULL);
43093 ctx = (duk_context *) thr;
43094
43095 /* Avoid fake finalization when callstack limit has been reached.
43096 * Otherwise a callstack limit error will be created, then refzero'ed.
43097 */
43099 thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
43100 DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake mark-and-sweep torture finalizer"));
43101 return;
43102 }
43103
43104 /* Run fake finalizer. Avoid creating unnecessary garbage. */
43105 duk_push_c_function(ctx, duk__markandsweep_fake_finalizer, 0 /*nargs*/);
43106 rc = duk_pcall(ctx, 0 /*nargs*/);
43107 DUK_UNREF(rc); /* ignored */
43108 duk_pop(ctx);
43109}
43110#endif /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
43111
43112/*
43113 * Main mark-and-sweep function.
43114 *
43115 * 'flags' represents the features requested by the caller. The current
43116 * heap->mark_and_sweep_base_flags is ORed automatically into the flags;
43117 * the base flags mask typically prevents certain mark-and-sweep operations
43118 * to avoid trouble.
43119 */
43120
43122 duk_hthread *thr;
43123 duk_size_t count_keep_obj;
43124 duk_size_t count_keep_str;
43125#ifdef DUK_USE_VOLUNTARY_GC
43126 duk_size_t tmp;
43127#endif
43128
43129 /* XXX: thread selection for mark-and-sweep is currently a hack.
43130 * If we don't have a thread, the entire mark-and-sweep is now
43131 * skipped (although we could just skip finalizations).
43132 */
43133
43134 /* If thr != NULL, the thr may still be in the middle of
43135 * initialization.
43136 * XXX: Improve the thread viability test.
43137 */
43138 thr = duk__get_temp_hthread(heap);
43139 if (thr == NULL) {
43140 DUK_D(DUK_DPRINT("gc skipped because we don't have a temp thread"));
43141
43142 /* reset voluntary gc trigger count */
43143#ifdef DUK_USE_VOLUNTARY_GC
43145#endif
43146 return 0; /* OK */
43147 }
43148
43149 /* If debugger is paused, garbage collection is disabled by default. */
43150 /* XXX: will need a force flag if garbage collection is triggered
43151 * explicitly during paused state.
43152 */
43153#if defined(DUK_USE_DEBUGGER_SUPPORT)
43154 if (DUK_HEAP_IS_PAUSED(heap)) {
43155 /* Checking this here rather that in memory alloc primitives
43156 * reduces checking code there but means a failed allocation
43157 * will go through a few retries before giving up. That's
43158 * fine because this only happens during debugging.
43159 */
43160 DUK_D(DUK_DPRINT("gc skipped because debugger is paused"));
43161 return 0;
43162 }
43163#endif
43164
43165 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
43166 (unsigned long) flags, (unsigned long) (flags | heap->mark_and_sweep_base_flags)));
43167
43168 flags |= heap->mark_and_sweep_base_flags;
43169
43170 /*
43171 * Assertions before
43172 */
43173
43174#ifdef DUK_USE_ASSERTIONS
43178 duk__assert_heaphdr_flags(heap);
43179#ifdef DUK_USE_REFERENCE_COUNTING
43180 /* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
43181 * finalizer may trigger a mark-and-sweep.
43182 */
43183 duk__assert_valid_refcounts(heap);
43184#endif /* DUK_USE_REFERENCE_COUNTING */
43185#endif /* DUK_USE_ASSERTIONS */
43186
43187 /*
43188 * Begin
43189 */
43190
43192
43193 /*
43194 * Mark roots, hoping that recursion limit is not normally hit.
43195 * If recursion limit is hit, run additional reachability rounds
43196 * starting from "temproots" until marking is complete.
43197 *
43198 * Marking happens in two phases: first we mark actual reachability
43199 * roots (and run "temproots" to complete the process). Then we
43200 * check which objects are unreachable and are finalizable; such
43201 * objects are marked as FINALIZABLE and marked as reachability
43202 * (and "temproots" is run again to complete the process).
43203 *
43204 * The heap finalize_list must also be marked as a reachability root.
43205 * There may be objects on the list from a previous round if the
43206 * previous run had finalizer skip flag.
43207 */
43208
43209 duk__mark_roots_heap(heap); /* main reachability roots */
43210#ifdef DUK_USE_REFERENCE_COUNTING
43211 duk__mark_refzero_list(heap); /* refzero_list treated as reachability roots */
43212#endif
43213 duk__mark_temproots_by_heap_scan(heap); /* temproots */
43214
43215 duk__mark_finalizable(heap); /* mark finalizable as reachability roots */
43216 duk__mark_finalize_list(heap); /* mark finalizer work list as reachability roots */
43217 duk__mark_temproots_by_heap_scan(heap); /* temproots */
43218
43219 /*
43220 * Sweep garbage and remove marking flags, and move objects with
43221 * finalizers to the finalizer work list.
43222 *
43223 * Objects to be swept need to get their refcounts finalized before
43224 * they are swept. In other words, their target object refcounts
43225 * need to be decreased. This has to be done before freeing any
43226 * objects to avoid decref'ing dangling pointers (which may happen
43227 * even without bugs, e.g. with reference loops)
43228 *
43229 * Because strings don't point to other heap objects, similar
43230 * finalization is not necessary for strings.
43231 */
43232
43233 /* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
43234
43235#ifdef DUK_USE_REFERENCE_COUNTING
43237#endif
43238 duk__sweep_heap(heap, flags, &count_keep_obj);
43239#if defined(DUK_USE_STRTAB_CHAIN)
43240 duk__sweep_stringtable_chain(heap, &count_keep_str);
43241#elif defined(DUK_USE_STRTAB_PROBE)
43242 duk__sweep_stringtable_probe(heap, &count_keep_str);
43243#else
43244#error internal error, invalid strtab options
43245#endif
43246#ifdef DUK_USE_REFERENCE_COUNTING
43248#endif
43250
43251 /*
43252 * Object compaction (emergency only).
43253 *
43254 * Object compaction is a separate step after sweeping, as there is
43255 * more free memory for it to work with. Also, currently compaction
43256 * may insert new objects into the heap allocated list and the string
43257 * table which we don't want to do during a sweep (the reachability
43258 * flags of such objects would be incorrect). The objects inserted
43259 * are currently:
43260 *
43261 * - a temporary duk_hbuffer for a new properties allocation
43262 * - if array part is abandoned, string keys are interned
43263 *
43264 * The object insertions go to the front of the list, so they do not
43265 * cause an infinite loop (they are not compacted).
43266 */
43267
43268 if ((flags & DUK_MS_FLAG_EMERGENCY) &&
43271 }
43272
43273 /*
43274 * String table resize check.
43275 *
43276 * Note: this may silently (and safely) fail if GC is caused by an
43277 * allocation call in stringtable resize_hash(). Resize_hash()
43278 * will prevent a recursive call to itself by setting the
43279 * DUK_MS_FLAG_NO_STRINGTABLE_RESIZE in heap->mark_and_sweep_base_flags.
43280 */
43281
43282 /* XXX: stringtable emergency compaction? */
43283
43284 /* XXX: remove this feature entirely? it would only matter for
43285 * emergency GC. Disable for lowest memory builds.
43286 */
43287#if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
43288 if (!(flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE)) {
43289 DUK_DD(DUK_DDPRINT("resize stringtable: %p", (void *) heap));
43291 } else {
43292 DUK_D(DUK_DPRINT("stringtable resize skipped because DUK_MS_FLAG_NO_STRINGTABLE_RESIZE is set"));
43293 }
43294#endif
43295
43296 /*
43297 * Finalize objects in the finalization work list. Finalized
43298 * objects are queued back to heap_allocated with FINALIZED set.
43299 *
43300 * Since finalizers may cause arbitrary side effects, they are
43301 * prevented during string table and object property allocation
43302 * resizing using the DUK_MS_FLAG_NO_FINALIZERS flag in
43303 * heap->mark_and_sweep_base_flags. In this case the objects
43304 * remain in the finalization work list after mark-and-sweep
43305 * exits and they may be finalized on the next pass.
43306 *
43307 * Finalization currently happens inside "MARKANDSWEEP_RUNNING"
43308 * protection (no mark-and-sweep may be triggered by the
43309 * finalizers). As a side effect:
43310 *
43311 * 1) an out-of-memory error inside a finalizer will not
43312 * cause a mark-and-sweep and may cause the finalizer
43313 * to fail unnecessarily
43314 *
43315 * 2) any temporary objects whose refcount decreases to zero
43316 * during finalization will not be put into refzero_list;
43317 * they can only be collected by another mark-and-sweep
43318 *
43319 * This is not optimal, but since the sweep for this phase has
43320 * already happened, this is probably good enough for now.
43321 */
43322
43323#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
43324 /* Cannot simulate individual finalizers because finalize_list only
43325 * contains objects with actual finalizers. But simulate side effects
43326 * from finalization by doing a bogus function call and resizing the
43327 * stacks.
43328 */
43329 if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
43330 DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, DUK_MS_FLAG_NO_FINALIZERS is set"));
43331 } else if (!(thr->valstack != NULL && thr->callstack != NULL && thr->catchstack != NULL)) {
43332 DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, thread not yet viable"));
43333 } else {
43334 DUK_D(DUK_DPRINT("run mark-and-sweep torture finalizer"));
43335 duk__markandsweep_torture_finalizer(thr);
43336 }
43337#endif /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
43338
43339 if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
43340 DUK_D(DUK_DPRINT("finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set"));
43341 } else {
43342 duk__run_object_finalizers(heap, flags);
43343 }
43344
43345 /*
43346 * Finish
43347 */
43348
43350
43351 /*
43352 * Assertions after
43353 */
43354
43355#ifdef DUK_USE_ASSERTIONS
43359 duk__assert_heaphdr_flags(heap);
43360#ifdef DUK_USE_REFERENCE_COUNTING
43361 /* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
43362 * finalizer may trigger a mark-and-sweep.
43363 */
43364 duk__assert_valid_refcounts(heap);
43365#endif /* DUK_USE_REFERENCE_COUNTING */
43366#endif /* DUK_USE_ASSERTIONS */
43367
43368 /*
43369 * Reset trigger counter
43370 */
43371
43372#ifdef DUK_USE_VOLUNTARY_GC
43373 tmp = (count_keep_obj + count_keep_str) / 256;
43377 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
43378 (long) count_keep_obj, (long) count_keep_str, (long) heap->mark_and_sweep_trigger_counter));
43379#else
43380 DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
43381 (long) count_keep_obj, (long) count_keep_str));
43382#endif
43383
43384 return 0; /* OK */
43385}
43386
43387#else /* DUK_USE_MARK_AND_SWEEP */
43388
43389/* no mark-and-sweep gc */
43390
43391#endif /* DUK_USE_MARK_AND_SWEEP */
43392#line 1 "duk_heap_memory.c"
43393/*
43394 * Memory allocation handling.
43395 */
43396
43397/* include removed: duk_internal.h */
43399/*
43400 * Helpers
43401 *
43402 * The fast path checks are done within a macro to ensure "inlining"
43403 * while the slow path actions use a helper (which won't typically be
43404 * inlined in size optimized builds).
43405 */
43406
43407#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
43408#define DUK__VOLUNTARY_PERIODIC_GC(heap) do { \
43409 (heap)->mark_and_sweep_trigger_counter--; \
43410 if ((heap)->mark_and_sweep_trigger_counter <= 0) { \
43411 duk__run_voluntary_gc(heap); \
43412 } \
43413 } while (0)
43414
43417 DUK_DD(DUK_DDPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
43418 } else {
43419 duk_small_uint_t flags;
43421
43422 DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
43423 flags = 0;
43424 rc = duk_heap_mark_and_sweep(heap, flags);
43425 DUK_UNREF(rc);
43426 }
43427}
43428#else
43429#define DUK__VOLUNTARY_PERIODIC_GC(heap) /* no voluntary gc */
43430#endif /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
43431
43432/*
43433 * Allocate memory with garbage collection
43434 */
43435
43436#ifdef DUK_USE_MARK_AND_SWEEP
43438 void *res;
43439 duk_bool_t rc;
43441
43442 DUK_ASSERT(heap != NULL);
43443 DUK_ASSERT_DISABLE(size >= 0);
43444
43445 /*
43446 * Voluntary periodic GC (if enabled)
43447 */
43448
43450
43451 /*
43452 * First attempt
43453 */
43454
43455#ifdef DUK_USE_GC_TORTURE
43456 /* simulate alloc failure on every alloc (except when mark-and-sweep is running) */
43458 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
43459 res = NULL;
43460 DUK_UNREF(res);
43461 goto skip_attempt;
43462 }
43463#endif
43464 res = heap->alloc_func(heap->heap_udata, size);
43465 if (res || size == 0) {
43466 /* for zero size allocations NULL is allowed */
43467 return res;
43468 }
43469#ifdef DUK_USE_GC_TORTURE
43470 skip_attempt:
43471#endif
43472
43473 DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
43474
43475 /*
43476 * Avoid a GC if GC is already running. This can happen at a late
43477 * stage in a GC when we try to e.g. resize the stringtable
43478 * or compact objects.
43479 */
43480
43482 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
43483 return NULL;
43484 }
43485
43486 /*
43487 * Retry with several GC attempts. Initial attempts are made without
43488 * emergency mode; later attempts use emergency mode which minimizes
43489 * memory allocations forcibly.
43490 */
43491
43492 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43493 duk_small_uint_t flags;
43494
43495 flags = 0;
43497 flags |= DUK_MS_FLAG_EMERGENCY;
43498 }
43499
43500 rc = duk_heap_mark_and_sweep(heap, flags);
43501 DUK_UNREF(rc);
43502
43503 res = heap->alloc_func(heap->heap_udata, size);
43504 if (res) {
43505 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
43506 (long) (i + 1), (long) size));
43507 return res;
43508 }
43509 }
43511 DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
43512 return NULL;
43513}
43514#else /* DUK_USE_MARK_AND_SWEEP */
43515/*
43516 * Compared to a direct macro expansion this wrapper saves a few
43517 * instructions because no heap dereferencing is required.
43518 */
43520 DUK_ASSERT(heap != NULL);
43521 DUK_ASSERT_DISABLE(size >= 0);
43522
43523 return heap->alloc_func(heap->heap_udata, size);
43524}
43525#endif /* DUK_USE_MARK_AND_SWEEP */
43526
43528 void *res;
43530 DUK_ASSERT(heap != NULL);
43531 DUK_ASSERT_DISABLE(size >= 0);
43532
43533 res = DUK_ALLOC(heap, size);
43534 if (res) {
43535 /* assume memset with zero size is OK */
43536 DUK_MEMZERO(res, size);
43537 }
43538 return res;
43539}
43540
43541/*
43542 * Reallocate memory with garbage collection
43543 */
43544
43545#ifdef DUK_USE_MARK_AND_SWEEP
43546DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
43547 void *res;
43548 duk_bool_t rc;
43550
43551 DUK_ASSERT(heap != NULL);
43552 /* ptr may be 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 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, ptr, 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 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() 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 flags = 0;
43605 flags |= DUK_MS_FLAG_EMERGENCY;
43606 }
43607
43608 rc = duk_heap_mark_and_sweep(heap, flags);
43609 DUK_UNREF(rc);
43610
43611 res = heap->realloc_func(heap->heap_udata, ptr, newsize);
43612 if (res || newsize == 0) {
43613 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
43614 (long) (i + 1), (long) newsize));
43615 return res;
43616 }
43617 }
43618
43619 DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
43620 return NULL;
43621}
43622#else /* DUK_USE_MARK_AND_SWEEP */
43623/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43624DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
43625 DUK_ASSERT(heap != NULL);
43626 /* ptr may be NULL */
43627 DUK_ASSERT_DISABLE(newsize >= 0);
43628
43629 return heap->realloc_func(heap->heap_udata, ptr, newsize);
43630}
43631#endif /* DUK_USE_MARK_AND_SWEEP */
43632
43633/*
43634 * Reallocate memory with garbage collection, using a callback to provide
43635 * the current allocated pointer. This variant is used when a mark-and-sweep
43636 * (e.g. finalizers) might change the original pointer.
43637 */
43638
43639#ifdef DUK_USE_MARK_AND_SWEEP
43641 void *res;
43642 duk_bool_t rc;
43644
43645 DUK_ASSERT(heap != NULL);
43646 DUK_ASSERT_DISABLE(newsize >= 0);
43647
43648 /*
43649 * Voluntary periodic GC (if enabled)
43650 */
43651
43653
43654 /*
43655 * First attempt
43656 */
43657
43658#ifdef DUK_USE_GC_TORTURE
43659 /* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
43661 DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
43662 res = NULL;
43663 DUK_UNREF(res);
43664 goto skip_attempt;
43665 }
43666#endif
43667 res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43668 if (res || newsize == 0) {
43669 /* for zero size allocations NULL is allowed */
43670 return res;
43671 }
43672#ifdef DUK_USE_GC_TORTURE
43673 skip_attempt:
43674#endif
43675
43676 DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
43677
43678 /*
43679 * Avoid a GC if GC is already running. See duk_heap_mem_alloc().
43680 */
43681
43683 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
43684 return NULL;
43685 }
43686
43687 /*
43688 * Retry with several GC attempts. Initial attempts are made without
43689 * emergency mode; later attempts use emergency mode which minimizes
43690 * memory allocations forcibly.
43691 */
43692
43693 for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43694 duk_small_uint_t flags;
43695
43696#ifdef DUK_USE_ASSERTIONS
43697 void *ptr_pre; /* ptr before mark-and-sweep */
43698 void *ptr_post;
43699#endif
43700
43701#ifdef DUK_USE_ASSERTIONS
43702 ptr_pre = cb(heap, ud);
43703#endif
43704 flags = 0;
43706 flags |= DUK_MS_FLAG_EMERGENCY;
43707 }
43708
43709 rc = duk_heap_mark_and_sweep(heap, flags);
43710 DUK_UNREF(rc);
43711#ifdef DUK_USE_ASSERTIONS
43712 ptr_post = cb(heap, ud);
43713 if (ptr_pre != ptr_post) {
43714 /* useful for debugging */
43715 DUK_DD(DUK_DDPRINT("note: base pointer changed by mark-and-sweep: %p -> %p",
43716 (void *) ptr_pre, (void *) ptr_post));
43717 }
43718#endif
43719
43720 /* Note: key issue here is to re-lookup the base pointer on every attempt.
43721 * The pointer being reallocated may change after every mark-and-sweep.
43722 */
43723
43724 res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43725 if (res || newsize == 0) {
43726 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
43727 (long) (i + 1), (long) newsize));
43728 return res;
43729 }
43731
43732 DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
43733 return NULL;
43734}
43735#else /* DUK_USE_MARK_AND_SWEEP */
43736/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43738 return heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43739}
43740#endif /* DUK_USE_MARK_AND_SWEEP */
43741
43742/*
43743 * Free memory
43744 */
43745
43746#ifdef DUK_USE_MARK_AND_SWEEP
43747DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
43748 DUK_ASSERT(heap != NULL);
43749 /* ptr may be NULL */
43750
43751 /* Must behave like a no-op with NULL and any pointer returned from
43752 * malloc/realloc with zero size.
43753 */
43754 heap->free_func(heap->heap_udata, ptr);
43755
43756 /* Count free operations toward triggering a GC but never actually trigger
43757 * a GC from a free. Otherwise code which frees internal structures would
43758 * need to put in NULLs at every turn to ensure the object is always in
43759 * consistent state for a mark-and-sweep.
43760 */
43761#ifdef DUK_USE_VOLUNTARY_GC
43763#endif
43764}
43765#else
43766/* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43767DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
43768 DUK_ASSERT(heap != NULL);
43769 /* ptr may be NULL */
43770
43771 /* Note: must behave like a no-op with NULL and any pointer
43772 * returned from malloc/realloc with zero size.
43773 */
43774 heap->free_func(heap->heap_udata, ptr);
43775}
43776#endif
43777#line 1 "duk_heap_misc.c"
43778/*
43779 * Support functions for duk_heap.
43780 */
43781
43782/* include removed: duk_internal.h */
43783
43784#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
43785/* arbitrary remove only works with double linked heap, and is only required by
43786 * reference counting so far.
43787 */
43790
43791 if (DUK_HEAPHDR_GET_PREV(heap, hdr)) {
43793 } else {
43794 heap->heap_allocated = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43795 }
43796 if (DUK_HEAPHDR_GET_NEXT(heap, hdr)) {
43798 } else {
43799 ;
43800 }
43801
43802 /* The prev/next pointers of the removed duk_heaphdr are left as garbage.
43803 * It's up to the caller to ensure they're written before inserting the
43804 * object back.
43805 */
43806}
43807#endif
43808
43811
43812#ifdef DUK_USE_DOUBLE_LINKED_HEAP
43813 if (heap->heap_allocated) {
43815 DUK_HEAPHDR_SET_PREV(heap, heap->heap_allocated, hdr);
43816 }
43817 DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
43818#endif
43819 DUK_HEAPHDR_SET_NEXT(heap, hdr, heap->heap_allocated);
43820 heap->heap_allocated = hdr;
43821}
43822
43823#ifdef DUK_USE_INTERRUPT_COUNTER
43824DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
43825 duk_hthread *curr_thr;
43826
43827 DUK_ASSERT(heap != NULL);
43828
43829 if (new_thr != NULL) {
43830 curr_thr = heap->curr_thread;
43831 if (curr_thr == NULL) {
43832 /* For initial entry use default value; zero forces an
43833 * interrupt before executing the first insturction.
43834 */
43835 DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
43836 new_thr->interrupt_counter = 0;
43837 new_thr->interrupt_init = 0;
43838 } else {
43839 /* Copy interrupt counter/init value state to new thread (if any).
43840 * It's OK for new_thr to be the same as curr_thr.
43841 */
43842#if defined(DUK_USE_DEBUG)
43843 if (new_thr != curr_thr) {
43844 DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
43845 }
43846#endif
43847 new_thr->interrupt_counter = curr_thr->interrupt_counter;
43848 new_thr->interrupt_init = curr_thr->interrupt_init;
43849 }
43850 } else {
43851 DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
43852 }
43853
43854 heap->curr_thread = new_thr; /* may be NULL */
43855}
43856#endif /* DUK_USE_INTERRUPT_COUNTER */
43857#line 1 "duk_heap_refcount.c"
43858/*
43859 * Reference counting implementation.
43860 */
43861
43862/* include removed: duk_internal.h */
43863
43864#ifdef DUK_USE_REFERENCE_COUNTING
43865
43866#ifndef DUK_USE_DOUBLE_LINKED_HEAP
43867#error internal error, reference counting requires a double linked heap
43868#endif
43869
43870/*
43871 * Misc
43872 */
43873
43875 /* tail insert: don't disturb head in case refzero is running */
43876
43877 if (heap->refzero_list != NULL) {
43878 duk_heaphdr *hdr_prev;
43879
43880 hdr_prev = heap->refzero_list_tail;
43881 DUK_ASSERT(hdr_prev != NULL);
43882 DUK_ASSERT(DUK_HEAPHDR_GET_NEXT(heap, hdr_prev) == NULL);
43883
43884 DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
43885 DUK_HEAPHDR_SET_PREV(heap, hdr, hdr_prev);
43886 DUK_HEAPHDR_SET_NEXT(heap, hdr_prev, hdr);
43887 DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
43888 DUK_ASSERT_HEAPHDR_LINKS(heap, hdr_prev);
43889 heap->refzero_list_tail = hdr;
43890 } else {
43892 DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
43893 DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
43894 DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
43895 heap->refzero_list = hdr;
43896 heap->refzero_list_tail = hdr;
43898}
43899
43900/*
43901 * Heap object refcount finalization.
43902 *
43903 * When an object is about to be freed, all other objects it refers to must
43904 * be decref'd. Refcount finalization does NOT free the object or its inner
43905 * allocations (mark-and-sweep shares these helpers), it just manipulates
43906 * the refcounts.
43907 *
43908 * Note that any of the decref's may cause a refcount to drop to zero, BUT
43909 * it will not be processed inline; instead, because refzero is already
43910 * running, the objects will just be queued to refzero list and processed
43911 * later. This eliminates C recursion.
43912 */
43913
43916
43917 DUK_ASSERT(h);
43919
43920 /* XXX: better to get base and walk forwards? */
43921
43922 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
43923 duk_hstring *key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
43924 if (!key) {
43925 continue;
43926 }
43927 duk_heaphdr_decref(thr, (duk_heaphdr *) key);
43928 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)) {
43931 } else {
43933 }
43934 }
43935
43936 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
43938 }
43939
43940 /* hash part is a 'weak reference' and does not contribute */
43941
43943
43946 duk_tval *tv, *tv_end;
43947 duk_hobject **funcs, **funcs_end;
43948
43949 if (DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f) != NULL) {
43952 while (tv < tv_end) {
43953 duk_tval_decref(thr, tv);
43954 tv++;
43955 }
43956
43958 funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
43959 while (funcs < funcs_end) {
43961 funcs++;
43962 }
43963 } else {
43964 /* May happen in some out-of-memory corner cases. */
43965 DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping decref"));
43966 }
43967
43969 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
43971 DUK_UNREF(f);
43972 /* nothing to finalize */
43973 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
43975 if (b->buf) {
43976 duk_heaphdr_decref(thr, (duk_heaphdr *) b->buf);
43977 }
43978 } else if (DUK_HOBJECT_IS_THREAD(h)) {
43979 duk_hthread *t = (duk_hthread *) h;
43980 duk_tval *tv;
43981
43982 tv = t->valstack;
43983 while (tv < t->valstack_top) {
43984 duk_tval_decref(thr, tv);
43985 tv++;
43986 }
43987
43988 for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
43989 duk_activation *act = t->callstack + i;
43993#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
43994 duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->prev_caller);
43995#endif
43996 }
43997
43998#if 0 /* nothing now */
43999 for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
44000 duk_catcher *cat = t->catchstack + i;
44001 }
44002#endif
44003
44004 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
44006 }
44007
44009 }
44010}
44011
44013 DUK_ASSERT(hdr);
44014
44015 switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
44016 case DUK_HTYPE_OBJECT:
44018 break;
44019 case DUK_HTYPE_BUFFER:
44020 /* nothing to finalize */
44021 break;
44022 case DUK_HTYPE_STRING:
44023 /* cannot happen: strings are not put into refzero list (they don't even have the next/prev pointers) */
44024 default:
44026 }
44027}
44028
44029#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
44030DUK_LOCAL duk_ret_t duk__refcount_fake_finalizer(duk_context *ctx) {
44031 DUK_UNREF(ctx);
44032 DUK_D(DUK_DPRINT("fake refcount torture finalizer executed"));
44033#if 0
44034 DUK_DD(DUK_DDPRINT("fake torture finalizer for: %!T", duk_get_tval(ctx, 0)));
44035#endif
44036 /* Require a lot of stack to force a value stack grow/shrink. */
44037 duk_require_stack(ctx, 100000);
44038
44039 /* XXX: do something to force a callstack grow/shrink, perhaps
44040 * just a manual forced resize?
44041 */
44042 return 0;
44043}
44044
44045DUK_LOCAL void duk__refcount_run_torture_finalizer(duk_hthread *thr, duk_hobject *obj) {
44046 duk_context *ctx;
44047 duk_int_t rc;
44048
44049 DUK_ASSERT(thr != NULL);
44050 DUK_ASSERT(obj != NULL);
44051 ctx = (duk_context *) thr;
44052
44053 /* Avoid fake finalization for the duk__refcount_fake_finalizer function
44054 * itself, otherwise we're in infinite recursion.
44055 */
44057 if (((duk_hnativefunction *) obj)->func == duk__refcount_fake_finalizer) {
44058 DUK_DD(DUK_DDPRINT("avoid fake torture finalizer for duk__refcount_fake_finalizer itself"));
44059 return;
44060 }
44061 }
44062 /* Avoid fake finalization when callstack limit has been reached.
44063 * Otherwise a callstack limit error will be created, then refzero'ed,
44064 * and we're in an infinite loop.
44065 */
44067 thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
44068 DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake torture finalizer"));
44069 return;
44070 }
44071
44072 /* Run fake finalizer. Avoid creating new refzero queue entries
44073 * so that we are not forced into a forever loop.
44074 */
44075 duk_push_c_function(ctx, duk__refcount_fake_finalizer, 1 /*nargs*/);
44076 duk_push_hobject(ctx, obj);
44077 rc = duk_pcall(ctx, 1);
44078 DUK_UNREF(rc); /* ignored */
44079 duk_pop(ctx);
44080}
44081#endif /* DUK_USE_REFZERO_FINALIZER_TORTURE */
44082
44083/*
44084 * Refcount memory freeing loop.
44085 *
44086 * Frees objects in the refzero_pending list until the list becomes
44087 * empty. When an object is freed, its references get decref'd and
44088 * may cause further objects to be queued for freeing.
44089 *
44090 * This could be expanded to allow incremental freeing: just bail out
44091 * early and resume at a future alloc/decref/refzero.
44092 */
44093
44095 duk_heaphdr *h1, *h2;
44096 duk_heap *heap;
44097 duk_int_t count = 0;
44098
44099 DUK_ASSERT(thr != NULL);
44100 DUK_ASSERT(thr->heap != NULL);
44101 heap = thr->heap;
44102 DUK_ASSERT(heap != NULL);
44103
44104 /*
44105 * Detect recursive invocation
44106 */
44107
44109 DUK_DDD(DUK_DDDPRINT("refzero free running, skip run"));
44110 return;
44111 }
44112
44113 /*
44114 * Churn refzero_list until empty
44115 */
44116
44118 while (heap->refzero_list) {
44119 duk_hobject *obj;
44120 duk_bool_t rescued = 0;
44121
44122 /*
44123 * Pick an object from the head (don't remove yet).
44124 */
44125
44126 h1 = heap->refzero_list;
44127 obj = (duk_hobject *) h1;
44128 DUK_DD(DUK_DDPRINT("refzero processing %p: %!O", (void *) h1, (duk_heaphdr *) h1));
44129 DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, h1) == NULL);
44130 DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h1) == DUK_HTYPE_OBJECT); /* currently, always the case */
44131
44132#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
44133 /* Torture option to shake out finalizer side effect issues:
44134 * make a bogus function call for every finalizable object,
44135 * essentially simulating the case where everything has a
44136 * finalizer.
44137 */
44138 DUK_DD(DUK_DDPRINT("refzero torture enabled, fake finalizer"));
44140 DUK_HEAPHDR_PREINC_REFCOUNT(h1); /* bump refcount to prevent refzero during finalizer processing */
44141 duk__refcount_run_torture_finalizer(thr, obj); /* must never longjmp */
44142 DUK_HEAPHDR_PREDEC_REFCOUNT(h1); /* remove artificial bump */
44143 DUK_ASSERT_DISABLE(h1->h_refcount >= 0); /* refcount is unsigned, so always true */
44144#endif
44145
44146 /*
44147 * Finalizer check.
44148 *
44149 * Note: running a finalizer may have arbitrary side effects, e.g.
44150 * queue more objects on refzero_list (tail), or even trigger a
44151 * mark-and-sweep.
44152 *
44153 * Note: quick reject check should match vast majority of
44154 * objects and must be safe (not throw any errors, ever).
44155 */
44156
44157 /* An object may have FINALIZED here if it was finalized by mark-and-sweep
44158 * on a previous run and refcount then decreased to zero. We won't run the
44159 * finalizer again here.
44160 */
44161
44162 /* A finalizer is looked up from the object and up its prototype chain
44163 * (which allows inherited finalizers).
44164 */
44166 DUK_DDD(DUK_DDDPRINT("object has a finalizer, run it"));
44167
44169 DUK_HEAPHDR_PREINC_REFCOUNT(h1); /* bump refcount to prevent refzero during finalizer processing */
44170
44171 duk_hobject_run_finalizer(thr, obj); /* must never longjmp */
44172 DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1)); /* duk_hobject_run_finalizer() sets */
44173
44174 DUK_HEAPHDR_PREDEC_REFCOUNT(h1); /* remove artificial bump */
44175 DUK_ASSERT_DISABLE(h1->h_refcount >= 0); /* refcount is unsigned, so always true */
44176
44177 if (DUK_HEAPHDR_GET_REFCOUNT(h1) != 0) {
44178 DUK_DDD(DUK_DDDPRINT("-> object refcount after finalization non-zero, object will be rescued"));
44179 rescued = 1;
44180 } else {
44181 DUK_DDD(DUK_DDDPRINT("-> object refcount still zero after finalization, object will be freed"));
44182 }
44183 }
44184
44185 /* Refzero head is still the same. This is the case even if finalizer
44186 * inserted more refzero objects; they are inserted to the tail.
44187 */
44188 DUK_ASSERT(h1 == heap->refzero_list);
44189
44190 /*
44191 * Remove the object from the refzero list. This cannot be done
44192 * before a possible finalizer has been executed; the finalizer
44193 * may trigger a mark-and-sweep, and mark-and-sweep must be able
44194 * to traverse a complete refzero_list.
44195 */
44196
44197 h2 = DUK_HEAPHDR_GET_NEXT(heap, h1);
44198 if (h2) {
44199 DUK_HEAPHDR_SET_PREV(heap, h2, NULL); /* not strictly necessary */
44200 heap->refzero_list = h2;
44201 } else {
44202 heap->refzero_list = NULL;
44203 heap->refzero_list_tail = NULL;
44204 }
44205
44206 /*
44207 * Rescue or free.
44208 */
44209
44210 if (rescued) {
44211 /* yes -> move back to heap allocated */
44212 DUK_DD(DUK_DDPRINT("object rescued during refcount finalization: %p", (void *) h1));
44216 h2 = heap->heap_allocated;
44217 DUK_HEAPHDR_SET_PREV(heap, h1, NULL);
44218 if (h2) {
44219 DUK_HEAPHDR_SET_PREV(heap, h2, h1);
44220 }
44221 DUK_HEAPHDR_SET_NEXT(heap, h1, h2);
44222 DUK_ASSERT_HEAPHDR_LINKS(heap, h1);
44223 DUK_ASSERT_HEAPHDR_LINKS(heap, h2);
44224 heap->heap_allocated = h1;
44225 } else {
44226 /* no -> decref members, then free */
44228 duk_heap_free_heaphdr_raw(heap, h1);
44229 }
44230
44231 count++;
44232 }
44234
44235 DUK_DDD(DUK_DDDPRINT("refzero processed %ld objects", (long) count));
44236
44237 /*
44238 * Once the whole refzero cascade has been freed, check for
44239 * a voluntary mark-and-sweep.
44240 */
44241
44242#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
44243 /* 'count' is more or less comparable to normal trigger counter update
44244 * which happens in memory block (re)allocation.
44245 */
44246 heap->mark_and_sweep_trigger_counter -= count;
44247 if (heap->mark_and_sweep_trigger_counter <= 0) {
44248 duk_bool_t rc;
44249 duk_small_uint_t flags = 0; /* not emergency */
44250 DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
44251 rc = duk_heap_mark_and_sweep(heap, flags);
44252 DUK_UNREF(rc);
44253 DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
44254 }
44255#endif /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
44256}
44257
44258/*
44259 * Incref and decref functions.
44260 *
44261 * Decref may trigger immediate refzero handling, which may free and finalize
44262 * an arbitrary number of objects.
44263 *
44264 */
44265
44267 duk_heap *heap;
44268
44269 DUK_ASSERT(thr != NULL);
44270 DUK_ASSERT(h != NULL);
44271
44272 heap = thr->heap;
44273 DUK_DDD(DUK_DDDPRINT("refzero %p: %!O", (void *) h, (duk_heaphdr *) h));
44274
44275 /*
44276 * Refzero handling is skipped entirely if (1) mark-and-sweep is
44277 * running or (2) execution is paused in the debugger. The objects
44278 * are left in the heap, and will be freed by mark-and-sweep or
44279 * eventual heap destruction.
44280 *
44281 * This is necessary during mark-and-sweep because refcounts are also
44282 * updated during the sweep phase (otherwise objects referenced by a
44283 * swept object would have incorrect refcounts) which then calls here.
44284 * This could be avoided by using separate decref macros in
44285 * mark-and-sweep; however, mark-and-sweep also calls finalizers which
44286 * would use the ordinary decref macros anyway and still call this
44287 * function.
44288 *
44289 * This check must be enabled also when mark-and-sweep support has been
44290 * disabled: the flag is also used in heap destruction when running
44291 * finalizers for remaining objects, and the flag prevents objects from
44292 * being moved around in heap linked lists.
44293 */
44294
44295 /* XXX: ideally this would be just one flag (maybe a derived one) so
44296 * that a single bit test is sufficient to check the condition.
44297 */
44298#if defined(DUK_USE_DEBUGGER_SUPPORT)
44299 if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) || DUK_HEAP_IS_PAUSED(heap))) {
44300#else
44302#endif
44303 DUK_DDD(DUK_DDDPRINT("refzero handling suppressed when mark-and-sweep running, object: %p", (void *) h));
44304 return;
44305 }
44306
44308 case DUK_HTYPE_STRING:
44309 /*
44310 * Strings have no internal references but do have "weak"
44311 * references in the string cache. Also note that strings
44312 * are not on the heap_allocated list like other heap
44313 * elements.
44314 */
44315
44319 break;
44320
44321 case DUK_HTYPE_OBJECT:
44322 /*
44323 * Objects have internal references. Must finalize through
44324 * the "refzero" work list.
44325 */
44326
44328 duk__queue_refzero(heap, h);
44330 break;
44331
44332 case DUK_HTYPE_BUFFER:
44333 /*
44334 * Buffers have no internal references. However, a dynamic
44335 * buffer has a separate allocation for the buffer. This is
44336 * freed by duk_heap_free_heaphdr_raw().
44337 */
44338
44341 break;
44342
44343 default:
44344 DUK_D(DUK_DPRINT("invalid heap type in decref: %ld", (long) DUK_HEAPHDR_GET_TYPE(h)));
44346 }
44347}
44348
44349#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
44350DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
44351 DUK_ASSERT(tv != NULL);
44352
44355 DUK_ASSERT(h != NULL);
44359 }
44360}
44361#endif
44362
44363#if 0 /* unused */
44364DUK_INTERNAL void duk_tval_incref_allownull(duk_tval *tv) {
44365 if (tv == NULL) {
44366 return;
44367 }
44370 DUK_ASSERT(h != NULL);
44374 }
44375}
44376#endif
44377
44379 DUK_ASSERT(thr != NULL);
44380 DUK_ASSERT(tv != NULL);
44381
44384 DUK_ASSERT(h != NULL);
44386 duk_heaphdr_decref(thr, h);
44387 }
44388}
44389
44390#if 0 /* unused */
44391DUK_INTERNAL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv) {
44392 DUK_ASSERT(thr != NULL);
44393
44394 if (tv == NULL) {
44395 return;
44396 }
44399 DUK_ASSERT(h != NULL);
44401 duk_heaphdr_decref(thr, h);
44402 }
44403}
44404#endif
44405
44406#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
44407DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
44408 DUK_ASSERT(h != NULL);
44413}
44414#endif
44415
44416#if 0 /* unused */
44417DUK_INTERNAL void duk_heaphdr_incref_allownull(duk_heaphdr *h) {
44418 if (h == NULL) {
44419 return;
44420 }
44423
44425}
44426#endif
44427
44430 DUK_ASSERT(thr->heap != NULL);
44431 DUK_ASSERT(h != NULL);
44434
44435#if defined(DUK_USE_ROM_OBJECTS)
44436 if (DUK_HEAPHDR_HAS_READONLY(h)) {
44437 return;
44438 }
44439#endif
44440 if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
44441 return;
44442 }
44443 duk_heaphdr_refzero(thr, h);
44444}
44445
44447 DUK_ASSERT(thr != NULL);
44448 DUK_ASSERT(thr->heap != NULL);
44449
44450 if (h == NULL) {
44451 return;
44452 }
44454
44455#if defined(DUK_USE_ROM_OBJECTS)
44456 if (DUK_HEAPHDR_HAS_READONLY(h)) {
44457 return;
44458 }
44459#endif
44461 if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
44462 return;
44463 }
44464 duk_heaphdr_refzero(thr, h);
44465}
44466
44467#else
44468
44469/* no refcounting */
44470
44471#endif /* DUK_USE_REFERENCE_COUNTING */
44472#line 1 "duk_heap_stringcache.c"
44473/*
44474 * String cache.
44476 * Provides a cache to optimize indexed string lookups. The cache keeps
44477 * track of (byte offset, char offset) states for a fixed number of strings.
44478 * Otherwise we'd need to scan from either end of the string, as we store
44479 * strings in (extended) UTF-8.
44480 */
44481
44482/* include removed: duk_internal.h */
44483
44484/*
44485 * Delete references to given hstring from the heap string cache.
44486 *
44487 * String cache references are 'weak': they are not counted towards
44488 * reference counts, nor serve as roots for mark-and-sweep. When an
44489 * object is about to be freed, such references need to be removed.
44490 */
44491
44494 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44495 duk_strcache *c = heap->strcache + i;
44496 if (c->h == h) {
44497 DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
44498 (void *) h, (void *) heap));
44499 c->h = NULL;
44501 /* XXX: the string shouldn't appear twice, but we now loop to the
44502 * end anyway; if fixed, add a looping assertion to ensure there
44503 * is no duplicate.
44504 */
44505 }
44506 }
44507}
44508
44509/*
44510 * String scanning helpers
44511 *
44512 * All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
44513 * considered to contribute a character. This must match how string
44514 * character length is computed.
44515 */
44517DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
44518 while (n > 0) {
44519 for (;;) {
44520 p++;
44521 if (p >= q) {
44522 return NULL;
44523 }
44524 if ((*p & 0xc0) != 0x80) {
44525 break;
44526 }
44527 }
44528 n--;
44529 }
44530 return p;
44531}
44532
44533DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
44534 while (n > 0) {
44535 for (;;) {
44536 p--;
44537 if (p < q) {
44538 return NULL;
44539 }
44540 if ((*p & 0xc0) != 0x80) {
44541 break;
44542 }
44543 }
44544 n--;
44545 }
44546 return p;
44547}
44548
44549/*
44550 * Convert char offset to byte offset
44551 *
44552 * Avoid using the string cache if possible: for ASCII strings byte and
44553 * char offsets are equal and for short strings direct scanning may be
44554 * better than using the string cache (which may evict a more important
44555 * entry).
44556 *
44557 * Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
44558 * Better typing might be to use duk_size_t.
44559 */
44560
44562 duk_heap *heap;
44563 duk_strcache *sce;
44564 duk_uint_fast32_t byte_offset;
44566 duk_bool_t use_cache;
44567 duk_uint_fast32_t dist_start, dist_end, dist_sce;
44568 const duk_uint8_t *p_start;
44569 const duk_uint8_t *p_end;
44570 const duk_uint8_t *p_found;
44571
44572 if (char_offset > DUK_HSTRING_GET_CHARLEN(h)) {
44573 goto error;
44574 }
44575
44576 /*
44577 * For ASCII strings, the answer is simple.
44578 */
44579
44580 if (DUK_HSTRING_IS_ASCII(h)) {
44581 /* clen == blen -> pure ascii */
44582 return char_offset;
44583 }
44584
44585 /*
44586 * For non-ASCII strings, we need to scan forwards or backwards
44587 * from some starting point. The starting point may be the start
44588 * or end of the string, or some cached midpoint in the string
44589 * cache.
44590 *
44591 * For "short" strings we simply scan without checking or updating
44592 * the cache. For longer strings we check and update the cache as
44593 * necessary, inserting a new cache entry if none exists.
44594 */
44595
44596 DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
44597 (void *) h, (long) char_offset,
44598 (long) DUK_HSTRING_GET_CHARLEN(h),
44599 (long) DUK_HSTRING_GET_BYTELEN(h)));
44600
44601 heap = thr->heap;
44602 sce = NULL;
44604
44605 if (use_cache) {
44606#ifdef DUK_USE_DDDPRINT
44607 DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
44608 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44609 duk_strcache *c = heap->strcache + i;
44610 DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
44611 (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
44612 }
44613#endif
44614
44615 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44616 duk_strcache *c = heap->strcache + i;
44617
44618 if (c->h == h) {
44619 sce = c;
44620 break;
44621 }
44622 }
44623 }
44624
44625 /*
44626 * Scan from shortest distance:
44627 * - start of string
44628 * - end of string
44629 * - cache entry (if exists)
44630 */
44631
44632 DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
44633 dist_start = char_offset;
44634 dist_end = DUK_HSTRING_GET_CHARLEN(h) - char_offset;
44635 dist_sce = 0; DUK_UNREF(dist_sce); /* initialize for debug prints, needed if sce==NULL */
44636
44637 p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
44638 p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
44639 p_found = NULL;
44640
44641 if (sce) {
44642 if (char_offset >= sce->cidx) {
44643 dist_sce = char_offset - sce->cidx;
44644 if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
44645 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44646 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44647 "scan forwards from sce",
44648 (long) use_cache, (void *) (sce ? sce->h : NULL),
44649 (sce ? (long) sce->cidx : (long) -1),
44650 (sce ? (long) sce->bidx : (long) -1),
44651 (long) dist_start, (long) dist_end, (long) dist_sce));
44652
44653 p_found = duk__scan_forwards(p_start + sce->bidx,
44654 p_end,
44655 dist_sce);
44656 goto scan_done;
44657 }
44658 } else {
44659 dist_sce = sce->cidx - char_offset;
44660 if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
44661 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44662 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44663 "scan backwards from sce",
44664 (long) use_cache, (void *) (sce ? sce->h : NULL),
44665 (sce ? (long) sce->cidx : (long) -1),
44666 (sce ? (long) sce->bidx : (long) -1),
44667 (long) dist_start, (long) dist_end, (long) dist_sce));
44668
44669 p_found = duk__scan_backwards(p_start + sce->bidx,
44670 p_start,
44671 dist_sce);
44672 goto scan_done;
44673 }
44674 }
44675 }
44676
44677 /* no sce, or sce scan not best */
44678
44679 if (dist_start <= dist_end) {
44680 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44681 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44682 "scan forwards from string start",
44683 (long) use_cache, (void *) (sce ? sce->h : NULL),
44684 (sce ? (long) sce->cidx : (long) -1),
44685 (sce ? (long) sce->bidx : (long) -1),
44686 (long) dist_start, (long) dist_end, (long) dist_sce));
44687
44688 p_found = duk__scan_forwards(p_start,
44689 p_end,
44690 dist_start);
44691 } else {
44692 DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44693 "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44694 "scan backwards from string end",
44695 (long) use_cache, (void *) (sce ? sce->h : NULL),
44696 (sce ? (long) sce->cidx : (long) -1),
44697 (sce ? (long) sce->bidx : (long) -1),
44698 (long) dist_start, (long) dist_end, (long) dist_sce));
44699
44700 p_found = duk__scan_backwards(p_end,
44701 p_start,
44702 dist_end);
44703 }
44704
44705 scan_done:
44706
44707 if (!p_found) {
44708 /* Scan error: this shouldn't normally happen; it could happen if
44709 * string is not valid UTF-8 data, and clen/blen are not consistent
44710 * with the scanning algorithm.
44711 */
44712 goto error;
44713 }
44714
44715 DUK_ASSERT(p_found >= p_start);
44716 DUK_ASSERT(p_found <= p_end); /* may be equal */
44717 byte_offset = (duk_uint32_t) (p_found - p_start);
44718
44719 DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
44720 (void *) h, (long) char_offset, (long) byte_offset));
44721
44722 /*
44723 * Update cache entry (allocating if necessary), and move the
44724 * cache entry to the first place (in an "LRU" policy).
44725 */
44726
44727 if (use_cache) {
44728 /* update entry, allocating if necessary */
44729 if (!sce) {
44730 sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1; /* take last entry */
44731 sce->h = h;
44732 }
44733 DUK_ASSERT(sce != NULL);
44734 sce->bidx = (duk_uint32_t) (p_found - p_start);
44735 sce->cidx = (duk_uint32_t) char_offset;
44736
44737 /* LRU: move our entry to first */
44738 if (sce > &heap->strcache[0]) {
44739 /*
44740 * A C
44741 * B A
44742 * C <- sce ==> B
44743 * D D
44744 */
44745 duk_strcache tmp;
44746
44747 tmp = *sce;
44748 DUK_MEMMOVE((void *) (&heap->strcache[1]),
44749 (const void *) (&heap->strcache[0]),
44750 (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
44751 heap->strcache[0] = tmp;
44752
44753 /* 'sce' points to the wrong entry here, but is no longer used */
44754 }
44755#ifdef DUK_USE_DDDPRINT
44756 DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
44757 for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44758 duk_strcache *c = heap->strcache + i;
44759 DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
44760 (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
44761 }
44762#endif
44765 return byte_offset;
44766
44767 error:
44769 return 0;
44770}
44771#line 1 "duk_heap_stringtable.c"
44772/*
44773 * Heap stringtable handling, string interning.
44774 */
44775
44776/* include removed: duk_internal.h */
44777
44778#if defined(DUK_USE_STRTAB_PROBE)
44779#define DUK__HASH_INITIAL(hash,h_size) DUK_STRTAB_HASH_INITIAL((hash),(h_size))
44780#define DUK__HASH_PROBE_STEP(hash) DUK_STRTAB_HASH_PROBE_STEP((hash))
44781#define DUK__DELETED_MARKER(heap) DUK_STRTAB_DELETED_MARKER((heap))
44782#endif
44783
44784#if defined(DUK_USE_MARK_AND_SWEEP)
44785#define DUK__PREVENT_MS_SIDE_EFFECTS(heap) do { \
44786 (heap)->mark_and_sweep_base_flags |= \
44787 DUK_MS_FLAG_NO_STRINGTABLE_RESIZE | /* avoid recursive string table call */ \
44788 DUK_MS_FLAG_NO_FINALIZERS | /* avoid pressure to add/remove strings, invalidation of call data argument, etc. */ \
44789 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid array abandoning which interns strings */ \
44790 } while (0)
44791#endif
44792
44793/*
44794 * Create a hstring and insert into the heap. The created object
44795 * is directly garbage collectable with reference count zero.
44796 *
44797 * The caller must place the interned string into the stringtable
44798 * immediately (without chance of a longjmp); otherwise the string
44799 * is lost.
44800 */
44801
44804 const duk_uint8_t *str,
44805 duk_uint32_t blen,
44806 duk_uint32_t strhash,
44807 const duk_uint8_t *extdata) {
44808 duk_hstring *res = NULL;
44809 duk_uint8_t *data;
44810 duk_size_t alloc_size;
44812 duk_uint32_t clen;
44813
44814#if defined(DUK_USE_STRLEN16)
44815 /* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
44816 if (blen > 0xffffUL) {
44817 DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
44818 return NULL;
44819 }
44820#endif
44821
44822 if (extdata) {
44823 alloc_size = (duk_size_t) sizeof(duk_hstring_external);
44824 res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
44825 if (!res) {
44826 goto alloc_error;
44827 }
44828 DUK_MEMZERO(res, sizeof(duk_hstring_external));
44829#if defined(DUK_USE_EXPLICIT_NULL_INIT)
44831#endif
44833
44834 ((duk_hstring_external *) res)->extdata = extdata;
44835 } else {
44836 /* NUL terminate for convenient C access */
44837 alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
44838 res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
44839 if (!res) {
44840 goto alloc_error;
44841 }
44842 DUK_MEMZERO(res, sizeof(duk_hstring));
44843#if defined(DUK_USE_EXPLICIT_NULL_INIT)
44845#endif
44847
44848 data = (duk_uint8_t *) (res + 1);
44849 DUK_MEMCPY(data, str, blen);
44850 data[blen] = (duk_uint8_t) 0;
44851 }
44852
44854 if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) {
44856 }
44857
44858 /* All strings beginning with 0xff are treated as "internal",
44859 * even strings interned by the user. This allows user code to
44860 * create internal properties too, and makes behavior consistent
44861 * in case user code happens to use a string also used by Duktape
44862 * (such as string has already been interned and has the 'internal'
44863 * flag set).
44864 */
44866 if (blen > 0 && str[0] == (duk_uint8_t) 0xff) {
44868 }
44869
44870 DUK_HSTRING_SET_HASH(res, strhash);
44871 DUK_HSTRING_SET_BYTELEN(res, blen);
44872
44873 clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen);
44874 DUK_ASSERT(clen <= blen);
44875#if defined(DUK_USE_HSTRING_CLEN)
44876 DUK_HSTRING_SET_CHARLEN(res, clen);
44877#endif
44878
44879 /* Using an explicit 'ASCII' flag has larger footprint (one call site
44880 * only) but is quite useful for the case when there's no explicit
44881 * 'clen' in duk_hstring.
44882 */
44884 if (clen == blen) {
44886 }
44887
44888 DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld",
44889 (unsigned long) DUK_HSTRING_GET_HASH(res),
44890 (long) DUK_HSTRING_GET_BYTELEN(res),
44891 (long) DUK_HSTRING_GET_CHARLEN(res),
44892 (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
44893 (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
44894
44895 return res;
44896
44897 alloc_error:
44898 DUK_FREE(heap, res);
44899 return NULL;
44900}
44901
44902/*
44903 * String table algorithm: fixed size string table with array chaining
44904 *
44905 * The top level string table has a fixed size, with each slot holding
44906 * either NULL, string pointer, or pointer to a separately allocated
44907 * string pointer list.
44908 *
44909 * This is good for low memory environments using a pool allocator: the
44910 * top level allocation has a fixed size and the pointer lists have quite
44911 * small allocation size, which further matches the typical pool sizes
44912 * needed by objects, strings, property tables, etc.
44913 */
44914
44915#if defined(DUK_USE_STRTAB_CHAIN)
44916
44917#if defined(DUK_USE_HEAPPTR16)
44918DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
44919 duk_small_uint_t slotidx;
44921 duk_uint16_t *lst;
44922 duk_uint16_t *new_lst;
44923 duk_size_t i, n;
44924 duk_uint16_t null16 = heap->heapptr_null16;
44925 duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
44926
44927 DUK_ASSERT(heap != NULL);
44928 DUK_ASSERT(h != NULL);
44929
44932
44933 e = heap->strtable + slotidx;
44934 if (e->listlen == 0) {
44935 if (e->u.str16 == null16) {
44936 e->u.str16 = h16;
44937 } else {
44938 /* Now two entries in the same slot, alloc list */
44939 lst = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * 2);
44940 if (lst == NULL) {
44941 return 1; /* fail */
44942 }
44943 lst[0] = e->u.str16;
44944 lst[1] = h16;
44945 e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) lst);
44946 e->listlen = 2;
44947 }
44948 } else {
44949 DUK_ASSERT(e->u.strlist16 != null16);
44950 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
44951 DUK_ASSERT(lst != NULL);
44952 for (i = 0, n = e->listlen; i < n; i++) {
44953 if (lst[i] == null16) {
44954 lst[i] = h16;
44955 return 0;
44956 }
44957 }
44958
44959 if (e->listlen + 1 == 0) {
44960 /* Overflow, relevant mainly when listlen is 16 bits. */
44961 return 1; /* fail */
44962 }
44963
44964 new_lst = (duk_uint16_t *) DUK_REALLOC(heap, lst, sizeof(duk_uint16_t) * (e->listlen + 1));
44965 if (new_lst == NULL) {
44966 return 1; /* fail */
44967 }
44968 new_lst[e->listlen++] = h16;
44969 e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) new_lst);
44970 }
44971 return 0;
44972}
44973#else /* DUK_USE_HEAPPTR16 */
44974DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
44975 duk_small_uint_t slotidx;
44977 duk_hstring **lst;
44978 duk_hstring **new_lst;
44979 duk_size_t i, n;
44980
44981 DUK_ASSERT(heap != NULL);
44982 DUK_ASSERT(h != NULL);
44983
44986
44987 e = heap->strtable + slotidx;
44988 if (e->listlen == 0) {
44989 if (e->u.str == NULL) {
44990 e->u.str = h;
44991 } else {
44992 /* Now two entries in the same slot, alloc list */
44993 lst = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * 2);
44994 if (lst == NULL) {
44995 return 1; /* fail */
44996 }
44997 lst[0] = e->u.str;
44998 lst[1] = h;
44999 e->u.strlist = lst;
45000 e->listlen = 2;
45001 }
45002 } else {
45003 DUK_ASSERT(e->u.strlist != NULL);
45004 lst = e->u.strlist;
45005 for (i = 0, n = e->listlen; i < n; i++) {
45006 if (lst[i] == NULL) {
45007 lst[i] = h;
45008 return 0;
45009 }
45010 }
45011
45012 if (e->listlen + 1 == 0) {
45013 /* Overflow, relevant mainly when listlen is 16 bits. */
45014 return 1; /* fail */
45015 }
45016
45017 new_lst = (duk_hstring **) DUK_REALLOC(heap, e->u.strlist, sizeof(duk_hstring *) * (e->listlen + 1));
45018 if (new_lst == NULL) {
45019 return 1; /* fail */
45020 }
45021 new_lst[e->listlen++] = h;
45022 e->u.strlist = new_lst;
45023 }
45024 return 0;
45025}
45026#endif /* DUK_USE_HEAPPTR16 */
45027
45028#if defined(DUK_USE_HEAPPTR16)
45029DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45030 duk_small_uint_t slotidx;
45032 duk_uint16_t *lst;
45033 duk_size_t i, n;
45034 duk_uint16_t null16 = heap->heapptr_null16;
45035
45036 DUK_ASSERT(heap != NULL);
45037
45038 slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
45040
45041 e = heap->strtable + slotidx;
45042 if (e->listlen == 0) {
45043 if (e->u.str16 != null16) {
45044 duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
45045 DUK_ASSERT(h != NULL);
45046 if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
45047 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
45048 return h;
45049 }
45050 }
45051 } else {
45052 DUK_ASSERT(e->u.strlist16 != null16);
45053 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45054 DUK_ASSERT(lst != NULL);
45055 for (i = 0, n = e->listlen; i < n; i++) {
45056 if (lst[i] != null16) {
45057 duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[i]);
45058 DUK_ASSERT(h != NULL);
45059 if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
45060 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
45061 return h;
45062 }
45063 }
45064 }
45065 }
45066
45067 return NULL;
45068}
45069#else /* DUK_USE_HEAPPTR16 */
45070DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45071 duk_small_uint_t slotidx;
45073 duk_hstring **lst;
45074 duk_size_t i, n;
45075
45076 DUK_ASSERT(heap != NULL);
45077
45078 slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
45080
45081 e = heap->strtable + slotidx;
45082 if (e->listlen == 0) {
45083 if (e->u.str != NULL &&
45084 DUK_HSTRING_GET_BYTELEN(e->u.str) == blen &&
45085 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e->u.str), (size_t) blen) == 0) {
45086 return e->u.str;
45087 }
45088 } else {
45089 DUK_ASSERT(e->u.strlist != NULL);
45090 lst = e->u.strlist;
45091 for (i = 0, n = e->listlen; i < n; i++) {
45092 if (lst[i] != NULL &&
45093 DUK_HSTRING_GET_BYTELEN(lst[i]) == blen &&
45094 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(lst[i]), (size_t) blen) == 0) {
45095 return lst[i];
45096 }
45097 }
45098 }
45099
45100 return NULL;
45101}
45102#endif /* DUK_USE_HEAPPTR16 */
45103
45104#if defined(DUK_USE_HEAPPTR16)
45105DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
45106 duk_small_uint_t slotidx;
45108 duk_uint16_t *lst;
45109 duk_size_t i, n;
45110 duk_uint16_t h16;
45111 duk_uint16_t null16 = heap->heapptr_null16;
45112
45113 DUK_ASSERT(heap != NULL);
45114 DUK_ASSERT(h != NULL);
45115
45118
45119 DUK_ASSERT(h != NULL);
45120 h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45121
45122 e = heap->strtable + slotidx;
45123 if (e->listlen == 0) {
45124 if (e->u.str16 == h16) {
45125 e->u.str16 = null16;
45126 return;
45127 }
45128 } else {
45129 DUK_ASSERT(e->u.strlist16 != null16);
45130 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45131 DUK_ASSERT(lst != NULL);
45132 for (i = 0, n = e->listlen; i < n; i++) {
45133 if (lst[i] == h16) {
45134 lst[i] = null16;
45135 return;
45136 }
45137 }
45138 }
45139
45140 DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
45142 return;
45143}
45144#else /* DUK_USE_HEAPPTR16 */
45145DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
45146 duk_small_uint_t slotidx;
45148 duk_hstring **lst;
45149 duk_size_t i, n;
45150
45151 DUK_ASSERT(heap != NULL);
45152 DUK_ASSERT(h != NULL);
45153
45156
45157 e = heap->strtable + slotidx;
45158 if (e->listlen == 0) {
45159 DUK_ASSERT(h != NULL);
45160 if (e->u.str == h) {
45161 e->u.str = NULL;
45162 return;
45163 }
45164 } else {
45165 DUK_ASSERT(e->u.strlist != NULL);
45166 lst = e->u.strlist;
45167 for (i = 0, n = e->listlen; i < n; i++) {
45168 DUK_ASSERT(h != NULL);
45169 if (lst[i] == h) {
45170 lst[i] = NULL;
45171 return;
45172 }
45173 }
45174 }
45175
45176 DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
45178 return;
45179}
45180#endif /* DUK_USE_HEAPPTR16 */
45181
45182#if defined(DUK_USE_DEBUG)
45183DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
45186 duk_size_t j, n, used;
45187#if defined(DUK_USE_HEAPPTR16)
45188 duk_uint16_t *lst;
45189 duk_uint16_t null16 = heap->heapptr_null16;
45190#else
45191 duk_hstring **lst;
45192#endif
45193
45194 DUK_ASSERT(heap != NULL);
45195
45196 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
45197 e = heap->strtable + i;
45198
45199 if (e->listlen == 0) {
45200#if defined(DUK_USE_HEAPPTR16)
45201 DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str16 != null16 ? 1 : 0)));
45202#else
45203 DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str ? 1 : 0)));
45204#endif
45205 } else {
45206 used = 0;
45207#if defined(DUK_USE_HEAPPTR16)
45208 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45209#else
45210 lst = e->u.strlist;
45211#endif
45212 DUK_ASSERT(lst != NULL);
45213 for (j = 0, n = e->listlen; j < n; j++) {
45214#if defined(DUK_USE_HEAPPTR16)
45215 if (lst[j] != null16) {
45216#else
45217 if (lst[j] != NULL) {
45218#endif
45219 used++;
45220 }
45221 }
45222 DUK_DD(DUK_DDPRINT("[%03d] -> array %d/%d", (int) i, (int) used, (int) e->listlen));
45224 }
45225}
45226#endif /* DUK_USE_DEBUG */
45227
45228#endif /* DUK_USE_STRTAB_CHAIN */
45229
45230/*
45231 * String table algorithm: closed hashing with a probe sequence
45232 *
45233 * This is the default algorithm and works fine for environments with
45234 * minimal memory constraints.
45235 */
45236
45237#if defined(DUK_USE_STRTAB_PROBE)
45238
45239/* Count actually used (non-NULL, non-DELETED) entries. */
45241 duk_int_t res = 0;
45242 duk_uint_fast32_t i, n;
45243#if defined(DUK_USE_HEAPPTR16)
45244 duk_uint16_t null16 = heap->heapptr_null16;
45245 duk_uint16_t deleted16 = heap->heapptr_deleted16;
45246#endif
45248 n = (duk_uint_fast32_t) heap->st_size;
45249 for (i = 0; i < n; i++) {
45250#if defined(DUK_USE_HEAPPTR16)
45251 if (heap->strtable16[i] != null16 && heap->strtable16[i] != deleted16) {
45252#else
45253 if (heap->strtable[i] != NULL && heap->strtable[i] != DUK__DELETED_MARKER(heap)) {
45254#endif
45255 res++;
45256 }
45257 }
45258 return res;
45259}
45260
45261#if defined(DUK_USE_HEAPPTR16)
45262DUK_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) {
45263#else
45264DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
45265#endif
45266 duk_uint32_t i;
45267 duk_uint32_t step;
45268#if defined(DUK_USE_HEAPPTR16)
45269 duk_uint16_t null16 = heap->heapptr_null16;
45270 duk_uint16_t deleted16 = heap->heapptr_deleted16;
45271#endif
45272
45273 DUK_ASSERT(size > 0);
45274
45277 for (;;) {
45278#if defined(DUK_USE_HEAPPTR16)
45279 duk_uint16_t e16 = entries16[i];
45280#else
45281 duk_hstring *e = entries[i];
45282#endif
45283
45284#if defined(DUK_USE_HEAPPTR16)
45285 /* XXX: could check for e16 == 0 because NULL is guaranteed to
45286 * encode to zero.
45287 */
45288 if (e16 == null16) {
45289#else
45290 if (e == NULL) {
45291#endif
45292 DUK_DDD(DUK_DDDPRINT("insert hit (null): %ld", (long) i));
45293#if defined(DUK_USE_HEAPPTR16)
45294 entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45295#else
45296 entries[i] = h;
45297#endif
45298 (*p_used)++;
45299 break;
45300#if defined(DUK_USE_HEAPPTR16)
45301 } else if (e16 == deleted16) {
45302#else
45303 } else if (e == DUK__DELETED_MARKER(heap)) {
45304#endif
45305 /* st_used remains the same, DELETED is counted as used */
45306 DUK_DDD(DUK_DDDPRINT("insert hit (deleted): %ld", (long) i));
45307#if defined(DUK_USE_HEAPPTR16)
45308 entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45309#else
45310 entries[i] = h;
45311#endif
45312 break;
45313 }
45314 DUK_DDD(DUK_DDDPRINT("insert miss: %ld", (long) i));
45315 i = (i + step) % size;
45316
45317 /* looping should never happen */
45319 }
45320}
45321
45322#if defined(DUK_USE_HEAPPTR16)
45323DUK_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) {
45324#else
45325DUK_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) {
45326#endif
45327 duk_uint32_t i;
45328 duk_uint32_t step;
45329
45330 DUK_ASSERT(size > 0);
45331
45332 i = DUK__HASH_INITIAL(strhash, size);
45333 step = DUK__HASH_PROBE_STEP(strhash);
45334 for (;;) {
45335 duk_hstring *e;
45336#if defined(DUK_USE_HEAPPTR16)
45337 e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, entries16[i]);
45338#else
45339 e = entries[i];
45340#endif
45341
45342 if (!e) {
45343 return NULL;
45344 }
45345 if (e != DUK__DELETED_MARKER(heap) && DUK_HSTRING_GET_BYTELEN(e) == blen) {
45346 if (DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e), (size_t) blen) == 0) {
45347 DUK_DDD(DUK_DDDPRINT("find matching hit: %ld (step %ld, size %ld)",
45348 (long) i, (long) step, (long) size));
45349 return e;
45350 }
45351 }
45352 DUK_DDD(DUK_DDDPRINT("find matching miss: %ld (step %ld, size %ld)",
45353 (long) i, (long) step, (long) size));
45354 i = (i + step) % size;
45355
45356 /* looping should never happen */
45357 DUK_ASSERT(i != DUK__HASH_INITIAL(strhash, size));
45358 }
45360}
45361
45362#if defined(DUK_USE_HEAPPTR16)
45363DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_hstring *h) {
45364#else
45365DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h) {
45366#endif
45367 duk_uint32_t i;
45368 duk_uint32_t step;
45369 duk_uint32_t hash;
45370#if defined(DUK_USE_HEAPPTR16)
45371 duk_uint16_t null16 = heap->heapptr_null16;
45372 duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45373#endif
45374
45375 DUK_ASSERT(size > 0);
45376
45377 hash = DUK_HSTRING_GET_HASH(h);
45378 i = DUK__HASH_INITIAL(hash, size);
45379 step = DUK__HASH_PROBE_STEP(hash);
45380 for (;;) {
45381#if defined(DUK_USE_HEAPPTR16)
45382 duk_uint16_t e16 = entries16[i];
45383#else
45384 duk_hstring *e = entries[i];
45385#endif
45386
45387#if defined(DUK_USE_HEAPPTR16)
45388 if (e16 == null16) {
45389#else
45390 if (!e) {
45391#endif
45393 break;
45394 }
45395#if defined(DUK_USE_HEAPPTR16)
45396 if (e16 == h16) {
45397#else
45398 if (e == h) {
45399#endif
45400 /* st_used remains the same, DELETED is counted as used */
45401 DUK_DDD(DUK_DDDPRINT("free matching hit: %ld", (long) i));
45402#if defined(DUK_USE_HEAPPTR16)
45403 entries16[i] = heap->heapptr_deleted16;
45404#else
45405 entries[i] = DUK__DELETED_MARKER(heap);
45406#endif
45407 break;
45408 }
45409
45410 DUK_DDD(DUK_DDDPRINT("free matching miss: %ld", (long) i));
45411 i = (i + step) % size;
45412
45413 /* looping should never happen */
45414 DUK_ASSERT(i != DUK__HASH_INITIAL(hash, size));
45415 }
45416}
45417
45418DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size) {
45419#if defined(DUK_USE_DEBUG)
45420 duk_uint32_t old_used = heap->st_used;
45421#endif
45422 duk_uint32_t old_size = heap->st_size;
45423#if defined(DUK_USE_HEAPPTR16)
45424 duk_uint16_t *old_entries = heap->strtable16;
45425 duk_uint16_t *new_entries = NULL;
45426#else
45427 duk_hstring **old_entries = heap->strtable;
45428 duk_hstring **new_entries = NULL;
45429#endif
45430 duk_uint32_t new_used = 0;
45431 duk_uint32_t i;
45432
45433#if defined(DUK_USE_DEBUG)
45434 DUK_UNREF(old_used); /* unused with some debug level combinations */
45435#endif
45436
45437#ifdef DUK_USE_DDDPRINT
45438 DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
45439 (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
45440 (long) (((double) old_used) / ((double) old_size) * 100.0),
45441 (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) duk__count_used_probe(heap),
45442 (long) (((double) duk__count_used_probe(heap)) / ((double) new_size) * 100.0)));
45443#endif
45444
45445 DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used_probe(heap)); /* required for rehash to succeed, equality not that useful */
45446 DUK_ASSERT(old_entries);
45447
45448 /*
45449 * The attempt to allocate may cause a GC. Such a GC must not attempt to resize
45450 * the stringtable (though it can be swept); finalizer execution and object
45451 * compaction must also be postponed to avoid the pressure to add strings to the
45452 * string table. Call site must prevent these.
45453 */
45454
45455#if defined(DUK_USE_MARK_AND_SWEEP)
45459#endif
45460
45461#if defined(DUK_USE_HEAPPTR16)
45462 new_entries = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * new_size);
45463#else
45464 new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size);
45465#endif
45466
45467 if (!new_entries) {
45468 goto resize_error;
45469 }
45470
45471#if defined(DUK_USE_EXPLICIT_NULL_INIT)
45472 for (i = 0; i < new_size; i++) {
45473#if defined(DUK_USE_HEAPPTR16)
45474 new_entries[i] = heap->heapptr_null16;
45475#else
45476 new_entries[i] = NULL;
45477#endif
45478 }
45479#else
45480#if defined(DUK_USE_HEAPPTR16)
45481 /* Relies on NULL encoding to zero. */
45482 DUK_MEMZERO(new_entries, sizeof(duk_uint16_t) * new_size);
45483#else
45484 DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size);
45485#endif
45486#endif
45487
45488 /* Because new_size > duk__count_used_probe(heap), guaranteed to work */
45489 for (i = 0; i < old_size; i++) {
45490 duk_hstring *e;
45491
45492#if defined(DUK_USE_HEAPPTR16)
45493 e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, old_entries[i]);
45494#else
45495 e = old_entries[i];
45496#endif
45497 if (e == NULL || e == DUK__DELETED_MARKER(heap)) {
45498 continue;
45499 }
45500 /* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */
45501 duk__insert_hstring_probe(heap, new_entries, new_size, &new_used, e);
45502 }
45503
45504#ifdef DUK_USE_DDPRINT
45505 DUK_DD(DUK_DDPRINT("resized stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
45506 (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
45507 (long) (((double) old_used) / ((double) old_size) * 100.0),
45508 (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) new_used,
45509 (long) (((double) new_used) / ((double) new_size) * 100.0)));
45510#endif
45511
45512#if defined(DUK_USE_HEAPPTR16)
45513 DUK_FREE(heap, heap->strtable16);
45514 heap->strtable16 = new_entries;
45515#else
45516 DUK_FREE(heap, heap->strtable);
45517 heap->strtable = new_entries;
45518#endif
45519 heap->st_size = new_size;
45520 heap->st_used = new_used; /* may be less, since DELETED entries are NULLed by rehash */
45521
45522 return 0; /* OK */
45523
45524 resize_error:
45525 DUK_FREE(heap, new_entries);
45526 return 1; /* FAIL */
45527}
45528
45530 duk_uint32_t new_size;
45531 duk_bool_t ret;
45532
45533 new_size = (duk_uint32_t) duk__count_used_probe(heap);
45534 if (new_size >= 0x80000000UL) {
45536 } else {
45538 new_size = duk_util_get_hash_prime(new_size);
45539 }
45540 DUK_ASSERT(new_size > 0);
45541
45542 /* rehash even if old and new sizes are the same to get rid of
45543 * DELETED entries.
45544 */
45545
45546 ret = duk__resize_strtab_raw_probe(heap, new_size);
45547
45548 return ret;
45549}
45550
45551DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe(duk_heap *heap, duk_uint32_t new_used) {
45552 duk_uint32_t new_free;
45553 duk_uint32_t tmp1;
45554 duk_uint32_t tmp2;
45555
45556 DUK_ASSERT(new_used <= heap->st_size); /* grow by at most one */
45557 new_free = heap->st_size - new_used; /* unsigned intentionally */
45558
45559 /* new_free / size <= 1 / DIV <=> new_free <= size / DIV */
45560 /* new_used / size <= 1 / DIV <=> new_used <= size / DIV */
45561
45562 tmp1 = heap->st_size / DUK_STRTAB_MIN_FREE_DIVISOR;
45563 tmp2 = heap->st_size / DUK_STRTAB_MIN_USED_DIVISOR;
45564
45565 if (new_free <= tmp1 || new_used <= tmp2) {
45566 /* load factor too low or high, count actually used entries and resize */
45567 return duk__resize_strtab_probe(heap);
45568 } else {
45569 return 0; /* OK */
45570 }
45571}
45572
45573#if defined(DUK_USE_DEBUG)
45574DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
45575 duk_uint32_t i;
45576 duk_hstring *h;
45577
45578 DUK_ASSERT(heap != NULL);
45579#if defined(DUK_USE_HEAPPTR16)
45580 DUK_ASSERT(heap->strtable16 != NULL);
45581#else
45582 DUK_ASSERT(heap->strtable != NULL);
45583#endif
45584 DUK_UNREF(h);
45585
45586 for (i = 0; i < heap->st_size; i++) {
45587#if defined(DUK_USE_HEAPPTR16)
45588 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->strtable16[i]);
45589#else
45590 h = heap->strtable[i];
45591#endif
45592
45593 DUK_DD(DUK_DDPRINT("[%03d] -> %p", (int) i, (void *) h));
45594 }
45595}
45596#endif /* DUK_USE_DEBUG */
45597
45598#endif /* DUK_USE_STRTAB_PROBE */
45599
45600/*
45601 * Raw intern and lookup
45602 */
45603
45604DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45605 duk_hstring *res;
45606 const duk_uint8_t *extdata;
45607#if defined(DUK_USE_MARK_AND_SWEEP)
45608 duk_small_uint_t prev_mark_and_sweep_base_flags;
45609#endif
45610
45611 /* Prevent any side effects on the string table and the caller provided
45612 * str/blen arguments while interning is in progress. For example, if
45613 * the caller provided str/blen from a dynamic buffer, a finalizer might
45614 * resize that dynamic buffer, invalidating the call arguments.
45615 */
45616#if defined(DUK_USE_MARK_AND_SWEEP)
45618 prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
45620#endif
45621
45622#if defined(DUK_USE_STRTAB_PROBE)
45623 if (duk__recheck_strtab_size_probe(heap, heap->st_used + 1)) {
45624 goto failed;
45625 }
45626#endif
45627
45628 /* For manual testing only. */
45629#if 0
45630 {
45631 duk_size_t i;
45632 DUK_PRINTF("INTERN: \"");
45633 for (i = 0; i < blen; i++) {
45634 duk_uint8_t x = str[i];
45635 if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') {
45636 DUK_PRINTF("%c", (int) x); /* char: use int cast */
45637 } else {
45638 DUK_PRINTF("\\x%02lx", (long) x);
45639 }
45640 }
45641 DUK_PRINTF("\"\n");
45642 }
45643#endif
45644
45645#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
45646 extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
45647#else
45648 extdata = (const duk_uint8_t *) NULL;
45649#endif
45650 res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata);
45651 if (!res) {
45652 goto failed;
45653 }
45654
45655#if defined(DUK_USE_STRTAB_CHAIN)
45656 if (duk__insert_hstring_chain(heap, res)) {
45657 /* failed */
45658 DUK_FREE(heap, res);
45659 goto failed;
45660 }
45661#elif defined(DUK_USE_STRTAB_PROBE)
45662 /* guaranteed to succeed */
45664#if defined(DUK_USE_HEAPPTR16)
45665 heap->strtable16,
45666#else
45667 heap->strtable,
45668#endif
45669 heap->st_size,
45670 &heap->st_used,
45671 res);
45672#else
45673#error internal error, invalid strtab options
45674#endif
45676 /* Note: hstring is in heap but has refcount zero and is not strongly reachable.
45677 * Caller should increase refcount and make the hstring reachable before any
45678 * operations which require allocation (and possible gc).
45679 */
45680
45681 done:
45682#if defined(DUK_USE_MARK_AND_SWEEP)
45683 heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
45684#endif
45685 return res;
45686
45687 failed:
45688 res = NULL;
45689 goto done;
45690}
45691
45692DUK_LOCAL duk_hstring *duk__do_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash) {
45693 duk_hstring *res;
45694
45695 DUK_ASSERT(out_strhash);
45696
45697 *out_strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
45698
45699#if defined(DUK_USE_ROM_STRINGS)
45700 {
45702 /* XXX: This is VERY inefficient now, and should be e.g. a
45703 * binary search or perfect hash, to be fixed.
45704 */
45705 for (i = 0; i < (duk_small_uint_t) (sizeof(duk_rom_strings) / sizeof(duk_hstring *)); i++) {
45706 duk_hstring *romstr;
45707 romstr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings[i]);
45708 if (blen == DUK_HSTRING_GET_BYTELEN(romstr) &&
45709 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(romstr), blen) == 0) {
45710 DUK_DD(DUK_DDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
45711 romstr, (unsigned long) *out_strhash, (unsigned long) DUK_HSTRING_GET_HASH(romstr)));
45712 DUK_ASSERT(*out_strhash == DUK_HSTRING_GET_HASH(romstr));
45713 *out_strhash = DUK_HSTRING_GET_HASH(romstr);
45714 return romstr;
45715 }
45716 }
45717 }
45718#endif /* DUK_USE_ROM_STRINGS */
45719
45720#if defined(DUK_USE_STRTAB_CHAIN)
45721 res = duk__find_matching_string_chain(heap, str, blen, *out_strhash);
45722#elif defined(DUK_USE_STRTAB_PROBE)
45724#if defined(DUK_USE_HEAPPTR16)
45725 heap->strtable16,
45726#else
45727 heap->strtable,
45728#endif
45729 heap->st_size,
45730 str,
45731 blen,
45732 *out_strhash);
45733#else
45734#error internal error, invalid strtab options
45735#endif
45736
45737 return res;
45738}
45739
45740/*
45741 * Exposed calls
45742 */
45743
45744#if 0 /*unused*/
45745DUK_INTERNAL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
45746 duk_uint32_t strhash; /* dummy */
45747 return duk__do_lookup(heap, str, blen, &strhash);
45748}
45749#endif
45751DUK_INTERNAL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
45752 duk_hstring *res;
45753 duk_uint32_t strhash;
45754
45755 /* caller is responsible for ensuring this */
45757
45758 res = duk__do_lookup(heap, str, blen, &strhash);
45759 if (res) {
45760 return res;
45761 }
45762
45763 res = duk__do_intern(heap, str, blen, strhash);
45764 return res; /* may be NULL */
45765}
45766
45767DUK_INTERNAL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
45768 duk_hstring *res = duk_heap_string_intern(thr->heap, str, blen);
45769 if (!res) {
45771 }
45772 return res;
45773}
45774
45775#if 0 /*unused*/
45776DUK_INTERNAL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val) {
45777 char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
45778 DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
45779 buf[sizeof(buf) - 1] = (char) 0;
45780 DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX); /* formatted result limited */
45781 return duk_heap_string_lookup(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
45782}
45783#endif
45784
45787 DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
45788 buf[sizeof(buf) - 1] = (char) 0;
45789 DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX); /* formatted result limited */
45790 return duk_heap_string_intern(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
45791}
45792
45795 if (!res) {
45797 }
45798 return res;
45799}
45800
45801/* find and remove string from stringtable; caller must free the string itself */
45802#if defined(DUK_USE_REFERENCE_COUNTING)
45804 DUK_DDD(DUK_DDDPRINT("remove string from stringtable: %!O", (duk_heaphdr *) h));
45805
45806#if defined(DUK_USE_STRTAB_CHAIN)
45807 duk__remove_matching_hstring_chain(heap, h);
45808#elif defined(DUK_USE_STRTAB_PROBE)
45810#if defined(DUK_USE_HEAPPTR16)
45811 heap->strtable16,
45812#else
45813 heap->strtable,
45814#endif
45815 heap->st_size,
45816 h);
45817#else
45818#error internal error, invalid strtab options
45819#endif
45820}
45821#endif
45822
45823#if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
45825 duk_small_uint_t prev_mark_and_sweep_base_flags;
45826 /* Force a resize so that DELETED entries are eliminated.
45827 * Another option would be duk__recheck_strtab_size_probe();
45828 * but since that happens on every intern anyway, this whole
45829 * check can now be disabled.
45830 */
45831
45833 prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
45835
45836#if defined(DUK_USE_STRTAB_CHAIN)
45837 DUK_UNREF(heap);
45838#elif defined(DUK_USE_STRTAB_PROBE)
45839 (void) duk__resize_strtab_probe(heap);
45840#endif
45841
45842 heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
45843}
45844#endif
45845
45846#if defined(DUK_USE_STRTAB_CHAIN)
45848 /* Free strings in the stringtable and any allocations needed
45849 * by the stringtable itself.
45850 */
45851 duk_uint_fast32_t i, j;
45853#if defined(DUK_USE_HEAPPTR16)
45854 duk_uint16_t *lst;
45855 duk_uint16_t null16 = heap->heapptr_null16;
45856#else
45857 duk_hstring **lst;
45858#endif
45859 duk_hstring *h;
45860
45861 for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
45862 e = heap->strtable + i;
45863 if (e->listlen > 0) {
45864#if defined(DUK_USE_HEAPPTR16)
45865 lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45866#else
45867 lst = e->u.strlist;
45868#endif
45869 DUK_ASSERT(lst != NULL);
45870
45871 for (j = 0; j < e->listlen; j++) {
45872#if defined(DUK_USE_HEAPPTR16)
45873 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
45874 lst[j] = null16;
45875#else
45876 h = lst[j];
45877 lst[j] = NULL;
45878#endif
45879 /* strings may have inner refs (extdata) in some cases */
45880 if (h != NULL) {
45881 duk_free_hstring_inner(heap, h);
45882 DUK_FREE(heap, h);
45883 }
45884 }
45885#if defined(DUK_USE_HEAPPTR16)
45886 e->u.strlist16 = null16;
45887#else
45888 e->u.strlist = NULL;
45889#endif
45890 DUK_FREE(heap, lst);
45891 } else {
45892#if defined(DUK_USE_HEAPPTR16)
45893 h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
45894 e->u.str16 = null16;
45895#else
45896 h = e->u.str;
45897 e->u.str = NULL;
45898#endif
45899 if (h != NULL) {
45900 duk_free_hstring_inner(heap, h);
45901 DUK_FREE(heap, h);
45902 }
45903 }
45904 e->listlen = 0;
45905 }
45906}
45907#endif /* DUK_USE_STRTAB_CHAIN */
45908
45909#if defined(DUK_USE_STRTAB_PROBE)
45912 duk_hstring *h;
45913
45914#if defined(DUK_USE_HEAPPTR16)
45915 if (heap->strtable16) {
45916#else
45917 if (heap->strtable) {
45918#endif
45919 for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
45920#if defined(DUK_USE_HEAPPTR16)
45921 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
45922#else
45923 h = heap->strtable[i];
45924#endif
45925 if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
45926 continue;
45927 }
45928 DUK_ASSERT(h != NULL);
45929
45930 /* strings may have inner refs (extdata) in some cases */
45931 duk_free_hstring_inner(heap, h);
45932 DUK_FREE(heap, h);
45933#if 0 /* not strictly necessary */
45934 heap->strtable[i] = NULL;
45935#endif
45936 }
45937#if defined(DUK_USE_HEAPPTR16)
45938 DUK_FREE(heap, heap->strtable16);
45939#else
45940 DUK_FREE(heap, heap->strtable);
45941#endif
45942#if 0 /* not strictly necessary */
45943 heap->strtable = NULL;
45944#endif
45945 }
45946}
45947#endif /* DUK_USE_STRTAB_PROBE */
45948
45949/* Undefine local defines */
45950#undef DUK__HASH_INITIAL
45951#undef DUK__HASH_PROBE_STEP
45952#undef DUK__DELETED_MARKER
45953#line 1 "duk_hobject_alloc.c"
45954/*
45955 * Hobject allocation.
45956 *
45957 * Provides primitive allocation functions for all object types (plain object,
45958 * compiled function, native function, thread). The object return is not yet
45959 * in "heap allocated" list and has a refcount of zero, so caller must careful.
45960 */
45961
45962/* include removed: duk_internal.h */
45963
45964DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags) {
45965#ifdef DUK_USE_EXPLICIT_NULL_INIT
45966 DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
45967#endif
45968
45969 /* XXX: macro? sets both heaphdr and object flags */
45970 obj->hdr.h_flags = hobject_flags;
45971 DUK_HEAPHDR_SET_TYPE(&obj->hdr, DUK_HTYPE_OBJECT); /* also goes into flags */
45972
45973#if defined(DUK_USE_HEAPPTR16)
45974 /* Zero encoded pointer is required to match NULL */
45975 DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
45976#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
45977 DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
45978#endif
45979#endif
45980 DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);
45982
45983 /*
45984 * obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
45985 * with this properly. This is intentional: empty objects consume a minimum
45986 * amount of memory. Further, an initial allocation might fail and cause
45987 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
45988 */
45989}
45990
45991/*
45992 * Allocate an duk_hobject.
45993 *
45994 * The allocated object has no allocation for properties; the caller may
45995 * want to force a resize if a desired size is known.
45996 *
45997 * The allocated object has zero reference count and is not reachable.
45998 * The caller MUST make the object reachable and increase its reference
45999 * count before invoking any operation that might require memory allocation.
46000 */
46001
46003 duk_hobject *res;
46004
46005 DUK_ASSERT(heap != NULL);
46007 /* different memory layout, alloc size, and init */
46008 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPILEDFUNCTION) == 0);
46009 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATIVEFUNCTION) == 0);
46010 DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_THREAD) == 0);
46011
46012 res = (duk_hobject *) DUK_ALLOC(heap, sizeof(duk_hobject));
46013 if (!res) {
46014 return NULL;
46015 }
46016 DUK_MEMZERO(res, sizeof(duk_hobject));
46017
46018 duk__init_object_parts(heap, res, hobject_flags);
46019
46020 return res;
46021}
46022
46025
46026 res = (duk_hcompiledfunction *) DUK_ALLOC(heap, sizeof(duk_hcompiledfunction));
46027 if (!res) {
46028 return NULL;
46029 }
46031
46032 duk__init_object_parts(heap, &res->obj, hobject_flags);
46033
46034#ifdef DUK_USE_EXPLICIT_NULL_INIT
46035#ifdef DUK_USE_HEAPPTR16
46036 /* NULL pointer is required to encode to zero, so memset is enough. */
46037#else
46038 res->data = NULL;
46039 res->funcs = NULL;
46040 res->bytecode = NULL;
46041#endif
46042#endif
46043
46044 return res;
46045}
46046
46049
46050 res = (duk_hnativefunction *) DUK_ALLOC(heap, sizeof(duk_hnativefunction));
46051 if (!res) {
46052 return NULL;
46053 }
46054 DUK_MEMZERO(res, sizeof(duk_hnativefunction));
46055
46056 duk__init_object_parts(heap, &res->obj, hobject_flags);
46057
46058#ifdef DUK_USE_EXPLICIT_NULL_INIT
46059 res->func = NULL;
46060#endif
46061
46062 return res;
46063}
46064
46066 duk_hbufferobject *res;
46067
46068 res = (duk_hbufferobject *) DUK_ALLOC(heap, sizeof(duk_hbufferobject));
46069 if (!res) {
46070 return NULL;
46071 }
46072 DUK_MEMZERO(res, sizeof(duk_hbufferobject));
46073
46074 duk__init_object_parts(heap, &res->obj, hobject_flags);
46076#ifdef DUK_USE_EXPLICIT_NULL_INIT
46077 res->buf = NULL;
46078#endif
46079
46081 return res;
46082}
46083
46084/*
46085 * Allocate a new thread.
46086 *
46087 * Leaves the built-ins array uninitialized. The caller must either
46088 * initialize a new global context or share existing built-ins from
46089 * another thread.
46090 */
46091
46093 duk_hthread *res;
46094
46095 res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
46096 if (!res) {
46097 return NULL;
46098 }
46099 DUK_MEMZERO(res, sizeof(duk_hthread));
46100
46101 duk__init_object_parts(heap, &res->obj, hobject_flags);
46102
46103#ifdef DUK_USE_EXPLICIT_NULL_INIT
46104 res->ptr_curr_pc = NULL;
46105 res->heap = NULL;
46106 res->valstack = NULL;
46107 res->valstack_end = NULL;
46108 res->valstack_bottom = NULL;
46109 res->valstack_top = NULL;
46110 res->callstack = NULL;
46111 res->catchstack = NULL;
46112 res->resumer = NULL;
46113 res->compile_ctx = NULL,
46114#ifdef DUK_USE_HEAPPTR16
46115 res->strs16 = NULL;
46116#else
46117 res->strs = NULL;
46118#endif
46119 {
46120 int i;
46121 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
46122 res->builtins[i] = NULL;
46123 }
46124 }
46125#endif
46126 /* when nothing is running, API calls are in non-strict mode */
46127 DUK_ASSERT(res->strict == 0);
46128
46129 res->heap = heap;
46133
46134 return res;
46135}
46136
46137#if 0 /* unused now */
46138DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) {
46139 duk_hobject *res = duk_hobject_alloc(thr->heap, hobject_flags);
46140 if (!res) {
46142 }
46143 return res;
46144}
46145#endif
46146#line 1 "duk_hobject_enum.c"
46147/*
46148 * Hobject enumeration support.
46149 *
46150 * Creates an internal enumeration state object to be used e.g. with for-in
46151 * enumeration. The state object contains a snapshot of target object keys
46152 * and internal control state for enumeration. Enumerator flags allow caller
46153 * to e.g. request internal/non-enumerable properties, and to enumerate only
46154 * "own" properties.
46155 *
46156 * Also creates the result value for e.g. Object.keys() based on the same
46157 * internal structure.
46158 *
46159 * This snapshot-based enumeration approach is used to simplify enumeration:
46160 * non-snapshot-based approaches are difficult to reconcile with mutating
46161 * the enumeration target, running multiple long-lived enumerators at the
46162 * same time, garbage collection details, etc. The downside is that the
46163 * enumerator object is memory inefficient especially for iterating arrays.
46164 */
46165
46166/* include removed: duk_internal.h */
46167
46168/* XXX: identify enumeration target with an object index (not top of stack) */
46169
46170/* must match exactly the number of internal properties inserted to enumerator */
46171#define DUK__ENUM_START_INDEX 2
46172
46173DUK_LOCAL const duk_uint16_t duk__bufferobject_virtual_props[] = {
46178};
46179
46180/*
46181 * Helper to sort array index keys. The keys are in the enumeration object
46182 * entry part, starting from DUK__ENUM_START_INDEX, and the entry part is dense.
46183 *
46184 * We use insertion sort because it is simple (leading to compact code,)
46185 * works nicely in-place, and minimizes operations if data is already sorted
46186 * or nearly sorted (which is a very common case here). It also minimizes
46187 * the use of element comparisons in general. This is nice because element
46188 * comparisons here involve re-parsing the string keys into numbers each
46189 * time, which is naturally very expensive.
46190 *
46191 * Note that the entry part values are all "true", e.g.
46192 *
46193 * "1" -> true, "3" -> true, "2" -> true
46194 *
46195 * so it suffices to only work in the key part without exchanging any keys,
46196 * simplifying the sort.
46197 *
46198 * http://en.wikipedia.org/wiki/Insertion_sort
46199 *
46200 * (Compiles to about 160 bytes now as a stand-alone function.)
46201 */
46202
46204 duk_hstring **keys;
46205 duk_hstring **p_curr, **p_insert, **p_end;
46206 duk_hstring *h_curr;
46207 duk_uarridx_t val_highest, val_curr, val_insert;
46208
46209 DUK_ASSERT(h_obj != NULL);
46210 DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h_obj) >= 2); /* control props */
46211 DUK_UNREF(thr);
46212
46213 if (DUK_HOBJECT_GET_ENEXT(h_obj) <= 1 + DUK__ENUM_START_INDEX) {
46214 return;
46215 }
46216
46217 keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
46218 p_end = keys + DUK_HOBJECT_GET_ENEXT(h_obj);
46219 keys += DUK__ENUM_START_INDEX;
46220
46221 DUK_DDD(DUK_DDDPRINT("keys=%p, p_end=%p (after skipping enum props)",
46222 (void *) keys, (void *) p_end));
46223
46224#ifdef DUK_USE_DDDPRINT
46225 {
46227 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
46228 DUK_DDD(DUK_DDDPRINT("initial: %ld %p -> %!O",
46229 (long) i,
46230 (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
46231 (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
46232 }
46233 }
46234#endif
46235
46236 val_highest = DUK_HSTRING_GET_ARRIDX_SLOW(keys[0]);
46237 for (p_curr = keys + 1; p_curr < p_end; p_curr++) {
46238 DUK_ASSERT(*p_curr != NULL);
46239 val_curr = DUK_HSTRING_GET_ARRIDX_SLOW(*p_curr);
46240
46241 if (val_curr >= val_highest) {
46242 DUK_DDD(DUK_DDDPRINT("p_curr=%p, p_end=%p, val_highest=%ld, val_curr=%ld -> "
46243 "already in correct order, next",
46244 (void *) p_curr, (void *) p_end, (long) val_highest, (long) val_curr));
46245 val_highest = val_curr;
46246 continue;
46247 }
46248
46249 DUK_DDD(DUK_DDDPRINT("p_curr=%p, p_end=%p, val_highest=%ld, val_curr=%ld -> "
46250 "needs to be inserted",
46251 (void *) p_curr, (void *) p_end, (long) val_highest, (long) val_curr));
46252
46253 /* Needs to be inserted; scan backwards, since we optimize
46254 * for the case where elements are nearly in order.
46255 */
46256
46257 p_insert = p_curr - 1;
46258 for (;;) {
46259 val_insert = DUK_HSTRING_GET_ARRIDX_SLOW(*p_insert);
46260 if (val_insert < val_curr) {
46261 DUK_DDD(DUK_DDDPRINT("p_insert=%p, val_insert=%ld, val_curr=%ld -> insert after this",
46262 (void *) p_insert, (long) val_insert, (long) val_curr));
46263 p_insert++;
46264 break;
46265 }
46266 if (p_insert == keys) {
46267 DUK_DDD(DUK_DDDPRINT("p_insert=%p -> out of keys, insert to beginning", (void *) p_insert));
46268 break;
46269 }
46270 DUK_DDD(DUK_DDDPRINT("p_insert=%p, val_insert=%ld, val_curr=%ld -> search backwards",
46271 (void *) p_insert, (long) val_insert, (long) val_curr));
46272 p_insert--;
46273 }
46274
46275 DUK_DDD(DUK_DDDPRINT("final p_insert=%p", (void *) p_insert));
46276
46277 /* .-- p_insert .-- p_curr
46278 * v v
46279 * | ... | insert | ... | curr
46280 */
46281
46282 h_curr = *p_curr;
46283 DUK_DDD(DUK_DDDPRINT("memmove: dest=%p, src=%p, size=%ld, h_curr=%p",
46284 (void *) (p_insert + 1), (void *) p_insert,
46285 (long) (p_curr - p_insert), (void *) h_curr));
46286
46287 DUK_MEMMOVE((void *) (p_insert + 1),
46288 (const void *) p_insert,
46289 (size_t) ((p_curr - p_insert) * sizeof(duk_hstring *)));
46290 *p_insert = h_curr;
46291 /* keep val_highest */
46292 }
46293
46294#ifdef DUK_USE_DDDPRINT
46295 {
46297 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
46298 DUK_DDD(DUK_DDDPRINT("final: %ld %p -> %!O",
46299 (long) i,
46300 (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
46301 (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
46302 }
46303 }
46304#endif
46305}
46306
46307/*
46308 * Create an internal enumerator object E, which has its keys ordered
46309 * to match desired enumeration ordering. Also initialize internal control
46310 * properties for enumeration.
46311 *
46312 * Note: if an array was used to hold enumeration keys instead, an array
46313 * scan would be needed to eliminate duplicates found in the prototype chain.
46314 */
46315
46317 duk_hthread *thr = (duk_hthread *) ctx;
46318 duk_hobject *enum_target;
46319 duk_hobject *curr;
46320 duk_hobject *res;
46321#if defined(DUK_USE_ES6_PROXY)
46322 duk_hobject *h_proxy_target;
46323 duk_hobject *h_proxy_handler;
46324 duk_hobject *h_trap_result;
46325#endif
46326 duk_uint_fast32_t i, len; /* used for array, stack, and entry indices */
46327
46328 DUK_ASSERT(ctx != NULL);
46329
46330 DUK_DDD(DUK_DDDPRINT("create enumerator, stack top: %ld", (long) duk_get_top(ctx)));
46331
46332 enum_target = duk_require_hobject(ctx, -1);
46333 DUK_ASSERT(enum_target != NULL);
46334
46336 res = duk_require_hobject(ctx, -1);
46337
46338 DUK_DDD(DUK_DDDPRINT("created internal object"));
46339
46340 /* [enum_target res] */
46341
46342 /* Target must be stored so that we can recheck whether or not
46343 * keys still exist when we enumerate. This is not done if the
46344 * enumeration result comes from a proxy trap as there is no
46345 * real object to check against.
46346 */
46347 duk_push_hobject(ctx, enum_target);
46349
46350 /* Initialize index so that we skip internal control keys. */
46353
46354 /*
46355 * Proxy object handling
46356 */
46357
46358#if defined(DUK_USE_ES6_PROXY)
46359 if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
46360 goto skip_proxy;
46361 }
46363 enum_target,
46364 &h_proxy_target,
46365 &h_proxy_handler))) {
46366 goto skip_proxy;
46367 }
46368
46369 DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
46370 duk_push_hobject(ctx, h_proxy_handler);
46372 /* No need to replace the 'enum_target' value in stack, only the
46373 * enum_target reference. This also ensures that the original
46374 * enum target is reachable, which keeps the proxy and the proxy
46375 * target reachable. We do need to replace the internal _Target.
46376 */
46377 DUK_DDD(DUK_DDDPRINT("no enumerate trap, enumerate proxy target instead"));
46378 DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
46379 enum_target = h_proxy_target;
46380
46381 duk_push_hobject(ctx, enum_target); /* -> [ ... enum_target res handler undefined target ] */
46383
46384 duk_pop_2(ctx); /* -> [ ... enum_target res ] */
46385 goto skip_proxy;
46386 }
46387
46388 /* [ ... enum_target res handler trap ] */
46389 duk_insert(ctx, -2);
46390 duk_push_hobject(ctx, h_proxy_target); /* -> [ ... enum_target res trap handler target ] */
46391 duk_call_method(ctx, 1 /*nargs*/); /* -> [ ... enum_target res trap_result ] */
46392 h_trap_result = duk_require_hobject(ctx, -1);
46393 DUK_UNREF(h_trap_result);
46394
46395 /* Copy trap result keys into the enumerator object. */
46396 len = (duk_uint_fast32_t) duk_get_length(ctx, -1);
46397 for (i = 0; i < len; i++) {
46398 /* XXX: not sure what the correct semantic details are here,
46399 * e.g. handling of missing values (gaps), handling of non-array
46400 * trap results, etc.
46401 *
46402 * For keys, we simply skip non-string keys which seems to be
46403 * consistent with how e.g. Object.keys() will process proxy trap
46404 * results (ES6, Section 19.1.2.14).
46405 */
46406 if (duk_get_prop_index(ctx, -1, i) && duk_is_string(ctx, -1)) {
46407 /* [ ... enum_target res trap_result val ] */
46408 duk_push_true(ctx);
46409 /* [ ... enum_target res trap_result val true ] */
46410 duk_put_prop(ctx, -4);
46411 } else {
46412 duk_pop(ctx);
46413 }
46414 }
46415 /* [ ... enum_target res trap_result ] */
46416 duk_pop(ctx);
46417 duk_remove(ctx, -2);
46418
46419 /* [ ... res ] */
46420
46421 /* The internal _Target property is kept pointing to the original
46422 * enumeration target (the proxy object), so that the enumerator
46423 * 'next' operation can read property values if so requested. The
46424 * fact that the _Target is a proxy disables key existence check
46425 * during enumeration.
46426 */
46427 DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
46428 goto compact_and_return;
46429
46430 skip_proxy:
46431#endif /* DUK_USE_ES6_PROXY */
46432
46433 curr = enum_target;
46434 while (curr) {
46435 /*
46436 * Virtual properties.
46437 *
46438 * String and buffer indices are virtual and always enumerable,
46439 * 'length' is virtual and non-enumerable. Array and arguments
46440 * object props have special behavior but are concrete.
46441 */
46442
46445 /* String and buffer enumeration behavior is identical now,
46446 * so use shared handler.
46447 */
46449 duk_hstring *h_val;
46450 h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
46451 DUK_ASSERT(h_val != NULL); /* string objects must not created without internal value */
46453 } else {
46454 duk_hbufferobject *h_bufobj;
46456 h_bufobj = (duk_hbufferobject *) curr;
46457 if (h_bufobj == NULL) {
46458 /* Neutered buffer, zero length seems
46459 * like good behavior here.
46460 */
46461 len = 0;
46462 } else {
46463 /* There's intentionally no check for
46464 * current underlying buffer length.
46465 */
46466 len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
46467 }
46468 }
46469
46470 for (i = 0; i < len; i++) {
46471 duk_hstring *k;
46472
46474 DUK_ASSERT(k);
46475 duk_push_hstring(ctx, k);
46476 duk_push_true(ctx);
46477
46478 /* [enum_target res key true] */
46479 duk_put_prop(ctx, -3);
46480
46481 /* [enum_target res] */
46482 }
46483
46484 /* 'length' and other virtual properties are not
46485 * enumerable, but are included if non-enumerable
46486 * properties are requested.
46487 */
46488
46489 if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
46491
46492 if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
46493 n = sizeof(duk__bufferobject_virtual_props) / sizeof(duk_uint16_t);
46494 } else {
46497 n = 1; /* only 'length' */
46498 }
46499
46500 for (i = 0; i < n; i++) {
46502 duk_push_true(ctx);
46503 duk_put_prop(ctx, -3);
46504 }
46505
46506 }
46507 } else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(curr)) {
46508 if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
46510 duk_push_true(ctx);
46511 duk_put_prop(ctx, -3);
46512 }
46513 }
46514
46515 /*
46516 * Array part
46517 *
46518 * Note: ordering between array and entry part must match 'abandon array'
46519 * behavior in duk_hobject_props.c: key order after an array is abandoned
46520 * must be the same.
46521 */
46522
46523 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
46524 duk_hstring *k;
46525 duk_tval *tv;
46526
46527 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
46528 if (DUK_TVAL_IS_UNUSED(tv)) {
46529 continue;
46530 }
46532 DUK_ASSERT(k);
46533
46534 duk_push_hstring(ctx, k);
46535 duk_push_true(ctx);
46536
46537 /* [enum_target res key true] */
46538 duk_put_prop(ctx, -3);
46539
46540 /* [enum_target res] */
46541 }
46542
46543 /*
46544 * Entries part
46545 */
46546
46547 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
46548 duk_hstring *k;
46549
46550 k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
46551 if (!k) {
46552 continue;
46553 }
46554 if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i) &&
46555 !(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
46556 continue;
46557 }
46558 if (DUK_HSTRING_HAS_INTERNAL(k) &&
46559 !(enum_flags & DUK_ENUM_INCLUDE_INTERNAL)) {
46560 continue;
46561 }
46562 if ((enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) &&
46564 continue;
46565 }
46566
46569
46570 duk_push_hstring(ctx, k);
46571 duk_push_true(ctx);
46572
46573 /* [enum_target res key true] */
46574 duk_put_prop(ctx, -3);
46575
46576 /* [enum_target res] */
46577 }
46578
46579 if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
46580 break;
46581 }
46582
46583 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
46584 }
46585
46586 /* [enum_target res] */
46587
46588 duk_remove(ctx, -2);
46589
46590 /* [res] */
46591
46594 /*
46595 * Some E5/E5.1 algorithms require that array indices are iterated
46596 * in a strictly ascending order. This is the case for e.g.
46597 * Array.prototype.forEach() and JSON.stringify() PropertyList
46598 * handling.
46599 *
46600 * To ensure this property for arrays with an array part (and
46601 * arbitrary objects too, since e.g. forEach() can be applied
46602 * to an array), the caller can request that we sort the keys
46603 * here.
46604 */
46605
46606 /* XXX: avoid this at least when enum_target is an Array, it has an
46607 * array part, and no ancestor properties were included? Not worth
46608 * it for JSON, but maybe worth it for forEach().
46609 */
46610
46611 /* XXX: may need a 'length' filter for forEach()
46612 */
46613 DUK_DDD(DUK_DDDPRINT("sort array indices by caller request"));
46614 duk__sort_array_indices(thr, res);
46615 }
46616
46617#if defined(DUK_USE_ES6_PROXY)
46618 compact_and_return:
46619#endif
46620 /* compact; no need to seal because object is internal */
46621 duk_hobject_compact_props(thr, res);
46622
46623 DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
46624}
46625
46626/*
46627 * Returns non-zero if a key and/or value was enumerated, and:
46628 *
46629 * [enum] -> [key] (get_value == 0)
46630 * [enum] -> [key value] (get_value == 1)
46631 *
46632 * Returns zero without pushing anything on the stack otherwise.
46633 */
46635 duk_hthread *thr = (duk_hthread *) ctx;
46636 duk_hobject *e;
46637 duk_hobject *enum_target;
46638 duk_hstring *res = NULL;
46640 duk_bool_t check_existence;
46641
46642 DUK_ASSERT(ctx != NULL);
46643
46644 /* [... enum] */
46645
46646 e = duk_require_hobject(ctx, -1);
46647
46648 /* XXX use get tval ptr, more efficient */
46650 idx = (duk_uint_fast32_t) duk_require_uint(ctx, -1);
46651 duk_pop(ctx);
46652 DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
46653
46654 /* Enumeration keys are checked against the enumeration target (to see
46655 * that they still exist). In the proxy enumeration case _Target will
46656 * be the proxy, and checking key existence against the proxy is not
46657 * required (or sensible, as the keys may be fully virtual).
46658 */
46660 enum_target = duk_require_hobject(ctx, -1);
46661 DUK_ASSERT(enum_target != NULL);
46662#if defined(DUK_USE_ES6_PROXY)
46663 check_existence = (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(enum_target));
46664#else
46665 check_existence = 1;
46666#endif
46667 duk_pop(ctx); /* still reachable */
46668
46669 DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
46670 (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(ctx, -1)));
46671
46672 /* no array part */
46673 for (;;) {
46674 duk_hstring *k;
46675
46676 if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
46677 DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
46678 break;
46679 }
46680
46681 /* we know these because enum objects are internally created */
46682 k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
46683 DUK_ASSERT(k != NULL);
46686
46687 idx++;
46688
46689 /* recheck that the property still exists */
46690 if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
46691 DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
46692 continue;
46693 }
46694
46695 DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
46696 res = k;
46697 break;
46698 }
46699
46700 DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
46701
46702 duk_push_u32(ctx, (duk_uint32_t) idx);
46704
46705 /* [... enum] */
46706
46707 if (res) {
46708 duk_push_hstring(ctx, res);
46709 if (get_value) {
46710 duk_push_hobject(ctx, enum_target);
46711 duk_dup(ctx, -2); /* -> [... enum key enum_target key] */
46712 duk_get_prop(ctx, -2); /* -> [... enum key enum_target val] */
46713 duk_remove(ctx, -2); /* -> [... enum key val] */
46714 duk_remove(ctx, -3); /* -> [... key val] */
46715 } else {
46716 duk_remove(ctx, -2); /* -> [... key] */
46717 }
46718 return 1;
46719 } else {
46720 duk_pop(ctx); /* -> [...] */
46721 return 0;
46722 }
46723}
46724
46725/*
46726 * Get enumerated keys in an Ecmascript array. Matches Object.keys() behavior
46727 * described in E5 Section 15.2.3.14.
46728 */
46729
46731 duk_hthread *thr = (duk_hthread *) ctx;
46732 duk_hobject *e;
46735
46736 DUK_ASSERT(ctx != NULL);
46737 DUK_ASSERT(duk_get_hobject(ctx, -1) != NULL);
46738 DUK_UNREF(thr);
46739
46740 /* Create a temporary enumerator to get the (non-duplicated) key list;
46741 * the enumerator state is initialized without being needed, but that
46742 * has little impact.
46743 */
46744
46745 duk_hobject_enumerator_create(ctx, enum_flags);
46746 duk_push_array(ctx);
46747
46748 /* [enum_target enum res] */
46749
46750 e = duk_require_hobject(ctx, -2);
46751 DUK_ASSERT(e != NULL);
46752
46753 idx = 0;
46755 duk_hstring *k;
46756
46757 k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, i);
46758 DUK_ASSERT(k); /* enumerator must have no keys deleted */
46759
46760 /* [enum_target enum res] */
46761 duk_push_hstring(ctx, k);
46762 duk_put_prop_index(ctx, -2, idx);
46763 idx++;
46764 }
46765
46766 /* [enum_target enum res] */
46767 duk_remove(ctx, -2);
46768
46769 /* [enum_target res] */
46770
46771 return 1; /* return 1 to allow callers to tail call */
46772}
46773#line 1 "duk_hobject_finalizer.c"
46774/*
46775 * Run an duk_hobject finalizer. Used for both reference counting
46776 * and mark-and-sweep algorithms. Must never throw an error.
46777 *
46778 * There is no return value. Any return value or error thrown by
46779 * the finalizer is ignored (although errors are debug logged).
46780 *
46781 * Notes:
46782 *
46783 * - The thread used for calling the finalizer is the same as the
46784 * 'thr' argument. This may need to change later.
46785 *
46786 * - The finalizer thread 'top' assertions are there because it is
46787 * critical that strict stack policy is observed (i.e. no cruft
46788 * left on the finalizer stack).
46789 */
46790
46791/* include removed: duk_internal.h */
46792
46794 duk_hthread *thr;
46795
46796 DUK_ASSERT(ctx != NULL);
46797 thr = (duk_hthread *) ctx;
46798
46799 DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
46800
46801 /* [... obj] */
46802
46803 /* XXX: Finalizer lookup should traverse the prototype chain (to allow
46804 * inherited finalizers) but should not invoke accessors or proxy object
46805 * behavior. At the moment this lookup will invoke proxy behavior, so
46806 * caller must ensure that this function is not called if the target is
46807 * a Proxy.
46808 */
46809
46810 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */
46811 if (!duk_is_callable(ctx, -1)) {
46812 DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
46813 return 0;
46814 }
46815 duk_dup(ctx, -2);
46817 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
46818 duk_call(ctx, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
46819 DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
46820 return 0;
46821
46822 /* Note: we rely on duk_safe_call() to fix up the stack for the caller,
46823 * so we don't need to pop stuff here. There is no return value;
46824 * caller determines rescued status based on object refcount.
46825 */
46826}
46827
46829 duk_context *ctx = (duk_context *) thr;
46830 duk_ret_t rc;
46831#ifdef DUK_USE_ASSERTIONS
46832 duk_idx_t entry_top;
46833#endif
46834
46835 DUK_DDD(DUK_DDDPRINT("running object finalizer for object: %p", (void *) obj));
46836
46837 DUK_ASSERT(thr != NULL);
46838 DUK_ASSERT(ctx != NULL);
46839 DUK_ASSERT(obj != NULL);
46841
46842#ifdef DUK_USE_ASSERTIONS
46843 entry_top = duk_get_top(ctx);
46844#endif
46845 /*
46846 * Get and call the finalizer. All of this must be wrapped
46847 * in a protected call, because even getting the finalizer
46848 * may trigger an error (getter may throw one, for instance).
46849 */
46850
46853 DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
46854 return;
46855 }
46856 DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */
46858 /* This shouldn't happen; call sites should avoid looking up
46859 * _Finalizer "through" a Proxy, but ignore if we come here
46860 * with a Proxy to avoid finalizer re-entry.
46861 */
46862 DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call"));
46863 return;
46864 }
46865
46866 /* XXX: use a NULL error handler for the finalizer call? */
46867
46868 DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
46869 duk_push_hobject(ctx, obj); /* this also increases refcount by one */
46870 rc = duk_safe_call(ctx, duk__finalize_helper, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
46871 DUK_ASSERT_TOP(ctx, entry_top + 2); /* duk_safe_call discipline */
46872
46873 if (rc != DUK_EXEC_SUCCESS) {
46874 /* Note: we ask for one return value from duk_safe_call to get this
46875 * error debugging here.
46876 */
46877 DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
46878 (void *) obj, (duk_tval *) duk_get_tval(ctx, -1)));
46879 }
46880 duk_pop_2(ctx); /* -> [...] */
46881
46882 DUK_ASSERT_TOP(ctx, entry_top);
46883}
46884#line 1 "duk_hobject_misc.c"
46885/*
46886 * Misc support functions
46887 */
46888
46889/* include removed: duk_internal.h */
46890
46892 duk_uint_t sanity;
46893
46894 DUK_ASSERT(thr != NULL);
46895
46896 /* False if the object is NULL or the prototype 'p' is NULL.
46897 * In particular, false if both are NULL (don't compare equal).
46898 */
46899 if (h == NULL || p == NULL) {
46900 return 0;
46901 }
46902
46904 do {
46905 if (h == p) {
46906 return 1;
46907 }
46908
46909 if (sanity-- == 0) {
46910 if (ignore_loop) {
46911 break;
46912 } else {
46914 }
46915 }
46916 h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
46917 } while (h);
46918
46919 return 0;
46920}
46921
46923#ifdef DUK_USE_REFERENCE_COUNTING
46924 duk_hobject *tmp;
46925
46926 DUK_ASSERT(h);
46927 tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
46928 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
46929 DUK_HOBJECT_INCREF_ALLOWNULL(thr, p); /* avoid problems if p == h->prototype */
46931#else
46932 DUK_ASSERT(h);
46933 DUK_UNREF(thr);
46934 DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
46935#endif
46936}
46937#line 1 "duk_hobject_pc2line.c"
46938/*
46939 * Helpers for creating and querying pc2line debug data, which
46940 * converts a bytecode program counter to a source line number.
46941 *
46942 * The run-time pc2line data is bit-packed, and documented in:
46943 *
46944 * doc/function-objects.rst
46945 */
46946
46947/* include removed: duk_internal.h */
46948
46949#if defined(DUK_USE_PC2LINE)
46950
46951/* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
46953 duk_context *ctx = (duk_context *) thr;
46954 duk_hbuffer_dynamic *h_buf;
46955 duk_bitencoder_ctx be_ctx_alloc;
46956 duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
46957 duk_uint32_t *hdr;
46958 duk_size_t new_size;
46959 duk_uint_fast32_t num_header_entries;
46960 duk_uint_fast32_t curr_offset;
46961 duk_int_fast32_t curr_line, next_line, diff_line;
46962 duk_uint_fast32_t curr_pc;
46963 duk_uint_fast32_t hdr_index;
46964
46966
46967 /* XXX: add proper spare handling to dynamic buffer, to minimize
46968 * reallocs; currently there is no spare at all.
46969 */
46970
46971 num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
46972 curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
46973
46974 duk_push_dynamic_buffer(ctx, (duk_size_t) curr_offset);
46975 h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
46976 DUK_ASSERT(h_buf != NULL);
46978
46979 hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
46980 DUK_ASSERT(hdr != NULL);
46981 hdr[0] = (duk_uint32_t) length; /* valid pc range is [0, length[ */
46982
46983 curr_pc = 0U;
46984 while (curr_pc < length) {
46985 new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
46986 duk_hbuffer_resize(thr, h_buf, new_size);
46987
46988 hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
46989 DUK_ASSERT(hdr != NULL);
46990 DUK_ASSERT(curr_pc < length);
46991 hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
46992 curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
46993 hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
46994 hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
46995
46996#if 0
46997 DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
46998 (long) (curr_pc / DUK_PC2LINE_SKIP),
46999 (long) curr_pc,
47000 (long) hdr[hdr_index + 0],
47001 (long) hdr[hdr_index + 1]));
47002#endif
47003
47004 DUK_MEMZERO(be_ctx, sizeof(*be_ctx));
47005 be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
47007
47008 for (;;) {
47009 curr_pc++;
47010 if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) || /* end of diff run */
47011 (curr_pc >= length) ) { /* end of bytecode */
47012 break;
47013 }
47014 DUK_ASSERT(curr_pc < length);
47015 next_line = (duk_int32_t) instrs[curr_pc].line;
47016 diff_line = next_line - curr_line;
47017
47018#if 0
47019 DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
47020 (long) curr_line, (long) next_line, (long) diff_line));
47021#endif
47022
47023 if (diff_line == 0) {
47024 /* 0 */
47025 duk_be_encode(be_ctx, 0, 1);
47026 } else if (diff_line >= 1 && diff_line <= 4) {
47027 /* 1 0 <2 bits> */
47028 duk_be_encode(be_ctx, (0x02 << 2) + (diff_line - 1), 4);
47029 } else if (diff_line >= -0x80 && diff_line <= 0x7f) {
47030 /* 1 1 0 <8 bits> */
47031 DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
47032 duk_be_encode(be_ctx, (0x06 << 8) + (diff_line + 0x80), 11);
47033 } else {
47034 /* 1 1 1 <32 bits>
47035 * Encode in two parts to avoid bitencode 24-bit limitation
47036 */
47037 duk_be_encode(be_ctx, (0x07 << 16) + ((next_line >> 16) & 0xffffU), 19);
47038 duk_be_encode(be_ctx, next_line & 0xffffU, 16);
47039 }
47040
47041 curr_line = next_line;
47042 }
47043
47044 duk_be_finish(be_ctx);
47045 DUK_ASSERT(!be_ctx->truncated);
47046
47047 /* be_ctx->offset == length of encoded bitstream */
47048 curr_offset += (duk_uint_fast32_t) be_ctx->offset;
47050
47051 /* compact */
47052 new_size = (duk_size_t) curr_offset;
47053 duk_hbuffer_resize(thr, h_buf, new_size);
47054
47055 (void) duk_to_fixed_buffer(ctx, -1, NULL);
47056
47057 DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
47058 (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
47059 (duk_tval *) duk_get_tval(ctx, -1)));
47060}
47061
47062/* PC is unsigned. If caller does PC arithmetic and gets a negative result,
47063 * it will map to a large PC which is out of bounds and causes a zero to be
47064 * returned.
47065 */
47067 duk_bitdecoder_ctx bd_ctx_alloc;
47068 duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
47069 duk_uint32_t *hdr;
47070 duk_uint_fast32_t start_offset;
47071 duk_uint_fast32_t pc_limit;
47072 duk_uint_fast32_t hdr_index;
47073 duk_uint_fast32_t pc_base;
47075 duk_uint_fast32_t curr_line;
47076
47077 DUK_ASSERT(buf != NULL);
47079 DUK_UNREF(thr);
47080
47081 /*
47082 * Use the index in the header to find the right starting point
47083 */
47084
47085 hdr_index = pc / DUK_PC2LINE_SKIP;
47086 pc_base = hdr_index * DUK_PC2LINE_SKIP;
47087 n = pc - pc_base;
47088
47089 if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
47090 DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
47091 goto error;
47092 }
47093
47094 hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
47095 pc_limit = hdr[0];
47096 if (pc >= pc_limit) {
47097 /* Note: pc is unsigned and cannot be negative */
47098 DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
47099 (long) pc, (long) pc_limit));
47100 goto error;
47101 }
47102
47103 curr_line = hdr[1 + hdr_index * 2];
47104 start_offset = hdr[1 + hdr_index * 2 + 1];
47105 if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
47106 DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
47107 (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
47108 goto error;
47109 }
47110
47111 /*
47112 * Iterate the bitstream (line diffs) until PC is reached
47113 */
47114
47115 DUK_MEMZERO(bd_ctx, sizeof(*bd_ctx));
47116 bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
47117 bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
47118
47119#if 0
47120 DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
47121 (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
47122#endif
47123
47124 while (n > 0) {
47125#if 0
47126 DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
47127#endif
47128
47129 if (duk_bd_decode_flag(bd_ctx)) {
47130 if (duk_bd_decode_flag(bd_ctx)) {
47131 if (duk_bd_decode_flag(bd_ctx)) {
47132 /* 1 1 1 <32 bits> */
47134 t = duk_bd_decode(bd_ctx, 16); /* workaround: max nbits = 24 now */
47135 t = (t << 16) + duk_bd_decode(bd_ctx, 16);
47136 curr_line = t;
47137 } else {
47138 /* 1 1 0 <8 bits> */
47140 t = duk_bd_decode(bd_ctx, 8);
47141 curr_line = curr_line + t - 0x80;
47142 }
47143 } else {
47144 /* 1 0 <2 bits> */
47146 t = duk_bd_decode(bd_ctx, 2);
47147 curr_line = curr_line + t + 1;
47148 }
47149 } else {
47150 /* 0: no change */
47151 }
47152
47153 n--;
47154 }
47155
47156 DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
47157 return curr_line;
47158
47159 error:
47160 DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
47161 return 0;
47162}
47163
47165 duk_hbuffer_fixed *pc2line;
47166 duk_uint_fast32_t line;
47167
47168 /* XXX: now that pc2line is used by the debugger quite heavily in
47169 * checked execution, this should be optimized to avoid value stack
47170 * and perhaps also implement some form of pc2line caching (see
47171 * future work in debugger.rst).
47172 */
47173
47175 pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
47176 if (pc2line != NULL) {
47178 line = duk__hobject_pc2line_query_raw((duk_hthread *) ctx, pc2line, (duk_uint_fast32_t) pc);
47179 } else {
47180 line = 0;
47181 }
47182 duk_pop(ctx);
47183
47184 return line;
47185}
47186
47187#endif /* DUK_USE_PC2LINE */
47188#line 1 "duk_hobject_props.c"
47189/*
47190 * Hobject property set/get functionality.
47191 *
47192 * This is very central functionality for size, performance, and compliance.
47193 * It is also rather intricate; see hobject-algorithms.rst for discussion on
47194 * the algorithms and memory-management.rst for discussion on refcounts and
47195 * side effect issues.
47196 *
47197 * Notes:
47198 *
47199 * - It might be tempting to assert "refcount nonzero" for objects
47200 * being operated on, but that's not always correct: objects with
47201 * a zero refcount may be operated on by the refcount implementation
47202 * (finalization) for instance. Hence, no refcount assertions are made.
47203 *
47204 * - Many operations (memory allocation, identifier operations, etc)
47205 * may cause arbitrary side effects (e.g. through GC and finalization).
47206 * These side effects may invalidate duk_tval pointers which point to
47207 * areas subject to reallocation (like value stack). Heap objects
47208 * themselves have stable pointers. Holding heap object pointers or
47209 * duk_tval copies is not problematic with respect to side effects;
47210 * care must be taken when holding and using argument duk_tval pointers.
47211 *
47212 * - If a finalizer is executed, it may operate on the the same object
47213 * we're currently dealing with. For instance, the finalizer might
47214 * delete a certain property which has already been looked up and
47215 * confirmed to exist. Ideally finalizers would be disabled if GC
47216 * happens during property access. At the moment property table realloc
47217 * disables finalizers, and all DECREFs may cause arbitrary changes so
47218 * handle DECREF carefully.
47219 *
47220 * - The order of operations for a DECREF matters. When DECREF is executed,
47221 * the entire object graph must be consistent; note that a refzero may
47222 * lead to a mark-and-sweep through a refcount finalizer.
47224
47225/*
47226 * XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
47227 * might be more appropriate.
47228 */
47229
47231 * XXX: duk_uint_fast32_t should probably be used in many places here.
47232 */
47233
47234/* include removed: duk_internal.h */
47235
47237 * Local defines
47238 */
47239
47240#define DUK__NO_ARRAY_INDEX DUK_HSTRING_NO_ARRAY_INDEX
47242/* hash probe sequence */
47243#define DUK__HASH_INITIAL(hash,h_size) DUK_HOBJECT_HASH_INITIAL((hash),(h_size))
47244#define DUK__HASH_PROBE_STEP(hash) DUK_HOBJECT_HASH_PROBE_STEP((hash))
47245
47246/* marker values for hash part */
47247#define DUK__HASH_UNUSED DUK_HOBJECT_HASHIDX_UNUSED
47248#define DUK__HASH_DELETED DUK_HOBJECT_HASHIDX_DELETED
47249
47250/* valstack space that suffices for all local calls, including recursion
47251 * of other than Duktape calls (getters etc)
47252 */
47253#define DUK__VALSTACK_SPACE 10
47254
47255/* valstack space allocated especially for proxy lookup which does a
47256 * recursive property lookup
47257 */
47258#define DUK__VALSTACK_PROXY_LOOKUP 20
47259
47260/*
47261 * Local prototypes
47262 */
47263
47267
47268DUK_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);
47270
47273DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc);
47274
47275/*
47276 * Misc helpers
47277 */
47278
47279/* Convert a duk_tval number (caller checks) to a 32-bit index. Returns
47280 * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
47281 * index.
47282 */
47283/* XXX: for fastints, could use a variant which assumes a double duk_tval
47284 * (and doesn't need to check for fastint again).
47285 */
47287 duk_double_t dbl;
47288 duk_uint32_t idx;
47289
47290 DUK_ASSERT(tv != NULL);
47292
47293 /* -0 is accepted here as index 0 because ToString(-0) == "0" which is
47294 * in canonical form and thus an array index.
47295 */
47296 dbl = DUK_TVAL_GET_NUMBER(tv);
47297 idx = (duk_uint32_t) dbl;
47298 if ((duk_double_t) idx == dbl) {
47299 /* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
47300 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
47301 */
47302 return idx;
47303 }
47304 return DUK__NO_ARRAY_INDEX;
47305}
47306
47307#if defined(DUK_USE_FASTINT)
47308/* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
47309DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
47310 duk_int64_t t;
47311
47312 DUK_ASSERT(tv != NULL);
47313 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
47315 t = DUK_TVAL_GET_FASTINT(tv);
47316 if ((t & ~0xffffffffULL) != 0) {
47317 /* Catches >0x100000000 and negative values. */
47318 return DUK__NO_ARRAY_INDEX;
47319 }
47320
47321 /* If the value happens to be 0xFFFFFFFF, it's not a valid array index
47322 * but will then match DUK__NO_ARRAY_INDEX.
47323 */
47324 return (duk_uint32_t) t;
47325}
47326#endif /* DUK_USE_FASTINT */
47327
47328/* Push an arbitrary duk_tval to the stack, coerce it to string, and return
47329 * both a duk_hstring pointer and an array index (or DUK__NO_ARRAY_INDEX).
47330 */
47332 duk_uint32_t arr_idx;
47334
47335 DUK_ASSERT(ctx != NULL);
47336 DUK_ASSERT(tv != NULL);
47337 DUK_ASSERT(out_h != NULL);
47338
47339 duk_push_tval(ctx, tv);
47340 duk_to_string(ctx, -1);
47341 h = duk_get_hstring(ctx, -1);
47342 DUK_ASSERT(h != NULL);
47343 *out_h = h;
47344
47346 return arr_idx;
47347}
47348
47349/* String is an own (virtual) property of a lightfunc. */
47351 DUK_UNREF(thr);
47352 return (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
47353 key == DUK_HTHREAD_STRING_NAME(thr));
47354}
47355
47356/*
47357 * Helpers for managing property storage size
47358 */
47359
47360/* Get default hash part size for a certain entry part size. */
47361#if defined(DUK_USE_HOBJECT_HASH_PART)
47362DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
47365 if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
47366 duk_uint32_t res;
47367
47368 /* result: hash_prime(floor(1.2 * e_size)) */
47369 res = duk_util_get_hash_prime(e_size + e_size / DUK_HOBJECT_H_SIZE_DIVISOR);
47370
47371 /* if fails, e_size will be zero = not an issue, except performance-wise */
47372 DUK_ASSERT(res == 0 || res > e_size);
47373 return res;
47374 } else {
47375 return 0;
47376 }
47377}
47378#endif /* USE_PROP_HASH_PART */
47379
47380/* Get minimum entry part growth for a certain size. */
47381DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
47382 duk_uint32_t res;
47383
47385
47387 DUK_ASSERT(res >= 1); /* important for callers */
47388 return res;
47389}
47390
47391/* Get minimum array part growth for a certain size. */
47392DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
47393 duk_uint32_t res;
47394
47396
47398 DUK_ASSERT(res >= 1); /* important for callers */
47399 return res;
47400}
47401
47402/* Count actually used entry part entries (non-NULL keys). */
47405 duk_uint_fast32_t n = 0;
47406 duk_hstring **e;
47407
47409 DUK_UNREF(thr);
47410
47411 e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
47412 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
47413 if (*e++) {
47414 n++;
47415 }
47416 }
47417 return (duk_uint32_t) n;
47418}
47419
47420/* Count actually used array part entries and array minimum size.
47421 * NOTE: 'out_min_size' can be computed much faster by starting from the
47422 * end and breaking out early when finding first used entry, but this is
47423 * not needed now.
47424 */
47425DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
47427 duk_uint_fast32_t used = 0;
47428 duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1; /* see below */
47429 duk_tval *a;
47430
47431 DUK_ASSERT(obj != NULL);
47432 DUK_ASSERT(out_used != NULL);
47433 DUK_ASSERT(out_min_size != NULL);
47434 DUK_UNREF(thr);
47435
47436 a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
47437 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
47438 duk_tval *tv = a++;
47439 if (!DUK_TVAL_IS_UNUSED(tv)) {
47440 used++;
47441 highest_idx = i;
47442 }
47443 }
47444
47445 /* Initial value for highest_idx is -1 coerced to unsigned. This
47446 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
47447 * for out_min_size as intended.
47448 */
47449
47450 *out_used = used;
47451 *out_min_size = highest_idx + 1; /* 0 if no used entries */
47452}
47453
47454/* Check array density and indicate whether or not the array part should be abandoned. */
47455DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
47456 /*
47457 * Array abandon check; abandon if:
47458 *
47459 * new_used / new_size < limit
47460 * new_used < limit * new_size || limit is 3 bits fixed point
47461 * new_used < limit' / 8 * new_size || *8
47462 * 8*new_used < limit' * new_size || :8
47463 * new_used < limit' * (new_size / 8)
47464 *
47465 * Here, new_used = a_used, new_size = a_size.
47466 *
47467 * Note: some callers use approximate values for a_used and/or a_size
47468 * (e.g. dropping a '+1' term). This doesn't affect the usefulness
47469 * of the check, but may confuse debugging.
47470 */
47471
47472 return (a_used < DUK_HOBJECT_A_ABANDON_LIMIT * (a_size >> 3));
47473}
47474
47475/* Fast check for extending array: check whether or not a slow density check is required. */
47476DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
47477 /*
47478 * In a fast check we assume old_size equals old_used (i.e., existing
47479 * array is fully dense).
47480 *
47481 * Slow check if:
47482 *
47483 * (new_size - old_size) / old_size > limit
47484 * new_size - old_size > limit * old_size
47485 * new_size > (1 + limit) * old_size || limit' is 3 bits fixed point
47486 * new_size > (1 + (limit' / 8)) * old_size || * 8
47487 * 8 * new_size > (8 + limit') * old_size || : 8
47488 * new_size > (8 + limit') * (old_size / 8)
47489 * new_size > limit'' * (old_size / 8) || limit'' = 9 -> max 25% increase
47490 * arr_idx + 1 > limit'' * (old_size / 8)
47491 *
47492 * This check doesn't work well for small values, so old_size is rounded
47493 * up for the check (and the '+ 1' of arr_idx can be ignored in practice):
47494 *
47495 * arr_idx > limit'' * ((old_size + 7) / 8)
47496 */
47497
47498 return (arr_idx > DUK_HOBJECT_A_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
47499}
47500
47501/*
47502 * Proxy helpers
47503 */
47504
47505#if defined(DUK_USE_ES6_PROXY)
47507 duk_tval *tv_target;
47508 duk_tval *tv_handler;
47509 duk_hobject *h_target;
47510 duk_hobject *h_handler;
47511
47512 DUK_ASSERT(thr != NULL);
47513 DUK_ASSERT(obj != NULL);
47514 DUK_ASSERT(out_target != NULL);
47515 DUK_ASSERT(out_handler != NULL);
47516
47517 /* Caller doesn't need to check exotic proxy behavior (but does so for
47518 * some fast paths).
47519 */
47521 return 0;
47522 }
47523
47525 if (!tv_handler) {
47527 return 0;
47528 }
47529 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_handler));
47530 h_handler = DUK_TVAL_GET_OBJECT(tv_handler);
47531 DUK_ASSERT(h_handler != NULL);
47532 *out_handler = h_handler;
47533 tv_handler = NULL; /* avoid issues with relocation */
47534
47536 if (!tv_target) {
47538 return 0;
47539 }
47540 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
47541 h_target = DUK_TVAL_GET_OBJECT(tv_target);
47542 DUK_ASSERT(h_target != NULL);
47543 *out_target = h_target;
47544 tv_target = NULL; /* avoid issues with relocation */
47545
47546 return 1;
47547}
47548#endif /* DUK_USE_ES6_PROXY */
47549
47550/* Get Proxy target object. If the argument is not a Proxy, return it as is.
47551 * If a Proxy is revoked, an error is thrown.
47552 */
47553#if defined(DUK_USE_ES6_PROXY)
47555 duk_hobject *h_target;
47556 duk_hobject *h_handler;
47557
47558 DUK_ASSERT(thr != NULL);
47559 DUK_ASSERT(obj != NULL);
47560
47561 /* Resolve Proxy targets until Proxy chain ends. No explicit check for
47562 * a Proxy loop: user code cannot create such a loop without tweaking
47563 * internal properties directly.
47565
47567 if (duk_hobject_proxy_check(thr, obj, &h_target, &h_handler)) {
47568 DUK_ASSERT(h_target != NULL);
47569 obj = h_target;
47570 } else {
47571 break;
47572 }
47573 }
47574
47575 DUK_ASSERT(obj != NULL);
47576 return obj;
47577}
47578#endif /* DUK_USE_ES6_PROXY */
47579
47580#if defined(DUK_USE_ES6_PROXY)
47582 duk_context *ctx = (duk_context *) thr;
47583 duk_hobject *h_handler;
47584
47585 DUK_ASSERT(thr != NULL);
47586 DUK_ASSERT(obj != NULL);
47587 DUK_ASSERT(tv_key != NULL);
47588 DUK_ASSERT(out_target != NULL);
47589
47590 if (!duk_hobject_proxy_check(thr, obj, out_target, &h_handler)) {
47591 return 0;
47592 }
47593 DUK_ASSERT(*out_target != NULL);
47594 DUK_ASSERT(h_handler != NULL);
47595
47596 /* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
47597 * normal property set/get which would allow a proxy handler to interfere with
47598 * such behavior and to get access to internal key strings. This is not a problem
47599 * as such because internal key strings can be created in other ways too (e.g.
47600 * through buffers). The best fix is to change Duktape internal lookups to
47601 * skip proxy behavior. Until that, internal property accesses bypass the
47602 * proxy and are applied to the target (as if the handler did not exist).
47603 * This has some side effects, see test-bi-proxy-internal-keys.js.
47604 */
47605
47606 if (DUK_TVAL_IS_STRING(tv_key)) {
47607 duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
47608 DUK_ASSERT(h_key != NULL);
47609 if (DUK_HSTRING_HAS_INTERNAL(h_key)) {
47610 DUK_DDD(DUK_DDDPRINT("internal key, skip proxy handler and apply to target"));
47611 return 0;
47612 }
47613 }
47614
47615 /* The handler is looked up with a normal property lookup; it may be an
47616 * accessor or the handler object itself may be a proxy object. If the
47617 * handler is a proxy, we need to extend the valstack as we make a
47618 * recursive proxy check without a function call in between (in fact
47619 * there is no limit to the potential recursion here).
47620 *
47621 * (For sanity, proxy creation rejects another proxy object as either
47622 * the handler or the target at the moment so recursive proxy cases
47623 * are not realized now.)
47624 */
47625
47626 /* XXX: C recursion limit if proxies are allowed as handler/target values */
47627
47629 duk_push_hobject(ctx, h_handler);
47630 if (duk_get_prop_stridx(ctx, -1, stridx_trap)) {
47631 /* -> [ ... handler trap ] */
47632 duk_insert(ctx, -2); /* -> [ ... trap handler ] */
47633
47634 /* stack prepped for func call: [ ... trap handler ] */
47635 return 1;
47636 } else {
47637 duk_pop_2(ctx);
47638 return 0;
47639 }
47640}
47641#endif /* DUK_USE_ES6_PROXY */
47642
47643/*
47644 * Reallocate property allocation, moving properties to the new allocation.
47645 *
47646 * Includes key compaction, rehashing, and can also optionally abandoning
47647 * the array part, 'migrating' array entries into the beginning of the
47648 * new entry part. Arguments are not validated here, so e.g. new_h_size
47649 * MUST be a valid prime.
47650 *
47651 * There is no support for in-place reallocation or just compacting keys
47652 * without resizing the property allocation. This is intentional to keep
47653 * code size minimal.
47654 *
47655 * The implementation is relatively straightforward, except for the array
47656 * abandonment process. Array abandonment requires that new string keys
47657 * are interned, which may trigger GC. All keys interned so far must be
47658 * reachable for GC at all times; valstack is used for that now.
47660 * Also, a GC triggered during this reallocation process must not interfere
47661 * with the object being resized. This is currently controlled by using
47662 * heap->mark_and_sweep_base_flags to indicate that no finalizers will be
47663 * executed (as they can affect ANY object) and no objects are compacted
47664 * (it would suffice to protect this particular object only, though).
47665 *
47666 * Note: a non-checked variant would be nice but is a bit tricky to
47667 * implement for the array abandonment process. It's easy for
47668 * everything else.
47669 *
47670 * Note: because we need to potentially resize the valstack (as part
47671 * of abandoning the array part), any tval pointers to the valstack
47672 * will become invalid after this call.
47673 */
47674
47677 duk_hobject *obj,
47678 duk_uint32_t new_e_size,
47679 duk_uint32_t new_a_size,
47680 duk_uint32_t new_h_size,
47681 duk_bool_t abandon_array) {
47682 duk_context *ctx = (duk_context *) thr;
47683#ifdef DUK_USE_MARK_AND_SWEEP
47684 duk_small_uint_t prev_mark_and_sweep_base_flags;
47685#endif
47686 duk_uint32_t new_alloc_size;
47687 duk_uint32_t new_e_size_adjusted;
47688 duk_uint8_t *new_p;
47689 duk_hstring **new_e_k;
47690 duk_propvalue *new_e_pv;
47691 duk_uint8_t *new_e_f;
47692 duk_tval *new_a;
47693 duk_uint32_t *new_h;
47694 duk_uint32_t new_e_next;
47696
47697 DUK_ASSERT(thr != NULL);
47698 DUK_ASSERT(ctx != NULL);
47699 DUK_ASSERT(obj != NULL);
47700 DUK_ASSERT(!abandon_array || new_a_size == 0); /* if abandon_array, new_a_size must be 0 */
47701 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
47702 DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size); /* required to guarantee success of rehashing,
47703 * intentionally use unadjusted new_e_size
47704 */
47707
47708 /*
47709 * Pre resize assertions.
47710 */
47711
47712#ifdef DUK_USE_ASSERTIONS
47713 /* XXX: pre-checks (such as no duplicate keys) */
47714#endif
47715
47716 /*
47717 * For property layout 1, tweak e_size to ensure that the whole entry
47718 * part (key + val + flags) is a suitable multiple for alignment
47719 * (platform specific).
47720 *
47721 * Property layout 2 does not require this tweaking and is preferred
47722 * on low RAM platforms requiring alignment.
47723 */
47724
47725#if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
47726 DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
47727 new_e_size_adjusted = new_e_size;
47728#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
47729 DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
47730 new_e_size_adjusted = new_e_size;
47731#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
47732 new_e_size_adjusted = (new_e_size + DUK_HOBJECT_ALIGN_TARGET - 1) & (~(DUK_HOBJECT_ALIGN_TARGET - 1));
47733 DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
47734 (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
47735 DUK_ASSERT(new_e_size_adjusted >= new_e_size);
47736#else
47737#error invalid hobject layout defines
47738#endif
47739
47740 /*
47741 * Debug logging after adjustment.
47742 */
47743
47744 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 "
47745 "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
47746 (void *) obj,
47750 (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
47751 (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
47752 (long) DUK_HOBJECT_GET_ESIZE(obj),
47753 (long) DUK_HOBJECT_GET_ENEXT(obj),
47754 (long) DUK_HOBJECT_GET_ASIZE(obj),
47755 (long) DUK_HOBJECT_GET_HSIZE(obj),
47756 (long) new_e_size_adjusted,
47757 (long) new_a_size,
47758 (long) new_h_size,
47759 (long) abandon_array,
47760 (long) new_e_size));
47761
47762 /*
47763 * Property count check. This is the only point where we ensure that
47764 * we don't get more (allocated) property space that we can handle.
47765 * There aren't hard limits as such, but some algorithms fail (e.g.
47766 * finding next higher prime, selecting hash part size) if we get too
47767 * close to the 4G property limit.
47768 *
47769 * Since this works based on allocation size (not actually used size),
47770 * the limit is a bit approximate but good enough in practice.
47771 */
47772
47773 if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
47775 }
47776
47777 /*
47778 * Compute new alloc size and alloc new area.
47779 *
47780 * The new area is allocated as a dynamic buffer and placed into the
47781 * valstack for reachability. The actual buffer is then detached at
47782 * the end.
47783 *
47784 * Note: heap_mark_and_sweep_base_flags are altered here to ensure
47785 * no-one touches this object while we're resizing and rehashing it.
47786 * The flags must be reset on every exit path after it. Finalizers
47787 * and compaction is prevented currently for all objects while it
47788 * would be enough to restrict it only for the current object.
47789 */
47790
47791#ifdef DUK_USE_MARK_AND_SWEEP
47792 prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
47794 DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */
47795 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact the current object */
47796#endif
47797
47798 new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
47799 DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
47800 if (new_alloc_size == 0) {
47801 /* for zero size, don't push anything on valstack */
47802 DUK_ASSERT(new_e_size_adjusted == 0);
47803 DUK_ASSERT(new_a_size == 0);
47804 DUK_ASSERT(new_h_size == 0);
47805 new_p = NULL;
47806 } else {
47807 /* This may trigger mark-and-sweep with arbitrary side effects,
47808 * including an attempted resize of the object we're resizing,
47809 * executing a finalizer which may add or remove properties of
47810 * the object we're resizing etc.
47811 */
47812
47813 /* Note: buffer is dynamic so that we can 'steal' the actual
47814 * allocation later.
47815 */
47816
47817 new_p = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, new_alloc_size); /* errors out if out of memory */
47818 DUK_ASSERT(new_p != NULL); /* since new_alloc_size > 0 */
47819 }
47820
47821 /* Set up pointers to the new property area: this is hidden behind a macro
47822 * because it is memory layout specific.
47823 */
47824 DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
47825 new_e_size_adjusted, new_a_size, new_h_size);
47826 DUK_UNREF(new_h); /* happens when hash part dropped */
47827 new_e_next = 0;
47828
47829 /* if new_p == NULL, all of these pointers are NULL */
47830 DUK_ASSERT((new_p != NULL) ||
47831 (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
47832 new_a == NULL && new_h == NULL));
47833
47834 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",
47835 (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
47836 (void *) new_a, (void *) new_h));
47837
47838 /*
47839 * Migrate array to start of entries if requested.
47840 *
47841 * Note: from an enumeration perspective the order of entry keys matters.
47842 * Array keys should appear wherever they appeared before the array abandon
47843 * operation.
47844 */
47845
47846 if (abandon_array) {
47847 /*
47848 * Note: assuming new_a_size == 0, and that entry part contains
47849 * no conflicting keys, refcounts do not need to be adjusted for
47850 * the values, as they remain exactly the same.
47851 *
47852 * The keys, however, need to be interned, incref'd, and be
47853 * reachable for GC. Any intern attempt may trigger a GC and
47854 * claim any non-reachable strings, so every key must be reachable
47855 * at all times.
47856 *
47857 * A longjmp must not occur here, as the new_p allocation would
47858 * be freed without these keys being decref'd, hence the messy
47859 * decref handling if intern fails.
47860 */
47861 DUK_ASSERT(new_a_size == 0);
47862
47863 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
47864 duk_tval *tv1;
47865 duk_tval *tv2;
47866 duk_hstring *key;
47867
47869
47870 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
47871 if (DUK_TVAL_IS_UNUSED(tv1)) {
47872 continue;
47873 }
47874
47875 DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
47876 new_e_pv != NULL && new_e_f != NULL);
47877
47878 /*
47879 * Intern key via the valstack to ensure reachability behaves
47880 * properly. We must avoid longjmp's here so use non-checked
47881 * primitives.
47882 *
47883 * Note: duk_check_stack() potentially reallocs the valstack,
47884 * invalidating any duk_tval pointers to valstack. Callers
47885 * must be careful.
47886 */
47887
47888 /* never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which is generous */
47889 if (!duk_check_stack(ctx, 1)) {
47890 goto abandon_error;
47891 }
47893 key = duk_heap_string_intern_u32(thr->heap, i);
47894 if (!key) {
47895 goto abandon_error;
47896 }
47897 duk_push_hstring(ctx, key); /* keep key reachable for GC etc; guaranteed not to fail */
47898
47899 /* key is now reachable in the valstack */
47900
47901 DUK_HSTRING_INCREF(thr, key); /* second incref for the entry reference */
47902 new_e_k[new_e_next] = key;
47903 tv2 = &new_e_pv[new_e_next].v; /* array entries are all plain values */
47904 DUK_TVAL_SET_TVAL(tv2, tv1);
47905 new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
47908 new_e_next++;
47909
47910 /* Note: new_e_next matches pushed temp key count, and nothing can
47911 * fail above between the push and this point.
47912 */
47913 }
47914
47915 DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
47916 duk_pop_n(ctx, new_e_next);
47917 }
47918
47919 /*
47920 * Copy keys and values in the entry part (compacting them at the same time).
47921 */
47922
47923 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
47924 duk_hstring *key;
47925
47927
47928 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
47929 if (!key) {
47930 continue;
47931 }
47932
47933 DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
47934 new_e_pv != NULL && new_e_f != NULL);
47935
47936 new_e_k[new_e_next] = key;
47937 new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
47938 new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
47939 new_e_next++;
47940 }
47941 /* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
47942
47943 /*
47944 * Copy array elements to new array part.
47945 */
47946
47947 if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
47948 /* copy existing entries as is */
47949 DUK_ASSERT(new_p != NULL && new_a != NULL);
47950 if (DUK_HOBJECT_GET_ASIZE(obj) > 0) {
47951 /* Avoid zero copy with an invalid pointer. If obj->p is NULL,
47952 * the 'new_a' pointer will be invalid which is not allowed even
47953 * when copy size is zero.
47954 */
47957 DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj));
47958 }
47959
47960 /* fill new entries with -unused- (required, gc reachable) */
47961 for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
47962 duk_tval *tv = &new_a[i];
47964 }
47965 } else {
47966#ifdef DUK_USE_ASSERTIONS
47967 /* caller must have decref'd values above new_a_size (if that is necessary) */
47968 if (!abandon_array) {
47969 for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
47970 duk_tval *tv;
47971 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
47972
47973 /* current assertion is quite strong: decref's and set to unused */
47975 }
47976 }
47977#endif
47978 if (new_a_size > 0) {
47979 /* Avoid zero copy with an invalid pointer. If obj->p is NULL,
47980 * the 'new_a' pointer will be invalid which is not allowed even
47981 * when copy size is zero.
47982 */
47984 DUK_ASSERT(new_a_size > 0);
47985 DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * new_a_size);
47986 }
47987 }
47988
47989 /*
47990 * Rebuild the hash part always from scratch (guaranteed to finish).
47991 *
47992 * Any resize of hash part requires rehashing. In addition, by rehashing
47993 * get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
47994 * to ensuring the hash part never fills up.
47995 */
47996
47997#if defined(DUK_USE_HOBJECT_HASH_PART)
47998 if (DUK_UNLIKELY(new_h_size > 0)) {
47999 DUK_ASSERT(new_h != NULL);
48000
48001 /* fill new_h with u32 0xff = UNUSED */
48003 DUK_ASSERT(new_h_size > 0);
48004 DUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
48005
48006 DUK_ASSERT(new_e_next <= new_h_size); /* equality not actually possible */
48007 for (i = 0; i < new_e_next; i++) {
48008 duk_hstring *key = new_e_k[i];
48009 duk_uint32_t j, step;
48010
48011 DUK_ASSERT(key != NULL);
48012 j = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size);
48014
48015 for (;;) {
48016 DUK_ASSERT(new_h[j] != DUK__HASH_DELETED); /* should never happen */
48017 if (new_h[j] == DUK__HASH_UNUSED) {
48018 DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
48019 new_h[j] = i;
48020 break;
48021 }
48022 DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
48023 j = (j + step) % new_h_size;
48024
48025 /* guaranteed to finish */
48026 DUK_ASSERT(j != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size));
48027 }
48028 }
48029 } else {
48030 DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
48031 }
48032#endif /* DUK_USE_HOBJECT_HASH_PART */
48033
48034 /*
48035 * Nice debug log.
48036 */
48037
48038 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 "
48039 "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
48040 (void *) obj,
48044 (long) new_alloc_size,
48045 (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
48046 (long) DUK_HOBJECT_GET_ESIZE(obj),
48047 (long) DUK_HOBJECT_GET_ENEXT(obj),
48048 (long) DUK_HOBJECT_GET_ASIZE(obj),
48049 (long) DUK_HOBJECT_GET_HSIZE(obj),
48050 (void *) new_p,
48051 (long) new_e_size_adjusted,
48052 (long) new_e_next,
48053 (long) new_a_size,
48054 (long) new_h_size,
48055 (long) abandon_array,
48056 (long) new_e_size));
48057
48058 /*
48059 * All done, switch properties ('p') allocation to new one.
48060 */
48061
48062 DUK_FREE(thr->heap, DUK_HOBJECT_GET_PROPS(thr->heap, obj)); /* NULL obj->p is OK */
48063 DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
48064 DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
48065 DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
48066 DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
48067 DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
48068
48069 if (new_p) {
48070 /*
48071 * Detach actual buffer from dynamic buffer in valstack, and
48072 * pop it from the stack.
48073 *
48074 * XXX: the buffer object is certainly not reachable at this point,
48075 * so it would be nice to free it forcibly even with only
48076 * mark-and-sweep enabled. Not a big issue though.
48077 */
48078 (void) duk_steal_buffer(ctx, -1, NULL);
48079 duk_pop(ctx);
48080 } else {
48081 DUK_ASSERT(new_alloc_size == 0);
48082 /* no need to pop, nothing was pushed */
48083 }
48084
48085 /* clear array part flag only after switching */
48086 if (abandon_array) {
48088 }
48089
48090 DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
48091
48092#ifdef DUK_USE_MARK_AND_SWEEP
48093 thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
48094#endif
48095
48096 /*
48097 * Post resize assertions.
48098 */
48099
48100#ifdef DUK_USE_ASSERTIONS
48101 /* XXX: post-checks (such as no duplicate keys) */
48102#endif
48103 return;
48104
48105 /*
48106 * Abandon array failed, need to decref keys already inserted
48107 * into the beginning of new_e_k before unwinding valstack.
48108 */
48109
48110 abandon_error:
48111 DUK_D(DUK_DPRINT("hobject resize failed during abandon array, decref keys"));
48112 i = new_e_next;
48113 while (i > 0) {
48114 i--;
48115 DUK_ASSERT(new_e_k != NULL);
48116 DUK_ASSERT(new_e_k[i] != NULL);
48117 DUK_HSTRING_DECREF(thr, new_e_k[i]); /* side effects */
48118 }
48119
48120#ifdef DUK_USE_MARK_AND_SWEEP
48121 thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
48122#endif
48123
48125}
48126
48127/*
48128 * Helpers to resize properties allocation on specific needs.
48129 */
48130
48131/* Grow entry part allocation for one additional entry. */
48133 duk_uint32_t old_e_used; /* actually used, non-NULL entries */
48134 duk_uint32_t new_e_size;
48135 duk_uint32_t new_a_size;
48136 duk_uint32_t new_h_size;
48137
48138 DUK_ASSERT(thr != NULL);
48139 DUK_ASSERT(obj != NULL);
48140
48141 /* Duktape 0.11.0 and prior tried to optimize the resize by not
48142 * counting the number of actually used keys prior to the resize.
48143 * This worked mostly well but also caused weird leak-like behavior
48144 * as in: test-bug-object-prop-alloc-unbounded.js. So, now we count
48145 * the keys explicitly to compute the new entry part size.
48146 */
48147
48148 old_e_used = duk__count_used_e_keys(thr, obj);
48149 new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
48150#if defined(DUK_USE_HOBJECT_HASH_PART)
48151 new_h_size = duk__get_default_h_size(new_e_size);
48152#else
48153 new_h_size = 0;
48154#endif
48155 new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
48156 DUK_ASSERT(new_e_size >= old_e_used + 1); /* duk__get_min_grow_e() is always >= 1 */
48157
48158 duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
48159}
48160
48161/* Grow array part for a new highest array index. */
48162DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
48163 duk_uint32_t new_e_size;
48164 duk_uint32_t new_a_size;
48165 duk_uint32_t new_h_size;
48166
48167 DUK_ASSERT(thr != NULL);
48168 DUK_ASSERT(obj != NULL);
48169 DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
48170
48171 /* minimum new length is highest_arr_idx + 1 */
48172
48173 new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
48174 new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
48175 new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
48176 DUK_ASSERT(new_a_size >= highest_arr_idx + 1); /* duk__get_min_grow_a() is always >= 1 */
48177
48178 duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
48179}
48180
48181/* Abandon array part, moving array entries into entries part.
48182 * This requires a props resize, which is a heavy operation.
48183 * We also compact the entries part while we're at it, although
48184 * this is not strictly required.
48185 */
48187 duk_uint32_t new_e_size;
48188 duk_uint32_t new_a_size;
48189 duk_uint32_t new_h_size;
48190 duk_uint32_t e_used; /* actually used, non-NULL keys */
48191 duk_uint32_t a_used;
48192 duk_uint32_t a_size;
48193
48194 DUK_ASSERT(thr != NULL);
48195 DUK_ASSERT(obj != NULL);
48196
48197 e_used = duk__count_used_e_keys(thr, obj);
48198 duk__compute_a_stats(thr, obj, &a_used, &a_size);
48199
48200 /*
48201 * Must guarantee all actually used array entries will fit into
48202 * new entry part. Add one growth step to ensure we don't run out
48203 * of space right away.
48204 */
48205
48206 new_e_size = e_used + a_used;
48207 new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
48208 new_a_size = 0;
48209#if defined(DUK_USE_HOBJECT_HASH_PART)
48210 new_h_size = duk__get_default_h_size(new_e_size);
48211#else
48212 new_h_size = 0;
48213#endif
48214
48215 DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
48216 "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
48217 "resize to e_size=%ld, a_size=%ld, h_size=%ld",
48218 (void *) obj, (long) e_used, (long) a_used, (long) a_size,
48219 (long) new_e_size, (long) new_a_size, (long) new_h_size));
48220
48221 duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
48222}
48223
48224/*
48225 * Compact an object. Minimizes allocation size for objects which are
48226 * not likely to be extended. This is useful for internal and non-
48227 * extensible objects, but can also be called for non-extensible objects.
48228 * May abandon the array part if it is computed to be too sparse.
48229 *
48230 * This call is relatively expensive, as it needs to scan both the
48231 * entries and the array part.
48232 *
48233 * The call may fail due to allocation error.
48234 */
48235
48237 duk_uint32_t e_size; /* currently used -> new size */
48238 duk_uint32_t a_size; /* currently required */
48239 duk_uint32_t a_used; /* actually used */
48240 duk_uint32_t h_size;
48241 duk_bool_t abandon_array;
48242
48243 DUK_ASSERT(thr != NULL);
48244 DUK_ASSERT(obj != NULL);
48245
48246#if defined(DUK_USE_ROM_OBJECTS)
48248 DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
48249 return;
48250 }
48251#endif
48252
48253 e_size = duk__count_used_e_keys(thr, obj);
48254 duk__compute_a_stats(thr, obj, &a_used, &a_size);
48255
48256 DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
48257 "resized array density would be: %ld/%ld = %lf",
48258 (long) e_size, (long) a_used, (long) a_size,
48259 (long) a_used, (long) a_size,
48260 (double) a_used / (double) a_size));
48261
48262 if (duk__abandon_array_density_check(a_used, a_size)) {
48263 DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
48264 (long) a_used, (long) a_size));
48265 abandon_array = 1;
48266 e_size += a_used;
48267 a_size = 0;
48268 } else {
48269 DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
48270 abandon_array = 0;
48271 }
48272
48273#if defined(DUK_USE_HOBJECT_HASH_PART)
48274 if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
48275 h_size = duk__get_default_h_size(e_size);
48276 } else {
48277 h_size = 0;
48278 }
48279#else
48280 h_size = 0;
48281#endif
48283 DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
48284 (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
48285
48286 duk__realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
48287}
48288
48289/*
48290 * Find an existing key from entry part either by linear scan or by
48291 * using the hash index (if it exists).
48292 *
48293 * Sets entry index (and possibly the hash index) to output variables,
48294 * which allows the caller to update the entry and hash entries in-place.
48295 * If entry is not found, both values are set to -1. If entry is found
48296 * but there is no hash part, h_idx is set to -1.
48297 */
48298
48300 DUK_ASSERT(obj != NULL);
48301 DUK_ASSERT(key != NULL);
48302 DUK_ASSERT(e_idx != NULL);
48303 DUK_ASSERT(h_idx != NULL);
48304 DUK_UNREF(heap);
48305
48306 if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
48307 {
48308 /* Linear scan: more likely because most objects are small.
48309 * This is an important fast path.
48310 *
48311 * XXX: this might be worth inlining for property lookups.
48312 */
48315 duk_hstring **h_keys_base;
48316 DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
48317
48318 h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
48319 n = DUK_HOBJECT_GET_ENEXT(obj);
48320 for (i = 0; i < n; i++) {
48321 if (h_keys_base[i] == key) {
48322 *e_idx = i;
48323 *h_idx = -1;
48324 return;
48325 }
48326 }
48327 }
48328#if defined(DUK_USE_HOBJECT_HASH_PART)
48329 else
48330 {
48331 /* hash lookup */
48332 duk_uint32_t n;
48333 duk_uint32_t i, step;
48334 duk_uint32_t *h_base;
48335
48336 DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
48337
48338 h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
48339 n = DUK_HOBJECT_GET_HSIZE(obj);
48342
48343 for (;;) {
48344 duk_uint32_t t;
48345
48346 DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
48348 t = h_base[i];
48350 (t < DUK_HOBJECT_GET_ESIZE(obj))); /* t >= 0 always true, unsigned */
48351
48352 if (t == DUK__HASH_UNUSED) {
48353 break;
48354 } else if (t == DUK__HASH_DELETED) {
48355 DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
48356 (long) i, (long) t));
48357 } else {
48359 if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
48360 DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
48361 (long) i, (long) t, (void *) key));
48362 *e_idx = t;
48363 *h_idx = i;
48364 return;
48365 }
48366 DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
48367 (long) i, (long) t));
48368 }
48369 i = (i + step) % n;
48370
48371 /* guaranteed to finish, as hash is never full */
48372 DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n));
48373 }
48374 }
48375#endif /* DUK_USE_HOBJECT_HASH_PART */
48376
48377 /* not found */
48378 *e_idx = -1;
48379 *h_idx = -1;
48380}
48381
48382/* For internal use: get non-accessor entry value */
48384 duk_int_t e_idx;
48385 duk_int_t h_idx;
48386
48387 DUK_ASSERT(obj != NULL);
48388 DUK_ASSERT(key != NULL);
48389 DUK_UNREF(heap);
48390
48391 duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
48392 if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
48393 return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
48394 } else {
48395 return NULL;
48396 }
48397}
48398
48399/* For internal use: get non-accessor entry value and attributes */
48401 duk_int_t e_idx;
48402 duk_int_t h_idx;
48404 DUK_ASSERT(obj != NULL);
48405 DUK_ASSERT(key != NULL);
48406 DUK_ASSERT(out_attrs != NULL);
48407 DUK_UNREF(heap);
48408
48409 duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
48410 if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
48411 *out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
48412 return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
48413 } else {
48414 *out_attrs = 0;
48415 return NULL;
48416 }
48417}
48418
48419/* For internal use: get array part value */
48421 duk_tval *tv;
48422
48423 DUK_ASSERT(obj != NULL);
48424 DUK_UNREF(heap);
48425
48426 if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
48427 return NULL;
48429 if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
48430 return NULL;
48431 }
48432 tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
48433 return tv;
48434}
48435
48436/*
48437 * Allocate and initialize a new entry, resizing the properties allocation
48438 * if necessary. Returns entry index (e_idx) or throws an error if alloc fails.
48439 *
48440 * Sets the key of the entry (increasing the key's refcount), and updates
48441 * the hash part if it exists. Caller must set value and flags, and update
48442 * the entry value refcount. A decref for the previous value is not necessary.
48443 */
48444
48446 duk_uint32_t idx;
48447
48448 DUK_ASSERT(thr != NULL);
48449 DUK_ASSERT(obj != NULL);
48450 DUK_ASSERT(key != NULL);
48452
48453#ifdef DUK_USE_ASSERTIONS
48454 /* key must not already exist in entry part */
48455 {
48457 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
48458 DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
48459 }
48460 }
48461#endif
48462
48464 /* only need to guarantee 1 more slot, but allocation growth is in chunks */
48465 DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
48467 }
48469 idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
48470
48471 /* previous value is assumed to be garbage, so don't touch it */
48472 DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
48473 DUK_HSTRING_INCREF(thr, key);
48474
48475#if defined(DUK_USE_HOBJECT_HASH_PART)
48476 if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
48477 duk_uint32_t n;
48478 duk_uint32_t i, step;
48479 duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
48480
48481 n = DUK_HOBJECT_GET_HSIZE(obj);
48484
48485 for (;;) {
48486 duk_uint32_t t = h_base[i];
48487 if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
48488 DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() inserted key into hash part, %ld -> %ld",
48489 (long) i, (long) idx));
48490 DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
48492 DUK_ASSERT_DISABLE(idx >= 0);
48494 h_base[i] = idx;
48495 break;
48496 }
48497 DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() miss %ld", (long) i));
48498 i = (i + step) % n;
48499
48500 /* guaranteed to find an empty slot */
48502 }
48503 }
48504#endif /* DUK_USE_HOBJECT_HASH_PART */
48505
48506 /* Note: we could return the hash index here too, but it's not
48507 * needed right now.
48508 */
48509
48510 DUK_ASSERT_DISABLE(idx >= 0);
48513 return idx;
48514}
48515
48516/*
48517 * Object internal value
48518 *
48519 * Returned value is guaranteed to be reachable / incref'd, caller does not need
48520 * to incref OR decref. No proxies or accessors are invoked, no prototype walk.
48521 */
48522
48524 duk_int_t e_idx;
48526
48527 DUK_ASSERT(heap != NULL);
48528 DUK_ASSERT(obj != NULL);
48529 DUK_ASSERT(tv_out != NULL);
48530
48531 /* always in entry part, no need to look up parents etc */
48532 duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx);
48533 if (e_idx >= 0) {
48534 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
48535 DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
48536 return 1;
48537 }
48538 DUK_TVAL_SET_UNDEFINED(tv_out);
48539 return 0;
48540}
48541
48543 duk_tval tv;
48544
48545 DUK_ASSERT(heap != NULL);
48546 DUK_ASSERT(obj != NULL);
48547
48548 /* This is not strictly necessary, but avoids compiler warnings; e.g.
48549 * gcc won't reliably detect that no uninitialized data is read below.
48550 */
48551 DUK_MEMZERO((void *) &tv, sizeof(duk_tval));
48552
48553 if (duk_hobject_get_internal_value(heap, obj, &tv)) {
48554 duk_hstring *h;
48556 h = DUK_TVAL_GET_STRING(&tv);
48557 return h;
48558 }
48559
48560 return NULL;
48561}
48562
48563/*
48564 * Arguments handling helpers (argument map mainly).
48565 *
48566 * An arguments object has exotic behavior for some numeric indices.
48567 * Accesses may translate to identifier operations which may have
48568 * arbitrary side effects (potentially invalidating any duk_tval
48569 * pointers).
48570 */
48571
48572/* Lookup 'key' from arguments internal 'map', perform a variable lookup
48573 * if mapped, and leave the result on top of stack (and return non-zero).
48574 * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
48575 */
48578 duk_hobject *obj,
48579 duk_hstring *key,
48580 duk_propdesc *temp_desc,
48581 duk_hobject **out_map,
48582 duk_hobject **out_varenv) {
48583 duk_context *ctx = (duk_context *) thr;
48584 duk_hobject *map;
48585 duk_hobject *varenv;
48586 duk_bool_t rc;
48587
48589
48590 DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
48591 "(obj -> %!O, key -> %!O)",
48592 (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
48593 (duk_heaphdr *) obj, (duk_heaphdr *) key));
48594
48596 DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
48597 return 0;
48598 }
48599
48600 map = duk_require_hobject(ctx, -1);
48601 DUK_ASSERT(map != NULL);
48602 duk_pop(ctx); /* map is reachable through obj */
48603
48604 if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
48605 DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
48606 return 0;
48607 }
48608
48609 /* [... varname] */
48610 DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
48611 (duk_tval *) duk_get_tval(ctx, -1)));
48612 DUK_ASSERT(duk_is_string(ctx, -1)); /* guaranteed when building arguments */
48613
48614 /* get varenv for varname (callee's declarative lexical environment) */
48616 DUK_UNREF(rc);
48617 DUK_ASSERT(rc != 0); /* arguments MUST have an initialized lexical environment reference */
48618 varenv = duk_require_hobject(ctx, -1);
48619 DUK_ASSERT(varenv != NULL);
48620 duk_pop(ctx); /* varenv remains reachable through 'obj' */
48621
48622 DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
48623
48624 /* success: leave varname in stack */
48625 *out_map = map;
48626 *out_varenv = varenv;
48627 return 1; /* [... varname] */
48628}
48629
48630/* Lookup 'key' from arguments internal 'map', and leave replacement value
48631 * on stack top if mapped (and return non-zero).
48632 * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
48633 */
48635 duk_context *ctx = (duk_context *) thr;
48636 duk_hobject *map;
48637 duk_hobject *varenv;
48638 duk_hstring *varname;
48639
48641
48642 if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
48643 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
48644 return 0;
48645 }
48646
48647 /* [... varname] */
48648
48649 varname = duk_require_hstring(ctx, -1);
48650 DUK_ASSERT(varname != NULL);
48651 duk_pop(ctx); /* varname is still reachable */
48652
48653 DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
48654 "key=%!O, varname=%!O",
48656 (duk_heaphdr *) varname));
48657
48658 (void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
48659
48660 /* [... value this_binding] */
48661
48662 duk_pop(ctx);
48663
48664 /* leave result on stack top */
48665 return 1;
48666}
48667
48668/* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
48669 * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
48670 * Assumes stack top contains 'put' value (which is NOT popped).
48671 */
48673 duk_context *ctx = (duk_context *) thr;
48674 duk_hobject *map;
48675 duk_hobject *varenv;
48676 duk_hstring *varname;
48677
48679
48680 if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
48681 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
48682 return;
48683 }
48684
48685 /* [... put_value varname] */
48686
48687 varname = duk_require_hstring(ctx, -1);
48688 DUK_ASSERT(varname != NULL);
48689 duk_pop(ctx); /* varname is still reachable */
48690
48691 DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
48692 "key=%!O, varname=%!O, value=%!T",
48693 (duk_heaphdr *) key,
48694 (duk_heaphdr *) varname,
48695 (duk_tval *) duk_require_tval(ctx, -1)));
48696
48697 /* [... put_value] */
48698
48700 * Note: although arguments object variable mappings are only established
48701 * for non-strict functions (and a call to a non-strict function created
48702 * the arguments object in question), an inner strict function may be doing
48703 * the actual property write. Hence the throw_flag applied here comes from
48704 * the property write call.
48705 */
48706
48707 duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, -1), throw_flag);
48708
48709 /* [... put_value] */
48710}
48711
48712/* Lookup 'key' from arguments internal 'map', delete mapping if found.
48713 * Used in E5 Section 10.6 algorithm for [[Delete]]. Note that the
48714 * variable/argument itself (where the map points) is not deleted.
48715 */
48717 duk_context *ctx = (duk_context *) thr;
48718 duk_hobject *map;
48719
48721
48723 DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
48724 return;
48725 }
48726
48727 map = duk_require_hobject(ctx, -1);
48728 DUK_ASSERT(map != NULL);
48729 duk_pop(ctx); /* map is reachable through obj */
48730
48731 DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
48732 (duk_heaphdr *) key));
48733
48734 /* Note: no recursion issue, we can trust 'map' to behave */
48736 DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
48737 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
48738 DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
48739}
48740
48741/*
48742 * Ecmascript compliant [[GetOwnProperty]](P), for internal use only.
48743 *
48744 * If property is found:
48745 * - Fills descriptor fields to 'out_desc'
48746 * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
48747 * property onto the stack ('undefined' for accessor properties).
48748 * - Returns non-zero
48749 *
48750 * If property is not found:
48751 * - 'out_desc' is left in untouched state (possibly garbage)
48752 * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
48753 * set)
48754 * - Returns zero
48755 *
48756 * Notes:
48757 *
48758 * - Getting a property descriptor may cause an allocation (and hence
48759 * GC) to take place, hence reachability and refcount of all related
48760 * values matter. Reallocation of value stack, properties, etc may
48761 * invalidate many duk_tval pointers (concretely, those which reside
48762 * in memory areas subject to reallocation). However, heap object
48763 * pointers are never affected (heap objects have stable pointers).
48764 *
48765 * - The value of a plain property is always reachable and has a non-zero
48766 * reference count.
48767 *
48768 * - The value of a virtual property is not necessarily reachable from
48769 * elsewhere and may have a refcount of zero. Hence we push it onto
48770 * the valstack for the caller, which ensures it remains reachable
48771 * while it is needed.
48772 *
48773 * - There are no virtual accessor properties. Hence, all getters and
48774 * setters are always related to concretely stored properties, which
48775 * ensures that the get/set functions in the resulting descriptor are
48776 * reachable and have non-zero refcounts. Should there be virtual
48777 * accessor properties later, this would need to change.
48778 */
48779
48780DUK_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) {
48781 duk_context *ctx = (duk_context *) thr;
48782 duk_tval *tv;
48783
48784 DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
48785 "arr_idx=%ld (obj -> %!O, key -> %!O)",
48786 (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
48787 (long) flags, (long) arr_idx,
48788 (duk_heaphdr *) obj, (duk_heaphdr *) key));
48789
48790 DUK_ASSERT(ctx != NULL);
48791 DUK_ASSERT(thr != NULL);
48792 DUK_ASSERT(thr->heap != NULL);
48793 DUK_ASSERT(obj != NULL);
48794 DUK_ASSERT(key != NULL);
48795 DUK_ASSERT(out_desc != NULL);
48797
48798 /* XXX: optimize this filling behavior later */
48799 out_desc->flags = 0;
48800 out_desc->get = NULL;
48801 out_desc->set = NULL;
48802 out_desc->e_idx = -1;
48803 out_desc->h_idx = -1;
48804 out_desc->a_idx = -1;
48805
48806 /*
48807 * Array part
48808 */
48809
48810 if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
48811 if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
48812 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
48813 if (!DUK_TVAL_IS_UNUSED(tv)) {
48814 DUK_DDD(DUK_DDDPRINT("-> found in array part"));
48815 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48816 duk_push_tval(ctx, tv);
48817 }
48818 /* implicit attributes */
48819 out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
48822 out_desc->a_idx = arr_idx;
48823 goto prop_found;
48824 }
48825 }
48826 /* assume array part is comprehensive (contains all array indexed elements
48827 * or none of them); hence no need to check the entries part here.
48828 */
48829 DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property (has array part, "
48830 "should be there if present)"));
48831 goto prop_not_found_concrete;
48832 }
48833
48834 /*
48835 * Entries part
48836 */
48837
48838 duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx);
48839 if (out_desc->e_idx >= 0) {
48840 duk_int_t e_idx = out_desc->e_idx;
48841 out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
48842 if (out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR) {
48843 DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
48844 out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
48845 out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
48846 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48847 /* a dummy undefined value is pushed to make valstack
48848 * behavior uniform for caller
48849 */
48850 duk_push_undefined(ctx);
48851 }
48852 } else {
48853 DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
48854 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
48855 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48856 duk_push_tval(ctx, tv);
48857 }
48858 }
48859 goto prop_found;
48860 }
48861
48862 /*
48863 * Not found as a concrete property, check whether a String object
48864 * virtual property matches.
48865 */
48866
48867 prop_not_found_concrete:
48868
48870 DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
48871 (duk_heaphdr *) key, (long) arr_idx));
48872
48873 if (arr_idx != DUK__NO_ARRAY_INDEX) {
48874 duk_hstring *h_val;
48875
48876 DUK_DDD(DUK_DDDPRINT("array index exists"));
48877
48879 DUK_ASSERT(h_val);
48880 if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
48881 DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
48882 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48883 duk_push_hstring(ctx, h_val);
48884 duk_substring(ctx, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
48885 }
48886 out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE | /* E5 Section 15.5.5.2 */
48888
48890 return 1; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
48891 } else {
48892 /* index is above internal string length -> property is fully normal */
48893 DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
48894 }
48895 } else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
48896 duk_hstring *h_val;
48897
48898 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
48899
48901 DUK_ASSERT(h_val != NULL);
48902 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48904 }
48905 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* E5 Section 15.5.5.1 */
48906
48908 return 1; /* cannot be arguments exotic */
48909 }
48910 } else if (DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
48911 duk_hbufferobject *h_bufobj;
48912 duk_uint_t byte_off;
48913 duk_small_uint_t elem_size;
48914
48915 h_bufobj = (duk_hbufferobject *) obj;
48917 DUK_DDD(DUK_DDDPRINT("bufferobject property get for key: %!O, arr_idx: %ld",
48918 (duk_heaphdr *) key, (long) arr_idx));
48919
48920 if (arr_idx != DUK__NO_ARRAY_INDEX) {
48921 DUK_DDD(DUK_DDDPRINT("array index exists"));
48922
48923 /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
48924 * length downshift won't.
48925 */
48926 if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
48927 byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
48928 elem_size = 1 << h_bufobj->shift;
48929 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48930 duk_uint8_t *data;
48931
48932 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
48933 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
48934 duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
48935 } else {
48936 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
48937 duk_push_uint(ctx, 0);
48938 }
48939 }
48940 out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
48943
48945 return 1; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
48946 } else {
48947 /* index is above internal buffer length -> property is fully normal */
48948 DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
48949 }
48950 } else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
48951 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
48952
48953 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48954 /* Length in elements: take into account shift, but
48955 * intentionally don't check the underlying buffer here.
48956 */
48957 duk_push_uint(ctx, h_bufobj->length >> h_bufobj->shift);
48958 }
48959 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48960
48962 return 1; /* cannot be arguments exotic */
48963 } else if (key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
48964 /* If neutered must return 0; length is zeroed during
48965 * neutering.
48966 */
48967 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48968 duk_push_uint(ctx, h_bufobj->length);
48969 }
48970 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48971 return 1; /* cannot be arguments exotic */
48972 } else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
48973 /* If neutered must return 0; offset is zeroed during
48974 * neutering.
48975 */
48976 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48977 duk_push_uint(ctx, h_bufobj->offset);
48978 }
48979 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48980 return 1; /* cannot be arguments exotic */
48981 } else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
48982 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48983 duk_push_uint(ctx, 1 << h_bufobj->shift);
48984 }
48985 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
48986 return 1; /* cannot be arguments exotic */
48987 }
48988 } else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(obj)) {
48989 DUK_DDD(DUK_DDDPRINT("duktape/c object exotic property get for key: %!O, arr_idx: %ld",
48990 (duk_heaphdr *) key, (long) arr_idx));
48991
48992 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
48993 DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
48994
48995 if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48996 duk_int16_t func_nargs = ((duk_hnativefunction *) obj)->nargs;
48997 duk_push_int(ctx, func_nargs == DUK_HNATIVEFUNCTION_NARGS_VARARGS ? 0 : func_nargs);
48998 }
48999 out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* not enumerable */
49000
49002 return 1; /* cannot be arguments exotic */
49003 }
49004 }
49005
49006 /* Array properties have exotic behavior but they are concrete,
49007 * so no special handling here.
49008 *
49009 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
49010 * is only relevant as a post-check implemented below; hence no
49011 * check here.
49012 */
49013
49014 /*
49015 * Not found as concrete or virtual
49016 */
49017
49018 DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
49019 return 0;
49020
49021 /*
49022 * Found
49023 *
49024 * Arguments object has exotic post-processing, see E5 Section 10.6,
49025 * description of [[GetOwnProperty]] variant for arguments.
49026 */
49027
49028 prop_found:
49029 DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
49030
49031 /* Notes:
49032 * - only numbered indices are relevant, so arr_idx fast reject is good
49033 * (this is valid unless there are more than 4**32-1 arguments).
49034 * - since variable lookup has no side effects, this can be skipped if
49035 * DUK_GETDESC_FLAG_PUSH_VALUE is not set.
49036 */
49037
49039 arr_idx != DUK__NO_ARRAY_INDEX &&
49040 (flags & DUK_GETDESC_FLAG_PUSH_VALUE)) {
49041 duk_propdesc temp_desc;
49042
49043 /* Magically bound variable cannot be an accessor. However,
49044 * there may be an accessor property (or a plain property) in
49045 * place with magic behavior removed. This happens e.g. when
49046 * a magic property is redefined with defineProperty().
49047 * Cannot assert for "not accessor" here.
49049
49050 /* replaces top of stack with new value if necessary */
49052
49053 if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
49054 DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
49055 (duk_tval *) duk_get_tval(ctx, -2),
49056 (duk_tval *) duk_get_tval(ctx, -1)));
49057 /* [... old_result result] -> [... result] */
49058 duk_remove(ctx, -2);
49059 }
49060 }
49061
49062 return 1;
49063}
49064
49066 DUK_ASSERT(thr != NULL);
49067 DUK_ASSERT(obj != NULL);
49068 DUK_ASSERT(key != NULL);
49069 DUK_ASSERT(out_desc != NULL);
49071
49072 return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
49073}
49074
49075/*
49076 * Ecmascript compliant [[GetProperty]](P), for internal use only.
49078 * If property is found:
49079 * - Fills descriptor fields to 'out_desc'
49080 * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
49081 * property onto the stack ('undefined' for accessor properties).
49082 * - Returns non-zero
49083 *
49084 * If property is not found:
49085 * - 'out_desc' is left in untouched state (possibly garbage)
49086 * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
49087 * set)
49088 * - Returns zero
49089 *
49090 * May cause arbitrary side effects and invalidate (most) duk_tval
49091 * pointers.
49092 */
49093
49095 duk_hobject *curr;
49096 duk_uint32_t arr_idx;
49097 duk_uint_t sanity;
49098
49099 DUK_ASSERT(thr != NULL);
49100 DUK_ASSERT(thr->heap != NULL);
49101 DUK_ASSERT(obj != NULL);
49102 DUK_ASSERT(key != NULL);
49103 DUK_ASSERT(out_desc != NULL);
49105
49106 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
49107
49108 DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
49109 "arr_idx=%ld (obj -> %!O, key -> %!O)",
49110 (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
49111 (long) flags, (long) arr_idx,
49112 (duk_heaphdr *) obj, (duk_heaphdr *) key));
49113
49114 curr = obj;
49115 DUK_ASSERT(curr != NULL);
49117 do {
49118 if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
49119 /* stack contains value (if requested), 'out_desc' is set */
49120 return 1;
49121 }
49122
49123 /* not found in 'curr', next in prototype chain; impose max depth */
49124 if (sanity-- == 0) {
49126 /* treat like property not found */
49127 break;
49128 } else {
49130 }
49131 }
49132 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
49133 } while (curr);
49134
49135 /* out_desc is left untouched (possibly garbage), caller must use return
49136 * value to determine whether out_desc can be looked up
49137 */
49138
49139 return 0;
49140}
49141
49142/*
49143 * Shallow fast path checks for accessing array elements with numeric
49144 * indices. The goal is to try to avoid coercing an array index to an
49145 * (interned) string for the most common lookups, in particular, for
49146 * standard Array objects.
49147 *
49148 * Interning is avoided but only for a very narrow set of cases:
49149 * - Object has array part, index is within array allocation, and
49150 * value is not unused (= key exists)
49151 * - Object has no interfering exotic behavior (e.g. arguments or
49152 * string object exotic behaviors interfere, array exotic
49153 * behavior does not).
49154 *
49155 * Current shortcoming: if key does not exist (even if it is within
49156 * the array allocation range) a slow path lookup with interning is
49157 * always required. This can probably be fixed so that there is a
49158 * quick fast path for non-existent elements as well, at least for
49159 * standard Array objects.
49160 */
49161
49163 duk_tval *tv;
49164 duk_uint32_t idx;
49165
49166 DUK_UNREF(thr);
49167
49168 if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
49173 /* Must have array part and no conflicting exotic behaviors.
49174 * Doesn't need to have array special behavior, e.g. Arguments
49175 * object has array part.
49176 */
49177 return NULL;
49178 }
49179
49180 /* Arrays never have other exotic behaviors. */
49181
49182 DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
49183 "behavior, object has array part)"));
49184
49185#if defined(DUK_USE_FASTINT)
49186 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49187 idx = duk__tval_fastint_to_arr_idx(tv_key);
49188 } else
49189#endif
49190 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49191 idx = duk__tval_number_to_arr_idx(tv_key);
49192 } else {
49193 DUK_DDD(DUK_DDDPRINT("key is not a number"));
49194 return NULL;
49195 }
49196
49197 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49198 * is 0xffffffffUL. We don't need to check for that explicitly
49199 * because 0xffffffffUL will never be inside object 'a_size'.
49200 */
49201
49202 if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
49203 DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
49204 return NULL;
49205 }
49206 DUK_ASSERT(idx != 0xffffffffUL);
49208
49209 /* XXX: for array instances we could take a shortcut here and assume
49210 * Array.prototype doesn't contain an array index property.
49211 */
49212
49213 DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
49214 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
49215 if (!DUK_TVAL_IS_UNUSED(tv)) {
49216 DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
49217 return tv;
49218 }
49219
49220 DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
49221 return NULL;
49222}
49223
49225 duk_tval *tv;
49226 duk_uint32_t idx;
49227 duk_uint32_t old_len, new_len;
49228
49229 if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
49232 return 0;
49233 }
49234 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures */
49235
49236#if defined(DUK_USE_FASTINT)
49237 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49238 idx = duk__tval_fastint_to_arr_idx(tv_key);
49239 } else
49240#endif
49241 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49242 idx = duk__tval_number_to_arr_idx(tv_key);
49243 } else {
49244 DUK_DDD(DUK_DDDPRINT("key is not a number"));
49245 return 0;
49246 }
49247
49248 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49249 * is 0xffffffffUL. We don't need to check for that explicitly
49250 * because 0xffffffffUL will never be inside object 'a_size'.
49251 */
49252
49253 if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { /* for resizing of array part, use slow path */
49254 return 0;
49255 }
49256 DUK_ASSERT(idx != 0xffffffffUL);
49258
49259 old_len = duk__get_old_array_length(thr, obj, temp_desc);
49260
49261 if (idx >= old_len) {
49262 DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
49263 "(arr_idx=%ld, old_len=%ld)",
49264 (long) idx, (long) old_len));
49265 if (!(temp_desc->flags & DUK_PROPDESC_FLAG_WRITABLE)) {
49267 return 0; /* not reachable */
49268 }
49269 new_len = idx + 1;
49270
49271 /* No resize has occurred so temp_desc->e_idx is still OK */
49272 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
49274 DUK_TVAL_SET_FASTINT_U32(tv, new_len); /* no need for decref/incref because value is a number */
49275 } else {
49276 ;
49277 }
49278
49279 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
49280 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
49281
49282 DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
49283 return 1;
49284}
49285
49286/*
49287 * Fast path for bufferobject getprop/putprop
49288 */
49289
49291 duk_context *ctx;
49292 duk_uint32_t idx;
49293 duk_hbufferobject *h_bufobj;
49294 duk_uint_t byte_off;
49295 duk_small_uint_t elem_size;
49296 duk_uint8_t *data;
49297
49298 ctx = (duk_context *) thr;
49299
49300 if (!DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
49301 return 0;
49302 }
49303 h_bufobj = (duk_hbufferobject *) obj;
49304
49305#if defined(DUK_USE_FASTINT)
49306 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49307 idx = duk__tval_fastint_to_arr_idx(tv_key);
49308 } else
49309#endif
49310 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49311 idx = duk__tval_number_to_arr_idx(tv_key);
49312 } else {
49313 return 0;
49314 }
49315
49316 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49317 * is 0xffffffffUL. We don't need to check for that explicitly
49318 * because 0xffffffffUL will never be inside bufferobject length.
49319 */
49320
49321 /* Careful with wrapping (left shifting idx would be unsafe). */
49322 if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
49323 return 0;
49326
49327 byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
49328 elem_size = 1 << h_bufobj->shift;
49329
49330 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
49331 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
49332 duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
49333 } else {
49334 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
49335 duk_push_uint(ctx, 0);
49336 }
49337
49338 return 1;
49339}
49340
49342 duk_context *ctx;
49343 duk_uint32_t idx;
49344 duk_hbufferobject *h_bufobj;
49345 duk_uint_t byte_off;
49346 duk_small_uint_t elem_size;
49347 duk_uint8_t *data;
49348
49349 ctx = (duk_context *) thr;
49350
49351 if (!(DUK_HOBJECT_IS_BUFFEROBJECT(obj) &&
49352 DUK_TVAL_IS_NUMBER(tv_val))) {
49353 return 0;
49354 }
49355 DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures; rom objects are never bufferobjects now */
49356
49357 h_bufobj = (duk_hbufferobject *) obj;
49358#if defined(DUK_USE_FASTINT)
49359 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49360 idx = duk__tval_fastint_to_arr_idx(tv_key);
49361 } else
49362#endif
49363 if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49364 idx = duk__tval_number_to_arr_idx(tv_key);
49365 } else {
49366 return 0;
49367 }
49368
49369 /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49370 * is 0xffffffffUL. We don't need to check for that explicitly
49371 * because 0xffffffffUL will never be inside bufferobject length.
49372 */
49373
49374 /* Careful with wrapping (left shifting idx would be unsafe). */
49375 if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
49376 return 0;
49377 }
49379
49380 byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
49381 elem_size = 1 << h_bufobj->shift;
49382
49383 /* Value is required to be a number in the fast path so there
49384 * are no side effects in write coercion.
49385 */
49386 duk_push_tval(ctx, tv_val);
49388
49389 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
49390 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
49391 duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
49392 } else {
49393 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
49394 }
49395
49396 duk_pop(ctx);
49397 return 1;
49398}
49399
49400/*
49401 * GETPROP: Ecmascript property read.
49402 */
49403
49405 duk_context *ctx = (duk_context *) thr;
49406 duk_tval tv_obj_copy;
49407 duk_tval tv_key_copy;
49408 duk_hobject *curr = NULL;
49409 duk_hstring *key = NULL;
49410 duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
49411 duk_propdesc desc;
49412 duk_uint_t sanity;
49413
49414 DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
49415 (void *) thr, (void *) tv_obj, (void *) tv_key,
49416 (duk_tval *) tv_obj, (duk_tval *) tv_key));
49417
49418 DUK_ASSERT(ctx != NULL);
49419 DUK_ASSERT(thr != NULL);
49420 DUK_ASSERT(thr->heap != NULL);
49421 DUK_ASSERT(tv_obj != NULL);
49422 DUK_ASSERT(tv_key != NULL);
49423
49425
49426 /*
49427 * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
49428 * them being invalidated by a valstack resize.
49429 *
49430 * XXX: this is now an overkill for many fast paths. Rework this
49431 * to be faster (although switching to a valstack discipline might
49432 * be a better solution overall).
49433 */
49434
49435 DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
49436 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
49437 tv_obj = &tv_obj_copy;
49438 tv_key = &tv_key_copy;
49439
49440 /*
49441 * Coercion and fast path processing
49442 */
49443
49444 switch (DUK_TVAL_GET_TAG(tv_obj)) {
49445 case DUK_TAG_UNDEFINED:
49446 case DUK_TAG_NULL: {
49447 /* Note: unconditional throw */
49448 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
49449#if defined(DUK_USE_PARANOID_ERRORS)
49451#else
49452 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
49454#endif
49455 return 0;
49456 }
49457
49458 case DUK_TAG_BOOLEAN: {
49459 DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
49460 curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
49461 break;
49462 }
49463
49464 case DUK_TAG_STRING: {
49465 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
49466 duk_int_t pop_count;
49467
49468#if defined(DUK_USE_FASTINT)
49469 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49470 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
49471 DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
49472 pop_count = 0;
49473 } else
49474#endif
49475 if (DUK_TVAL_IS_NUMBER(tv_key)) {
49476 arr_idx = duk__tval_number_to_arr_idx(tv_key);
49477 DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
49478 pop_count = 0;
49479 } else {
49480 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49481 DUK_ASSERT(key != NULL);
49482 DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
49483 "coercion key is %!T, arr_idx %ld",
49484 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49485 pop_count = 1;
49486 }
49487
49488 if (arr_idx != DUK__NO_ARRAY_INDEX &&
49489 arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
49490 duk_pop_n(ctx, pop_count);
49491 duk_push_hstring(ctx, h);
49492 duk_substring(ctx, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
49493
49494 DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
49495 "after coercion -> return char)",
49496 (duk_tval *) duk_get_tval(ctx, -1)));
49497 return 1;
49498 }
49499
49500 if (pop_count == 0) {
49501 /* This is a pretty awkward control flow, but we need to recheck the
49502 * key coercion here.
49503 */
49504 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49505 DUK_ASSERT(key != NULL);
49506 DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
49507 "coercion key is %!T, arr_idx %ld",
49508 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49509 }
49510
49511 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49512 duk_pop(ctx); /* [key] -> [] */
49513 duk_push_uint(ctx, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h)); /* [] -> [res] */
49514
49515 DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
49516 "return string length)",
49517 (duk_tval *) duk_get_tval(ctx, -1)));
49518 return 1;
49519 }
49520 DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
49521 curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
49522 goto lookup; /* avoid double coercion */
49523 }
49524
49525 case DUK_TAG_OBJECT: {
49526 duk_tval *tmp;
49527
49528 curr = DUK_TVAL_GET_OBJECT(tv_obj);
49529 DUK_ASSERT(curr != NULL);
49530
49531 tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
49532 if (tmp) {
49533 duk_push_tval(ctx, tmp);
49534
49535 DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
49536 "fast path)",
49537 (duk_tval *) duk_get_tval(ctx, -1)));
49538 return 1;
49539 }
49540
49541 if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
49542 /* Read value pushed on stack. */
49543 DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufferobject "
49544 "fast path)",
49545 (duk_tval *) duk_get_tval(ctx, -1)));
49546 return 1;
49547 }
49548
49549#if defined(DUK_USE_ES6_PROXY)
49551 duk_hobject *h_target;
49552
49553 if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
49554 /* -> [ ... trap handler ] */
49555 DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
49556 duk_push_hobject(ctx, h_target); /* target */
49557 duk_push_tval(ctx, tv_key); /* P */
49558 duk_push_tval(ctx, tv_obj); /* Receiver: Proxy object */
49559 duk_call_method(ctx, 3 /*nargs*/);
49560
49561 /* Target object must be checked for a conflicting
49562 * non-configurable property.
49563 */
49564 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49565 DUK_ASSERT(key != NULL);
49566
49567 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
49568 duk_tval *tv_hook = duk_require_tval(ctx, -3); /* value from hook */
49569 duk_tval *tv_targ = duk_require_tval(ctx, -1); /* value from target */
49570 duk_bool_t datadesc_reject;
49571 duk_bool_t accdesc_reject;
49572
49573 DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
49574 "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
49575 "desc.get=%p, desc.set=%p",
49576 (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
49577 (unsigned long) desc.flags,
49578 (void *) desc.get, (void *) desc.set));
49579
49580 datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
49583 !duk_js_samevalue(tv_hook, tv_targ);
49584 accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
49586 (desc.get == NULL) &&
49587 !DUK_TVAL_IS_UNDEFINED(tv_hook);
49588 if (datadesc_reject || accdesc_reject) {
49590 }
49591
49592 duk_pop_2(ctx);
49593 } else {
49594 duk_pop(ctx);
49595 }
49596 return 1; /* return value */
49597 }
49598
49599 curr = h_target; /* resume lookup from target */
49600 DUK_TVAL_SET_OBJECT(tv_obj, curr);
49601 }
49602#endif /* DUK_USE_ES6_PROXY */
49603
49605 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49606 DUK_ASSERT(key != NULL);
49607
49608 if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
49609 DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
49610 "key matches magically bound property -> skip standard "
49611 "Get with replacement value)",
49612 (duk_tval *) duk_get_tval(ctx, -1)));
49613
49614 /* no need for 'caller' post-check, because 'key' must be an array index */
49615
49616 duk_remove(ctx, -2); /* [key result] -> [result] */
49617 return 1;
49618 }
49619
49620 goto lookup; /* avoid double coercion */
49621 }
49622 break;
49623 }
49624
49625 /* Buffer has virtual properties similar to string, but indexed values
49626 * are numbers, not 1-byte buffers/strings which would perform badly.
49627 */
49628 case DUK_TAG_BUFFER: {
49629 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
49630 duk_int_t pop_count;
49631
49632 /*
49633 * Because buffer values are often looped over, a number fast path
49634 * is important.
49635 */
49636
49637#if defined(DUK_USE_FASTINT)
49638 if (DUK_TVAL_IS_FASTINT(tv_key)) {
49639 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
49640 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
49641 pop_count = 0;
49642 }
49643 else
49644#endif
49645 if (DUK_TVAL_IS_NUMBER(tv_key)) {
49646 arr_idx = duk__tval_number_to_arr_idx(tv_key);
49647 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
49648 pop_count = 0;
49649 } else {
49650 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49651 DUK_ASSERT(key != NULL);
49652 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
49653 "coercion key is %!T, arr_idx %ld",
49654 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49655 pop_count = 1;
49656 }
49657
49658 if (arr_idx != DUK__NO_ARRAY_INDEX &&
49659 arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
49660 duk_pop_n(ctx, pop_count);
49661 duk_push_uint(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
49662
49663 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
49664 "after coercion -> return byte as number)",
49665 (duk_tval *) duk_get_tval(ctx, -1)));
49666 return 1;
49667 }
49668
49669 if (pop_count == 0) {
49670 /* This is a pretty awkward control flow, but we need to recheck the
49671 * key coercion here.
49672 */
49673 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49674 DUK_ASSERT(key != NULL);
49675 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
49676 "coercion key is %!T, arr_idx %ld",
49677 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49678 }
49679
49680 if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
49681 key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
49682 duk_pop(ctx); /* [key] -> [] */
49683 duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h)); /* [] -> [res] */
49684
49685 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' or 'byteLength' "
49686 "after coercion -> return buffer length)",
49687 (duk_tval *) duk_get_tval(ctx, -1)));
49688 return 1;
49689 } else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
49690 duk_pop(ctx); /* [key] -> [] */
49691 duk_push_uint(ctx, 0); /* [] -> [res] */
49692
49693 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'byteOffset' after coercion -> "
49694 "return 0 for consistency with Buffer objects)",
49695 (duk_tval *) duk_get_tval(ctx, -1)));
49696 return 1;
49697 } else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
49698 duk_pop(ctx); /* [key] -> [] */
49699 duk_push_uint(ctx, 1); /* [] -> [res] */
49700
49701 DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'BYTES_PER_ELEMENT' after coercion -> "
49702 "return 1 for consistency with Buffer objects)",
49703 (duk_tval *) duk_get_tval(ctx, -1)));
49704 return 1;
49705 }
49706
49707 DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from buffer prototype"));
49708 curr = thr->builtins[DUK_BIDX_BUFFER_PROTOTYPE];
49709 goto lookup; /* avoid double coercion */
49710 }
49711
49712 case DUK_TAG_POINTER: {
49713 DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
49714 curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
49715 break;
49716 }
49717
49718 case DUK_TAG_LIGHTFUNC: {
49719 duk_int_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_obj);
49720
49721 /* Must coerce key: if key is an object, it may coerce to e.g. 'length'. */
49722 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49723
49724 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49725 duk_int_t lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
49726 duk_pop(ctx);
49727 duk_push_int(ctx, lf_len);
49728 return 1;
49729 } else if (key == DUK_HTHREAD_STRING_NAME(thr)) {
49730 duk_pop(ctx);
49731 duk_push_lightfunc_name(ctx, tv_obj);
49732 return 1;
49733 }
49734
49735 DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
49736 curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
49737 goto lookup; /* avoid double coercion */
49738 }
49739
49740#if defined(DUK_USE_FASTINT)
49741 case DUK_TAG_FASTINT:
49742#endif
49743 default: {
49744 /* number */
49745 DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
49748 curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
49749 break;
49750 }
49751 }
49752
49753 /* key coercion (unless already coerced above) */
49754 DUK_ASSERT(key == NULL);
49755 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49756 DUK_ASSERT(key != NULL);
49757
49758 /*
49759 * Property lookup
49760 */
49761
49762 lookup:
49763 /* [key] (coerced) */
49764 DUK_ASSERT(curr != NULL);
49765 DUK_ASSERT(key != NULL);
49766
49768 do {
49769 if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
49770 goto next_in_chain;
49771 }
49772
49773 if (desc.get != NULL) {
49774 /* accessor with defined getter */
49776
49777 duk_pop(ctx); /* [key undefined] -> [key] */
49778 duk_push_hobject(ctx, desc.get);
49779 duk_push_tval(ctx, tv_obj); /* note: original, uncoerced base */
49780#ifdef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
49781 duk_dup(ctx, -3);
49782 duk_call_method(ctx, 1); /* [key getter this key] -> [key retval] */
49783#else
49784 duk_call_method(ctx, 0); /* [key getter this] -> [key retval] */
49785#endif
49786 } else {
49787 /* [key value] or [key undefined] */
49788
49789 /* data property or accessor without getter */
49791 (desc.get == NULL));
49792
49793 /* if accessor without getter, return value is undefined */
49795 duk_is_undefined(ctx, -1));
49796
49797 /* Note: for an accessor without getter, falling through to
49798 * check for "caller" exotic behavior is unnecessary as
49799 * "undefined" will never activate the behavior. But it does
49800 * no harm, so we'll do it anyway.
49801 */
49802 }
49803
49804 goto found; /* [key result] */
49805
49806 next_in_chain:
49807 /* XXX: option to pretend property doesn't exist if sanity limit is
49808 * hit might be useful.
49809 */
49810 if (sanity-- == 0) {
49812 }
49813 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
49814 } while (curr);
49815
49816 /*
49817 * Not found
49818 */
49819
49820 duk_to_undefined(ctx, -1); /* [key] -> [undefined] (default value) */
49821
49822 DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(ctx, -1)));
49823 return 0;
49824
49825 /*
49826 * Found; post-processing (Function and arguments objects)
49827 */
49828
49829 found:
49830 /* [key result] */
49831
49832#if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
49833 /* Special behavior for 'caller' property of (non-bound) function objects
49834 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
49835 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
49836 * Quite interestingly, a non-strict function with no formal arguments
49837 * will get an arguments object -without- special 'caller' behavior!
49838 *
49839 * The E5.1 spec is a bit ambiguous if this special behavior applies when
49840 * a bound function is the base value (not the 'caller' value): Section
49841 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
49842 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
49843 * However, Section 13.3.5.4 has "NOTE: Function objects created using
49844 * Function.prototype.bind use the default [[Get]] internal method."
49845 * The current implementation assumes this means that bound functions
49846 * should not have the special [[Get]] behavior.
49847 *
49848 * The E5.1 spec is also a bit unclear if the TypeError throwing is
49849 * applied if the 'caller' value is a strict bound function. The
49850 * current implementation will throw even for both strict non-bound
49851 * and strict bound functions.
49852 *
49853 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
49854 * tests.
49855 *
49856 * This exotic behavior is disabled when the non-standard 'caller' property
49857 * is enabled, as it conflicts with the free use of 'caller'.
49858 */
49859 if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
49860 DUK_TVAL_IS_OBJECT(tv_obj)) {
49861 duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
49862 DUK_ASSERT(orig != NULL);
49863
49866 duk_hobject *h;
49867
49868 /* XXX: The TypeError is currently not applied to bound
49869 * functions because the 'strict' flag is not copied by
49870 * bind(). This may or may not be correct, the specification
49871 * only refers to the value being a "strict mode Function
49872 * object" which is ambiguous.
49873 */
49875
49876 h = duk_get_hobject(ctx, -1); /* NULL if not an object */
49877 if (h &&
49880 /* XXX: sufficient to check 'strict', assert for 'is function' */
49882 }
49884 }
49885#endif /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
49886
49887 duk_remove(ctx, -2); /* [key result] -> [result] */
49888
49889 DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(ctx, -1)));
49890 return 1;
49891}
49892
49893/*
49894 * HASPROP: Ecmascript property existence check ("in" operator).
49895 *
49896 * Interestingly, the 'in' operator does not do any coercion of
49897 * the target object.
49898 */
49899
49901 duk_context *ctx = (duk_context *) thr;
49902 duk_tval tv_key_copy;
49903 duk_hobject *obj;
49904 duk_hstring *key;
49905 duk_uint32_t arr_idx;
49906 duk_bool_t rc;
49907 duk_propdesc desc;
49908
49909 DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
49910 (void *) thr, (void *) tv_obj, (void *) tv_key,
49911 (duk_tval *) tv_obj, (duk_tval *) tv_key));
49912
49913 DUK_ASSERT(thr != NULL);
49914 DUK_ASSERT(thr->heap != NULL);
49915 DUK_ASSERT(tv_obj != NULL);
49916 DUK_ASSERT(tv_key != NULL);
49918
49919 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
49920 tv_key = &tv_key_copy;
49921
49922 /*
49923 * The 'in' operator requires an object as its right hand side,
49924 * throwing a TypeError unconditionally if this is not the case.
49925 *
49926 * However, lightfuncs need to behave like fully fledged objects
49927 * here to be maximally transparent, so we need to handle them
49928 * here.
49929 */
49930
49931 /* XXX: Refactor key coercion so that it's only called once. It can't
49932 * be trivially lifted here because the object must be type checked
49933 * first.
49934 */
49935
49936 if (DUK_TVAL_IS_OBJECT(tv_obj)) {
49937 obj = DUK_TVAL_GET_OBJECT(tv_obj);
49938 DUK_ASSERT(obj != NULL);
49939
49940 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49941 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
49942 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49943 if (duk__key_is_lightfunc_ownprop(thr, key)) {
49944 /* FOUND */
49945 rc = 1;
49946 goto pop_and_return;
49947 }
49948
49949 /* If not found, resume existence check from Function.prototype.
49950 * We can just substitute the value in this case; nothing will
49951 * need the original base value (as would be the case with e.g.
49952 * setters/getters.
49953 */
49954 obj = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
49955 } else {
49956 /* Note: unconditional throw */
49957 DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
49959 }
49960
49961 /* XXX: fast path for arrays? */
49962
49963 DUK_ASSERT(key != NULL);
49964 DUK_ASSERT(obj != NULL);
49965 DUK_UNREF(arr_idx);
49966
49967#if defined(DUK_USE_ES6_PROXY)
49969 duk_hobject *h_target;
49970 duk_bool_t tmp_bool;
49971
49972 /* XXX: the key in 'key in obj' is string coerced before we're called
49973 * (which is the required behavior in E5/E5.1/E6) so the key is a string
49974 * here already.
49975 */
49976
49977 if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
49978 /* [ ... key trap handler ] */
49979 DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
49980 duk_push_hobject(ctx, h_target); /* target */
49981 duk_push_tval(ctx, tv_key); /* P */
49982 duk_call_method(ctx, 2 /*nargs*/);
49983 tmp_bool = duk_to_boolean(ctx, -1);
49984 if (!tmp_bool) {
49985 /* Target object must be checked for a conflicting
49986 * non-configurable property.
49987 */
49988
49989 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
49990 DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
49991 "conflicting property; desc.flags=0x%08lx, "
49992 "desc.get=%p, desc.set=%p",
49993 (duk_heaphdr *) key, (unsigned long) desc.flags,
49994 (void *) desc.get, (void *) desc.set));
49995 /* XXX: Extensibility check for target uses IsExtensible(). If we
49996 * implemented the isExtensible trap and didn't reject proxies as
49997 * proxy targets, it should be respected here.
49998 */
49999 if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && /* property is configurable and */
50000 DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) { /* ... target is extensible */
50002 }
50003 }
50004 }
50005
50006 duk_pop_2(ctx); /* [ key trap_result ] -> [] */
50007 return tmp_bool;
50008 }
50009
50010 obj = h_target; /* resume check from proxy target */
50011 }
50012#endif /* DUK_USE_ES6_PROXY */
50013
50014 /* XXX: inline into a prototype walking loop? */
50015
50016 rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/); /* don't push value */
50017 /* fall through */
50018
50019 pop_and_return:
50020 duk_pop(ctx); /* [ key ] -> [] */
50021 return rc;
50022}
50023
50024/*
50025 * HASPROP variant used internally.
50026 *
50027 * This primitive must never throw an error, callers rely on this.
50028 * In particular, don't throw an error for prototype loops; instead,
50029 * pretend like the property doesn't exist if a prototype sanity limit
50030 * is reached.
50031 *
50032 * Does not implement proxy behavior: if applied to a proxy object,
50033 * returns key existence on the proxy object itself.
50034 */
50035
50038
50039 DUK_ASSERT(thr != NULL);
50041 DUK_ASSERT(obj != NULL);
50042 DUK_ASSERT(key != NULL);
50043
50045
50046 return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP); /* don't push value */
50047}
50048
50049/*
50050 * Helper: handle Array object 'length' write which automatically
50051 * deletes properties, see E5 Section 15.4.5.1, step 3. This is
50052 * quite tricky to get right.
50053 *
50054 * Used by duk_hobject_putprop().
50055 */
50056
50057DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc) {
50058 duk_bool_t rc;
50059 duk_tval *tv;
50060 duk_uint32_t res;
50061
50063
50064 /* This function is only called for objects with array exotic behavior.
50065 * The [[DefineOwnProperty]] algorithm for arrays requires that
50066 * 'length' can never have a value outside the unsigned 32-bit range,
50067 * attempt to write such a value is a RangeError. Here we can thus
50068 * assert for this. When Duktape internals go around the official
50069 * property write interface (doesn't happen often) this assumption is
50070 * easy to accidentally break, so such code must be written carefully.
50071 * See test-bi-array-push-maxlen.js.
50072 */
50073
50074 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 */
50075 DUK_UNREF(rc);
50076 DUK_ASSERT(rc != 0); /* arrays MUST have a 'length' property */
50077 DUK_ASSERT(temp_desc->e_idx >= 0);
50078
50079 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
50080 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* array 'length' is always a number, as we coerce it */
50081 DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) >= 0.0);
50082 DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (double) 0xffffffffUL);
50084#if defined(DUK_USE_FASTINT)
50085 /* Downgrade checks are not made everywhere, so 'length' is not always
50086 * a fastint (it is a number though). This can be removed once length
50087 * is always guaranteed to be a fastint.
50088 */
50089 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv) || DUK_TVAL_IS_DOUBLE(tv));
50090 if (DUK_TVAL_IS_FASTINT(tv)) {
50091 res = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv);
50092 } else {
50093 res = (duk_uint32_t) DUK_TVAL_GET_DOUBLE(tv);
50094 }
50095#else
50096 res = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
50097#endif /* DUK_USE_FASTINT */
50098
50099 return res;
50100}
50101
50103 duk_context *ctx = (duk_context *) thr;
50104 duk_uint32_t res;
50105 duk_double_t d;
50106
50107 /* Input value should be on stack top and will be coerced and
50108 * popped. Refuse to update an Array's 'length' to a value
50109 * outside the 32-bit range. Negative zero is accepted as zero.
50110 */
50111
50112 /* XXX: fastint */
50113
50114 d = duk_to_number(ctx, -1);
50115 res = (duk_uint32_t) d;
50116 if ((duk_double_t) res != d) {
50118 }
50119 duk_pop(ctx);
50120 return res;
50121}
50122
50123/* Delete elements required by a smaller length, taking into account
50124 * potentially non-configurable elements. Returns non-zero if all
50125 * elements could be deleted, and zero if all or some elements could
50126 * not be deleted. Also writes final "target length" to 'out_result_len'.
50127 * This is the length value that should go into the 'length' property
50128 * (must be set by the caller). Never throws an error.
50129 */
50132 duk_hobject *obj,
50133 duk_uint32_t old_len,
50134 duk_uint32_t new_len,
50135 duk_bool_t force_flag,
50136 duk_uint32_t *out_result_len) {
50137 duk_uint32_t target_len;
50139 duk_uint32_t arr_idx;
50140 duk_hstring *key;
50141 duk_tval *tv;
50142 duk_bool_t rc;
50143
50144 DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
50145 "probably need to remove elements",
50146 (long) old_len, (long) new_len));
50147
50148 /*
50149 * New length is smaller than old length, need to delete properties above
50150 * the new length.
50151 *
50152 * If array part exists, this is straightforward: array entries cannot
50153 * be non-configurable so this is guaranteed to work.
50154 *
50155 * If array part does not exist, array-indexed values are scattered
50156 * in the entry part, and some may not be configurable (preventing length
50157 * from becoming lower than their index + 1). To handle the algorithm
50158 * in E5 Section 15.4.5.1, step l correctly, we scan the entire property
50159 * set twice.
50160 */
50161
50162 DUK_ASSERT(thr != NULL);
50163 DUK_ASSERT(obj != NULL);
50164 DUK_ASSERT(new_len < old_len);
50165 DUK_ASSERT(out_result_len != NULL);
50167
50168 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
50169 /*
50170 * All defined array-indexed properties are in the array part
50171 * (we assume the array part is comprehensive), and all array
50172 * entries are writable, configurable, and enumerable. Thus,
50173 * nothing can prevent array entries from being deleted.
50174 */
50175
50176 DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
50177
50178 if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
50179 /* XXX: assertion that entries >= old_len are already unused */
50180 i = old_len;
50181 } else {
50182 i = DUK_HOBJECT_GET_ASIZE(obj);
50183 }
50185
50186 while (i > new_len) {
50187 i--;
50188 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
50189 DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
50190 }
50191
50192 *out_result_len = new_len;
50193 return 1;
50194 } else {
50195 /*
50196 * Entries part is a bit more complex
50197 */
50198
50199 /* Stage 1: find highest preventing non-configurable entry (if any).
50200 * When forcing, ignore non-configurability.
50201 */
50202
50203 DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
50204
50205 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
50206 "(highest preventing non-configurable entry (if any))"));
50207
50208 target_len = new_len;
50209 if (force_flag) {
50210 DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
50211 goto skip_stage1;
50212 }
50213 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50214 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
50215 if (!key) {
50216 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
50217 continue;
50218 }
50219 if (!DUK_HSTRING_HAS_ARRIDX(key)) {
50220 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
50221 continue;
50222 }
50223
50224 DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
50225 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
50226 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
50227 DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
50228
50229 if (arr_idx < new_len) {
50230 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
50231 (long) i, (long) arr_idx));
50232 continue;
50233 }
50234 if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
50235 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
50236 (long) i, (long) arr_idx));
50237 continue;
50238 }
50239
50240 /* relevant array index is non-configurable, blocks write */
50241 if (arr_idx >= target_len) {
50242 DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
50243 "update target_len %ld -> %ld",
50244 (long) i, (long) arr_idx, (long) target_len,
50245 (long) (arr_idx + 1)));
50246 target_len = arr_idx + 1;
50247 }
50248 }
50249 skip_stage1:
50250
50251 /* stage 2: delete configurable entries above target length */
50252
50253 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
50254 (long) old_len, (long) new_len, (long) target_len));
50255
50256 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
50257 "entries >= target_len"));
50258
50259 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50260 key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
50261 if (!key) {
50262 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
50263 continue;
50264 }
50265 if (!DUK_HSTRING_HAS_ARRIDX(key)) {
50266 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
50267 continue;
50268 }
50269
50270 DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
50271 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
50272 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
50273 DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
50274
50275 if (arr_idx < target_len) {
50276 DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
50277 (long) i, (long) arr_idx));
50278 continue;
50279 }
50280 DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)); /* stage 1 guarantees */
50281
50282 DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
50283 (long) i, (long) arr_idx));
50284
50285 /*
50286 * Slow delete, but we don't care as we're already in a very slow path.
50287 * The delete always succeeds: key has no exotic behavior, property
50288 * is configurable, and no resize occurs.
50289 */
50290 rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
50291 DUK_UNREF(rc);
50292 DUK_ASSERT(rc != 0);
50293 }
50294
50295 /* stage 3: update length (done by caller), decide return code */
50296
50297 DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
50298
50299 *out_result_len = target_len;
50300
50301 if (target_len == new_len) {
50302 DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
50303 return 1;
50304 }
50305 DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
50306 "full length adjustment), return error"));
50307 return 0;
50308 }
50309
50311}
50312
50313/* XXX: is valstack top best place for argument? */
50315 duk_context *ctx = (duk_context *) thr;
50316 duk_propdesc desc;
50317 duk_uint32_t old_len;
50318 duk_uint32_t new_len;
50319 duk_uint32_t result_len;
50320 duk_tval *tv;
50321 duk_bool_t rc;
50322
50323 DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
50324 "new val: %!T",
50325 (duk_tval *) duk_get_tval(ctx, -1)));
50326
50327 DUK_ASSERT(thr != NULL);
50328 DUK_ASSERT(ctx != NULL);
50329 DUK_ASSERT(obj != NULL);
50330
50332
50334
50335 /*
50336 * Get old and new length
50337 */
50338
50339 old_len = duk__get_old_array_length(thr, obj, &desc);
50340 duk_dup(ctx, -1); /* [in_val in_val] */
50341 new_len = duk__to_new_array_length_checked(thr); /* -> [in_val] */
50342 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
50343
50344 /*
50345 * Writability check
50346 */
50347
50348 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50349 DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
50350 return 0;
50351 }
50352
50353 /*
50354 * New length not lower than old length => no changes needed
50355 * (not even array allocation).
50356 */
50357
50358 if (new_len >= old_len) {
50359 DUK_DDD(DUK_DDDPRINT("new length is higher than old length, just update length, no deletions"));
50360
50361 DUK_ASSERT(desc.e_idx >= 0);
50363 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
50365 /* no decref needed for a number */
50366 DUK_TVAL_SET_FASTINT_U32(tv, new_len);
50368 return 1;
50369 }
50370
50371 DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
50372
50373 /*
50374 * New length lower than old length => delete elements, then
50375 * update length.
50376 *
50377 * Note: even though a bunch of elements have been deleted, the 'desc' is
50378 * still valid as properties haven't been resized (and entries compacted).
50379 */
50380
50381 rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
50382 DUK_ASSERT(result_len >= new_len && result_len <= old_len);
50383
50384 DUK_ASSERT(desc.e_idx >= 0);
50386 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
50388 /* no decref needed for a number */
50389 DUK_TVAL_SET_FASTINT_U32(tv, result_len);
50391
50392 /* XXX: shrink array allocation or entries compaction here? */
50393
50394 return rc;
50395}
50396
50397/*
50398 * PUTPROP: Ecmascript property write.
50399 *
50400 * Unlike Ecmascript primitive which returns nothing, returns 1 to indicate
50401 * success and 0 to indicate failure (assuming throw is not set).
50402 *
50403 * This is an extremely tricky function. Some examples:
50404 *
50405 * * Currently a decref may trigger a GC, which may compact an object's
50406 * property allocation. Consequently, any entry indices (e_idx) will
50407 * be potentially invalidated by a decref.
50408 *
50409 * * Exotic behaviors (strings, arrays, arguments object) require,
50410 * among other things:
50411 *
50412 * - Preprocessing before and postprocessing after an actual property
50413 * write. For example, array index write requires pre-checking the
50414 * array 'length' property for access control, and may require an
50415 * array 'length' update after the actual write has succeeded (but
50416 * not if it fails).
50417 *
50418 * - Deletion of multiple entries, as a result of array 'length' write.
50419 *
50420 * * Input values are taken as pointers which may point to the valstack.
50421 * If valstack is resized because of the put (this may happen at least
50422 * when the array part is abandoned), the pointers can be invalidated.
50423 * (We currently make a copy of all of the input values to avoid issues.)
50424 */
50425
50426DUK_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) {
50427 duk_context *ctx = (duk_context *) thr;
50428 duk_tval tv_obj_copy;
50429 duk_tval tv_key_copy;
50430 duk_tval tv_val_copy;
50431 duk_hobject *orig = NULL; /* NULL if tv_obj is primitive */
50432 duk_hobject *curr;
50433 duk_hstring *key = NULL;
50434 duk_propdesc desc;
50435 duk_tval *tv;
50436 duk_uint32_t arr_idx;
50437 duk_bool_t rc;
50438 duk_int_t e_idx;
50439 duk_uint_t sanity;
50440 duk_uint32_t new_array_length = 0; /* 0 = no update */
50441
50442 DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
50443 "(obj -> %!T, key -> %!T, val -> %!T)",
50444 (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
50445 (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
50446
50447 DUK_ASSERT(thr != NULL);
50448 DUK_ASSERT(thr->heap != NULL);
50449 DUK_ASSERT(ctx != NULL);
50450 DUK_ASSERT(tv_obj != NULL);
50451 DUK_ASSERT(tv_key != NULL);
50452 DUK_ASSERT(tv_val != NULL);
50453
50455
50456 /*
50457 * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
50458 * them being invalidated by a valstack resize.
50459 *
50460 * XXX: this is an overkill for some paths, so optimize this later
50461 * (or maybe switch to a stack arguments model entirely).
50462 */
50463
50464 DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
50465 DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
50466 DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
50467 tv_obj = &tv_obj_copy;
50468 tv_key = &tv_key_copy;
50469 tv_val = &tv_val_copy;
50470
50471 /*
50472 * Coercion and fast path processing.
50473 */
50474
50475 switch (DUK_TVAL_GET_TAG(tv_obj)) {
50476 case DUK_TAG_UNDEFINED:
50477 case DUK_TAG_NULL: {
50478 /* Note: unconditional throw */
50479 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
50480 (duk_tval *) tv_obj));
50481#if defined(DUK_USE_PARANOID_ERRORS)
50483#else
50484 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
50486#endif
50487 return 0;
50488 }
50489
50490 case DUK_TAG_BOOLEAN: {
50491 DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
50493 break;
50494 }
50495
50496 case DUK_TAG_STRING: {
50497 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
50498
50499 /*
50500 * Note: currently no fast path for array index writes.
50501 * They won't be possible anyway as strings are immutable.
50502 */
50503
50504 DUK_ASSERT(key == NULL);
50505 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50506 DUK_ASSERT(key != NULL);
50507
50508 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
50509 goto fail_not_writable;
50510 }
50511
50512 if (arr_idx != DUK__NO_ARRAY_INDEX &&
50513 arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
50514 goto fail_not_writable;
50515 }
50516
50517 DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
50519 goto lookup; /* avoid double coercion */
50520 }
50521
50522 case DUK_TAG_OBJECT: {
50523 orig = DUK_TVAL_GET_OBJECT(tv_obj);
50524 DUK_ASSERT(orig != NULL);
50525
50526#if defined(DUK_USE_ROM_OBJECTS)
50527 /* With this check in place fast paths won't need read-only
50528 * object checks. This is technically incorrect if there are
50529 * setters that cause no writes to ROM objects, but current
50530 * built-ins don't have such setters.
50531 */
50532 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
50533 DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
50534 goto fail_not_writable_no_pop; /* Must avoid duk_pop() in exit path */
50535 }
50536#endif
50537
50538 /* The fast path for array property put is not fully compliant:
50539 * If one places conflicting number-indexed properties into
50540 * Array.prototype (for example, a non-writable Array.prototype[7])
50541 * the fast path will incorrectly ignore them.
50542 *
50543 * This fast path could be made compliant by falling through
50544 * to the slow path if the previous value was UNUSED. This would
50545 * also remove the need to check for extensibility. Right now a
50546 * non-extensible array is slower than an extensible one as far
50547 * as writes are concerned.
50548 *
50549 * The fast path behavior is documented in more detail here:
50550 * tests/ecmascript/test-misc-array-fast-write.js
50551 */
50552
50553 if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val, &desc) != 0) {
50554 DUK_DDD(DUK_DDDPRINT("array fast path success"));
50555 return 1;
50556 }
50557
50558 if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
50559 DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufferobject fast path"));
50560 return 1;
50561 }
50562
50563#if defined(DUK_USE_ES6_PROXY)
50565 duk_hobject *h_target;
50566 duk_bool_t tmp_bool;
50567
50568 if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
50569 /* -> [ ... trap handler ] */
50570 DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
50571 duk_push_hobject(ctx, h_target); /* target */
50572 duk_push_tval(ctx, tv_key); /* P */
50573 duk_push_tval(ctx, tv_val); /* V */
50574 duk_push_tval(ctx, tv_obj); /* Receiver: Proxy object */
50575 duk_call_method(ctx, 4 /*nargs*/);
50576 tmp_bool = duk_to_boolean(ctx, -1);
50577 duk_pop(ctx);
50578 if (!tmp_bool) {
50579 goto fail_proxy_rejected;
50580 }
50581
50582 /* Target object must be checked for a conflicting
50583 * non-configurable property.
50584 */
50585 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50586 DUK_ASSERT(key != NULL);
50587
50588 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
50589 duk_tval *tv_targ = duk_require_tval(ctx, -1);
50590 duk_bool_t datadesc_reject;
50591 duk_bool_t accdesc_reject;
50592
50593 DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
50594 "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
50595 "desc.get=%p, desc.set=%p",
50596 (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
50597 (unsigned long) desc.flags,
50598 (void *) desc.get, (void *) desc.set));
50599
50600 datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
50603 !duk_js_samevalue(tv_val, tv_targ);
50604 accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
50606 (desc.set == NULL);
50607 if (datadesc_reject || accdesc_reject) {
50609 }
50610
50611 duk_pop_2(ctx);
50612 } else {
50613 duk_pop(ctx);
50614 }
50615 return 1; /* success */
50616 }
50617
50618 orig = h_target; /* resume write to target */
50619 DUK_TVAL_SET_OBJECT(tv_obj, orig);
50620 }
50621#endif /* DUK_USE_ES6_PROXY */
50622
50623 curr = orig;
50624 break;
50625 }
50626
50627 case DUK_TAG_BUFFER: {
50628 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
50629 duk_int_t pop_count = 0;
50630
50631 /*
50632 * Because buffer values may be looped over and read/written
50633 * from, an array index fast path is important.
50634 */
50635
50636#if defined(DUK_USE_FASTINT)
50637 if (DUK_TVAL_IS_FASTINT(tv_key)) {
50638 arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
50639 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
50640 pop_count = 0;
50641 } else
50642#endif
50643 if (DUK_TVAL_IS_NUMBER(tv_key)) {
50644 arr_idx = duk__tval_number_to_arr_idx(tv_key);
50645 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
50646 pop_count = 0;
50647 } else {
50648 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50649 DUK_ASSERT(key != NULL);
50650 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
50651 "coercion key is %!T, arr_idx %ld",
50652 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
50653 pop_count = 1;
50654 }
50655
50656 if (arr_idx != DUK__NO_ARRAY_INDEX &&
50657 arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
50658 duk_uint8_t *data;
50659 DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
50660 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
50661
50662 /* XXX: duk_to_int() ensures we'll get 8 lowest bits as
50663 * as input is within duk_int_t range (capped outside it).
50664 */
50665#if defined(DUK_USE_FASTINT)
50666 /* Buffer writes are often integers. */
50667 if (DUK_TVAL_IS_FASTINT(tv_val)) {
50668 data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
50669 }
50670 else
50671#endif
50672 {
50673 duk_push_tval(ctx, tv_val);
50674 data[arr_idx] = (duk_uint8_t) duk_to_uint32(ctx, -1);
50675 pop_count++;
50676 }
50677
50678 duk_pop_n(ctx, pop_count);
50679 DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
50680 return 1;
50681 }
50682
50683 if (pop_count == 0) {
50684 /* This is a pretty awkward control flow, but we need to recheck the
50685 * key coercion here.
50686 */
50687 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50688 DUK_ASSERT(key != NULL);
50689 DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
50690 "coercion key is %!T, arr_idx %ld",
50691 (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
50692 }
50693
50694 if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
50695 key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr) ||
50696 key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr) ||
50698 goto fail_not_writable;
50699 }
50700
50701 DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from buffer prototype"));
50703 goto lookup; /* avoid double coercion */
50704 }
50705
50706 case DUK_TAG_POINTER: {
50707 DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
50709 break;
50710 }
50711
50712 case DUK_TAG_LIGHTFUNC: {
50713 /* All lightfunc own properties are non-writable and the lightfunc
50714 * is considered non-extensible. However, the write may be captured
50715 * by an inherited setter which means we can't stop the lookup here.
50716 */
50717
50718 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50719
50720 if (duk__key_is_lightfunc_ownprop(thr, key)) {
50721 goto fail_not_writable;
50722 }
50723
50724 DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
50726 goto lookup; /* avoid double coercion */
50727 }
50728
50729#if defined(DUK_USE_FASTINT)
50730 case DUK_TAG_FASTINT:
50731#endif
50732 default: {
50733 /* number */
50734 DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
50737 break;
50738 }
50739 }
50740
50741 DUK_ASSERT(key == NULL);
50742 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50743 DUK_ASSERT(key != NULL);
50744
50745 lookup:
50746
50747 /*
50748 * Check whether the property already exists in the prototype chain.
50749 * Note that the actual write goes into the original base object
50750 * (except if an accessor property captures the write).
50751 */
50752
50753 /* [key] */
50754
50755 DUK_ASSERT(curr != NULL);
50757 do {
50758 if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
50759 goto next_in_chain;
50760 }
50761
50762 if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
50763 /*
50764 * Found existing accessor property (own or inherited).
50765 * Call setter with 'this' set to orig, and value as the only argument.
50766 * Setter calls are OK even for ROM objects.
50767 *
50768 * Note: no exotic arguments object behavior, because [[Put]] never
50769 * calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
50770 */
50771
50772 duk_hobject *setter;
50773
50774 DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
50775
50776 setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
50777 if (!setter) {
50778 goto fail_no_setter;
50779 }
50780 duk_push_hobject(ctx, setter);
50781 duk_push_tval(ctx, tv_obj); /* note: original, uncoerced base */
50782 duk_push_tval(ctx, tv_val); /* [key setter this val] */
50783#ifdef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
50784 duk_dup(ctx, -4);
50785 duk_call_method(ctx, 2); /* [key setter this val key] -> [key retval] */
50786#else
50787 duk_call_method(ctx, 1); /* [key setter this val] -> [key retval] */
50788#endif
50789 duk_pop(ctx); /* ignore retval -> [key] */
50790 goto success_no_arguments_exotic;
50791 }
50792
50793 if (orig == NULL) {
50794 /*
50795 * Found existing own or inherited plain property, but original
50796 * base is a primitive value.
50797 */
50798 DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
50799 goto fail_base_primitive;
50800 }
50801
50802 if (curr != orig) {
50803 /*
50804 * Found existing inherited plain property.
50805 * Do an access control check, and if OK, write
50806 * new property to 'orig'.
50807 */
50808 if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
50809 DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
50810 goto fail_not_extensible;
50811 }
50812 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50813 DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
50814 goto fail_not_writable;
50815 }
50816 DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
50817 goto create_new;
50818 } else {
50819 /*
50820 * Found existing own (non-inherited) plain property.
50821 * Do an access control check and update in place.
50822 */
50823
50824 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50825 DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
50826 goto fail_not_writable;
50827 }
50828 if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
50829 DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
50830 if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
50831 duk_hbufferobject *h_bufobj;
50832 duk_uint_t byte_off;
50833 duk_small_uint_t elem_size;
50834
50835 h_bufobj = (duk_hbufferobject *) curr;
50837
50838 DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
50839
50840 /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
50841 * length downshift won't.
50842 */
50843 if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
50844 duk_uint8_t *data;
50845 DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
50846
50847 DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX); /* index/length check guarantees */
50848 byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
50849 elem_size = 1 << h_bufobj->shift;
50850
50851 /* Coerce to number before validating pointers etc so that the
50852 * number coercions in duk_hbufferobject_validated_write() are
50853 * guaranteed to be side effect free and not invalidate the
50854 * pointer checks we do here.
50855 */
50856 duk_push_tval(ctx, tv_val);
50857 duk_to_number(ctx, -1);
50858
50859 if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
50860 data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
50861 duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
50862 } else {
50863 DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
50864 }
50865 duk_pop(ctx);
50866 goto success_no_arguments_exotic;
50867 }
50868 }
50869
50870 goto fail_internal; /* should not happen */
50871 }
50872 DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
50873 goto update_old;
50874 }
50876
50877 next_in_chain:
50878 /* XXX: option to pretend property doesn't exist if sanity limit is
50879 * hit might be useful.
50880 */
50881 if (sanity-- == 0) {
50883 }
50884 curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
50885 } while (curr);
50886
50887 /*
50888 * Property not found in prototype chain.
50889 */
50890
50891 DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
50892
50893 if (orig == NULL) {
50894 DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
50895 goto fail_base_primitive;
50896 }
50897
50898 if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
50899 DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
50900 goto fail_not_extensible;
50901 }
50902
50903 goto create_new;
50904
50905 update_old:
50906
50907 /*
50908 * Update an existing property of the base object.
50909 */
50910
50911 /* [key] */
50912
50913 DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
50914
50915 DUK_ASSERT(orig != NULL);
50916#if defined(DUK_USE_ROM_OBJECTS)
50917 /* This should not happen because DUK_TAG_OBJECT case checks
50918 * for this already, but check just in case.
50919 */
50920 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
50921 goto fail_not_writable;
50922 }
50923#endif
50924
50925 /* Although there are writable virtual properties (e.g. plain buffer
50926 * and buffer object number indices), they are handled before we come
50927 * here.
50928 */
50930 DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
50931
50932 if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
50933 key == DUK_HTHREAD_STRING_LENGTH(thr)) {
50934 /*
50935 * Write to 'length' of an array is a very complex case
50936 * handled in a helper which updates both the array elements
50937 * and writes the new 'length'. The write may result in an
50938 * unconditional RangeError or a partial write (indicated
50939 * by a return code).
50940 *
50941 * Note: the helper has an unnecessary writability check
50942 * for 'length', we already know it is writable.
50943 */
50944
50945 DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
50946
50947 /* XXX: the helper currently assumes stack top contains new
50948 * 'length' value and the whole calling convention is not very
50949 * compatible with what we need.
50950 */
50951
50952 duk_push_tval(ctx, tv_val); /* [key val] */
50953 rc = duk__handle_put_array_length(thr, orig);
50954 duk_pop(ctx); /* [key val] -> [key] */
50955 if (!rc) {
50956 goto fail_array_length_partial;
50957 }
50958
50959 /* key is 'length', cannot match argument exotic behavior */
50960 goto success_no_arguments_exotic;
50961 }
50962
50963 if (desc.e_idx >= 0) {
50964 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
50965 DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
50966 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
50967 /* don't touch property attributes or hash part */
50968 DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
50969 (long) desc.e_idx, (duk_tval *) tv));
50970 } else {
50971 /* Note: array entries are always writable, so the writability check
50972 * above is pointless for them. The check could be avoided with some
50973 * refactoring but is probably not worth it.
50974 */
50975
50976 DUK_ASSERT(desc.a_idx >= 0);
50977 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
50978 DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
50979 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
50980 DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
50981 (long) desc.a_idx, (duk_tval *) tv));
50982 }
50983
50984 /* Regardless of whether property is found in entry or array part,
50985 * it may have arguments exotic behavior (array indices may reside
50986 * in entry part for abandoned / non-existent array parts).
50987 */
50988 goto success_with_arguments_exotic;
50989
50990 create_new:
50991
50992 /*
50993 * Create a new property in the original object.
50994 *
50995 * Exotic properties need to be reconsidered here from a write
50996 * perspective (not just property attributes perspective).
50997 * However, the property does not exist in the object already,
50998 * so this limits the kind of exotic properties that apply.
50999 */
51000
51001 /* [key] */
51002
51003 DUK_DDD(DUK_DDDPRINT("create new property to original object"));
51004
51005 DUK_ASSERT(orig != NULL);
51006
51007#if defined(DUK_USE_ROM_OBJECTS)
51008 /* This should not happen because DUK_TAG_OBJECT case checks
51009 * for this already, but check just in case.
51010 */
51011 if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
51012 goto fail_not_writable;
51013 }
51014#endif
51015
51016 /* Not possible because array object 'length' is present
51017 * from its creation and cannot be deleted, and is thus
51018 * caught as an existing property above.
51019 */
51021 key == DUK_HTHREAD_STRING_LENGTH(thr)));
51022
51023 if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
51024 arr_idx != DUK__NO_ARRAY_INDEX) {
51025 /* automatic length update */
51026 duk_uint32_t old_len;
51027
51028 old_len = duk__get_old_array_length(thr, orig, &desc);
51029
51030 if (arr_idx >= old_len) {
51031 DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
51032 "(arr_idx=%ld, old_len=%ld)",
51033 (long) arr_idx, (long) old_len));
51034
51035 if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
51036 DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
51037 goto fail_not_writable;
51038 }
51039
51040 /* Note: actual update happens once write has been completed
51041 * without error below. The write should always succeed
51042 * from a specification viewpoint, but we may e.g. run out
51043 * of memory. It's safer in this order.
51044 */
51045
51046 DUK_ASSERT(arr_idx != 0xffffffffUL);
51047 new_array_length = arr_idx + 1; /* flag for later write */
51048 } else {
51049 DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
51050 "(arr_idx=%ld, old_len=%ld)",
51051 (long) arr_idx, (long) old_len));
51052 }
51053 }
51054
51055 /* write_to_array_part: */
51056
51057 /*
51058 * Write to array part?
51059 *
51060 * Note: array abandonding requires a property resize which uses
51061 * 'rechecks' valstack for temporaries and may cause any existing
51062 * valstack pointers to be invalidated. To protect against this,
51063 * tv_obj, tv_key, and tv_val are copies of the original inputs.
51064 */
51065
51066 if (arr_idx != DUK__NO_ARRAY_INDEX &&
51068 if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
51069 goto no_array_growth;
51070 }
51071
51072 /*
51073 * Array needs to grow, but we don't want it becoming too sparse.
51074 * If it were to become sparse, abandon array part, moving all
51075 * array entries into the entries part (for good).
51076 *
51077 * Since we don't keep track of actual density (used vs. size) of
51078 * the array part, we need to estimate somehow. The check is made
51079 * in two parts:
51080 *
51081 * - Check whether the resize need is small compared to the
51082 * current size (relatively); if so, resize without further
51083 * checking (essentially we assume that the original part is
51084 * "dense" so that the result would be dense enough).
51085 *
51086 * - Otherwise, compute the resize using an actual density
51087 * measurement based on counting the used array entries.
51088 */
51089
51090 DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
51091 "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
51092 (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
51093
51095 duk_uint32_t old_used;
51096 duk_uint32_t old_size;
51097
51098 DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
51099
51100 duk__compute_a_stats(thr, orig, &old_used, &old_size);
51101
51102 DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
51103 (long) old_used, (long) old_size, (long) arr_idx));
51104
51105 /* Note: intentionally use approximations to shave a few instructions:
51106 * a_used = old_used (accurate: old_used + 1)
51107 * a_size = arr_idx (accurate: arr_idx + 1)
51108 */
51109 if (duk__abandon_array_density_check(old_used, arr_idx)) {
51110 DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
51111 "decided to abandon array part (would become too sparse)"));
51112
51113 /* abandoning requires a props allocation resize and
51114 * 'rechecks' the valstack, invalidating any existing
51115 * valstack value pointers!
51116 */
51117 duk__abandon_array_checked(thr, orig);
51119
51120 goto write_to_entry_part;
51121 }
51122
51123 DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
51124 } else {
51125 DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
51126 }
51127
51128 DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
51129 "decided to extend current allocation"));
51130
51131 duk__grow_props_for_array_item(thr, orig, arr_idx);
51132
51133 no_array_growth:
51134
51135 /* Note: assume array part is comprehensive, so that either
51136 * the write goes to the array part, or we've abandoned the
51137 * array above (and will not come here).
51138 */
51139
51141 DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
51142
51143 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
51144 /* prev value must be unused, no decref */
51146 DUK_TVAL_SET_TVAL(tv, tv_val);
51147 DUK_TVAL_INCREF(thr, tv);
51148 DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
51149 (long) arr_idx, (duk_tval *) tv));
51150
51151 /* Note: array part values are [[Writable]], [[Enumerable]],
51152 * and [[Configurable]] which matches the required attributes
51153 * here.
51154 */
51155 goto entry_updated;
51156 }
51157
51158 write_to_entry_part:
51159
51160 /*
51161 * Write to entry part
51162 */
51163
51164 /* entry allocation updates hash part and increases the key
51165 * refcount; may need a props allocation resize but doesn't
51166 * 'recheck' the valstack.
51167 */
51168 e_idx = duk__alloc_entry_checked(thr, orig, key);
51169 DUK_ASSERT(e_idx >= 0);
51170
51171 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
51172 /* prev value can be garbage, no decref */
51173 DUK_TVAL_SET_TVAL(tv, tv_val);
51174 DUK_TVAL_INCREF(thr, tv);
51176 goto entry_updated;
51177
51178 entry_updated:
51179
51180 /*
51181 * Possible pending array length update, which must only be done
51182 * if the actual entry write succeeded.
51183 */
51184
51185 if (new_array_length > 0) {
51186 /*
51187 * Note: zero works as a "no update" marker because the new length
51188 * can never be zero after a new property is written.
51189 *
51190 * Note: must re-lookup because calls above (e.g. duk__alloc_entry_checked())
51191 * may realloc and compact properties and hence change e_idx.
51192 */
51193
51194 DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
51195 (long) new_array_length));
51196
51197 rc = duk__get_own_propdesc_raw(thr, orig, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &desc, 0 /*flags*/); /* don't push value */
51198 DUK_UNREF(rc);
51199 DUK_ASSERT(rc != 0);
51200 DUK_ASSERT(desc.e_idx >= 0);
51201
51202 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
51204 /* no need for decref/incref because value is a number */
51205 DUK_TVAL_SET_FASTINT_U32(tv, new_array_length);
51206 }
51207
51208 /*
51209 * Arguments exotic behavior not possible for new properties: all
51210 * magically bound properties are initially present in the arguments
51211 * object, and if they are deleted, the binding is also removed from
51212 * parameter map.
51213 */
51214
51215 goto success_no_arguments_exotic;
51216
51217 success_with_arguments_exotic:
51218
51219 /*
51220 * Arguments objects have exotic [[DefineOwnProperty]] which updates
51221 * the internal 'map' of arguments for writes to currently mapped
51222 * arguments. More conretely, writes to mapped arguments generate
51223 * a write to a bound variable.
51224 *
51225 * The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
51226 * data properties and new properties, but not for existing accessors.
51227 * Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
51228 * have a Desc with 'Value' (and possibly other properties too), and
51229 * we end up in step 5.b.i.
51230 */
51231
51232 if (arr_idx != DUK__NO_ARRAY_INDEX &&
51234 /* Note: only numbered indices are relevant, so arr_idx fast reject
51235 * is good (this is valid unless there are more than 4**32-1 arguments).
51236 */
51237
51238 DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
51239
51240 /* Note: we can reuse 'desc' here */
51241
51242 /* XXX: top of stack must contain value, which helper doesn't touch,
51243 * rework to use tv_val directly?
51244 */
51245
51246 duk_push_tval(ctx, tv_val);
51247 (void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
51248 duk_pop(ctx);
51249 }
51250 /* fall thru */
51251
51252 success_no_arguments_exotic:
51253 /* shared exit path now */
51254 DUK_DDD(DUK_DDDPRINT("result: success"));
51255 duk_pop(ctx); /* remove key */
51256 return 1;
51257
51258#if defined(DUK_USE_ES6_PROXY)
51259 fail_proxy_rejected:
51260 DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
51261 if (throw_flag) {
51263 }
51264 /* Note: no key on stack */
51265 return 0;
51266#endif
51267
51268 fail_base_primitive:
51269 DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
51270 if (throw_flag) {
51271#if defined(DUK_USE_PARANOID_ERRORS)
51273#else
51274 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
51276#endif
51277 }
51278 duk_pop(ctx); /* remove key */
51279 return 0;
51280
51281 fail_not_extensible:
51282 DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
51283 if (throw_flag) {
51285 }
51286 duk_pop(ctx); /* remove key */
51287 return 0;
51288
51289 fail_not_writable:
51290 DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
51291 if (throw_flag) {
51293 }
51294 duk_pop(ctx); /* remove key */
51295 return 0;
51296
51297#if defined(DUK_USE_ROM_OBJECTS)
51298 fail_not_writable_no_pop:
51299 DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
51300 if (throw_flag) {
51302 }
51303 return 0;
51304#endif
51305
51306 fail_array_length_partial:
51307 DUK_DDD(DUK_DDDPRINT("result: error, array length write only partially successful"));
51308 if (throw_flag) {
51310 }
51311 duk_pop(ctx); /* remove key */
51312 return 0;
51313
51314 fail_no_setter:
51315 DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
51316 if (throw_flag) {
51319 duk_pop(ctx); /* remove key */
51320 return 0;
51321
51322 fail_internal:
51323 DUK_DDD(DUK_DDDPRINT("result: error, internal"));
51324 if (throw_flag) {
51326 }
51327 duk_pop(ctx); /* remove key */
51328 return 0;
51329}
51330
51331/*
51332 * Ecmascript compliant [[Delete]](P, Throw).
51333 */
51334
51336 duk_propdesc desc;
51337 duk_tval *tv;
51338 duk_uint32_t arr_idx;
51339 duk_bool_t throw_flag;
51340 duk_bool_t force_flag;
51341
51342 throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
51343 force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
51344
51345 DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
51346 (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
51347 (duk_heaphdr *) obj, (duk_heaphdr *) key));
51348
51349 DUK_ASSERT(thr != NULL);
51350 DUK_ASSERT(thr->heap != NULL);
51351 DUK_ASSERT(obj != NULL);
51352 DUK_ASSERT(key != NULL);
51353
51355
51356 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51357
51358 /* 0 = don't push current value */
51359 if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
51360 DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
51361 goto success;
51362 }
51363
51364#if defined(DUK_USE_ROM_OBJECTS)
51366 DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
51367 goto fail_not_configurable;
51368 }
51369#endif
51370
51371 if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
51372 goto fail_not_configurable;
51373 }
51374 if (desc.a_idx < 0 && desc.e_idx < 0) {
51375 /* Currently there are no deletable virtual properties, but
51376 * with force_flag we might attempt to delete one.
51377 */
51378 goto fail_virtual;
51379 }
51380
51381 if (desc.a_idx >= 0) {
51382 DUK_ASSERT(desc.e_idx < 0);
51383
51384 tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
51385 DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
51386 goto success;
51387 } else {
51388 duk_hobject *h_get = NULL;
51389 duk_hobject *h_set = NULL;
51390 duk_tval tv_tmp;
51391
51392 DUK_ASSERT(desc.a_idx < 0);
51393
51394 /* Set property slot to an empty state. Careful not to invoke
51395 * any side effects while using desc.e_idx so that it doesn't
51396 * get invalidated by a finalizer mutating our object.
51397 */
51398
51399 /* remove hash entry (no decref) */
51400#if defined(DUK_USE_HOBJECT_HASH_PART)
51401 if (desc.h_idx >= 0) {
51402 duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
51403
51404 DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
51406 DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
51407 h_base[desc.h_idx] = DUK__HASH_DELETED;
51408 } else {
51410 }
51411#else
51413#endif
51414
51415 /* remove value */
51416 DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
51417 (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
51418 DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
51419 DUK_MEMSET((void *) &tv_tmp, 0, sizeof(tv_tmp));
51420 DUK_TVAL_SET_UNDEFINED(&tv_tmp);
51421 if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
51422 h_get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
51423 h_set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
51424 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
51425 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
51426 } else {
51427 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
51428 DUK_TVAL_SET_TVAL(&tv_tmp, tv);
51430 }
51431#if 0
51432 /* Not strictly necessary because if key == NULL, flag MUST be ignored. */
51433 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
51434#endif
51435
51436 /* remove key */
51437 DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
51438 (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
51439 DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
51440 DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
51441 DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
51442
51443 /* Do decrefs only with safe pointers to avoid side effects
51444 * disturbing e_idx.
51445 */
51446 DUK_TVAL_DECREF(thr, &tv_tmp);
51447 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_get);
51448 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_set);
51449 DUK_HSTRING_DECREF(thr, key);
51450 goto success;
51451 }
51452
51454
51455 success:
51456 /*
51457 * Argument exotic [[Delete]] behavior (E5 Section 10.6) is
51458 * a post-check, keeping arguments internal 'map' in sync with
51459 * any successful deletes (note that property does not need to
51460 * exist for delete to 'succeed').
51461 *
51462 * Delete key from 'map'. Since 'map' only contains array index
51463 * keys, we can use arr_idx for a fast skip.
51464 */
51465
51466 DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
51467
51469 /* Note: only numbered indices are relevant, so arr_idx fast reject
51470 * is good (this is valid unless there are more than 4**32-1 arguments).
51471 */
51472
51473 DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
51474
51475 /* Note: we can reuse 'desc' here */
51476 (void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
51477 }
51478
51479 DUK_DDD(DUK_DDDPRINT("delete successful"));
51480 return 1;
51481
51482 fail_virtual:
51483 DUK_DDD(DUK_DDDPRINT("delete failed: property found, force flag, but virtual"));
51484
51485 if (throw_flag) {
51487 }
51488 return 0;
51489
51490 fail_not_configurable:
51491 DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
51492
51493 if (throw_flag) {
51495 }
51496 return 0;
51497}
51498
51499/*
51500 * DELPROP: Ecmascript property deletion.
51501 */
51502
51504 duk_context *ctx = (duk_context *) thr;
51505 duk_hstring *key = NULL;
51506#if defined(DUK_USE_ES6_PROXY)
51507 duk_propdesc desc;
51508#endif
51509 duk_int_t entry_top;
51510 duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
51511 duk_bool_t rc;
51512
51513 DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
51514 (void *) thr, (void *) tv_obj, (void *) tv_key,
51515 (duk_tval *) tv_obj, (duk_tval *) tv_key));
51516
51517 DUK_ASSERT(ctx != NULL);
51518 DUK_ASSERT(thr != NULL);
51519 DUK_ASSERT(thr->heap != NULL);
51520 DUK_ASSERT(tv_obj != NULL);
51521 DUK_ASSERT(tv_key != NULL);
51522
51524
51525 /* Storing the entry top is cheaper here to ensure stack is correct at exit,
51526 * as there are several paths out.
51527 */
51528 entry_top = duk_get_top(ctx);
51529
51530 if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
51531 DUK_TVAL_IS_NULL(tv_obj)) {
51532 DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
51533 goto fail_invalid_base_uncond;
51534 }
51535
51536 duk_push_tval(ctx, tv_obj);
51537 duk_push_tval(ctx, tv_key);
51538
51539 tv_obj = DUK_GET_TVAL_NEGIDX(ctx, -2);
51540 if (DUK_TVAL_IS_OBJECT(tv_obj)) {
51541 duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
51542 DUK_ASSERT(obj != NULL);
51543
51544#if defined(DUK_USE_ES6_PROXY)
51546 duk_hobject *h_target;
51547 duk_bool_t tmp_bool;
51548
51549 /* Note: proxy handling must happen before key is string coerced. */
51550
51551 if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
51552 /* -> [ ... trap handler ] */
51553 DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
51554 duk_push_hobject(ctx, h_target); /* target */
51555 duk_push_tval(ctx, tv_key); /* P */
51556 duk_call_method(ctx, 2 /*nargs*/);
51557 tmp_bool = duk_to_boolean(ctx, -1);
51558 duk_pop(ctx);
51559 if (!tmp_bool) {
51560 goto fail_proxy_rejected; /* retval indicates delete failed */
51561 }
51562
51563 /* Target object must be checked for a conflicting
51564 * non-configurable property.
51565 */
51566 arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
51567 DUK_ASSERT(key != NULL);
51568
51569 if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
51570 int desc_reject;
51571
51572 DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
51573 "conflicting property; desc.flags=0x%08lx, "
51574 "desc.get=%p, desc.set=%p",
51575 (duk_heaphdr *) key, (unsigned long) desc.flags,
51576 (void *) desc.get, (void *) desc.set));
51577
51578 desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
51579 if (desc_reject) {
51580 /* unconditional */
51582 }
51583 }
51584 rc = 1; /* success */
51585 goto done_rc;
51586 }
51587
51588 obj = h_target; /* resume delete to target */
51589 }
51590#endif /* DUK_USE_ES6_PROXY */
51591
51592 duk_to_string(ctx, -1);
51593 key = duk_get_hstring(ctx, -1);
51594 DUK_ASSERT(key != NULL);
51595
51596 rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
51597 goto done_rc;
51598 } else if (DUK_TVAL_IS_STRING(tv_obj)) {
51599 /* XXX: unnecessary string coercion for array indices,
51600 * intentional to keep small.
51601 */
51602 duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
51603 DUK_ASSERT(h != NULL);
51604
51605 duk_to_string(ctx, -1);
51606 key = duk_get_hstring(ctx, -1);
51607 DUK_ASSERT(key != NULL);
51608
51609 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51610 goto fail_not_configurable;
51611 }
51612
51613 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51614
51615 if (arr_idx != DUK__NO_ARRAY_INDEX &&
51616 arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
51617 goto fail_not_configurable;
51618 }
51619 } else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
51620 /* XXX: unnecessary string coercion for array indices,
51621 * intentional to keep small; some overlap with string
51622 * handling.
51623 */
51624 duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
51625 DUK_ASSERT(h != NULL);
51626
51627 duk_to_string(ctx, -1);
51628 key = duk_get_hstring(ctx, -1);
51629 DUK_ASSERT(key != NULL);
51630
51631 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51632 goto fail_not_configurable;
51633 }
51634
51635 arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51636
51637 if (arr_idx != DUK__NO_ARRAY_INDEX &&
51638 arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
51639 goto fail_not_configurable;
51640 }
51641 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
51642 /* Lightfunc virtual properties are non-configurable, so
51643 * reject if match any of them.
51644 */
51645
51646 duk_to_string(ctx, -1);
51647 key = duk_get_hstring(ctx, -1);
51648 DUK_ASSERT(key != NULL);
51649
51650 if (duk__key_is_lightfunc_ownprop(thr, key)) {
51651 goto fail_not_configurable;
51652 }
51653 }
51654
51655 /* non-object base, no offending virtual property */
51656 rc = 1;
51657 goto done_rc;
51658
51659 done_rc:
51660 duk_set_top(ctx, entry_top);
51661 return rc;
51662
51663 fail_invalid_base_uncond:
51664 /* Note: unconditional throw */
51665 DUK_ASSERT(duk_get_top(ctx) == entry_top);
51666#if defined(DUK_USE_PARANOID_ERRORS)
51668#else
51669 DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
51671#endif
51672 return 0;
51673
51674#if defined(DUK_USE_ES6_PROXY)
51675 fail_proxy_rejected:
51676 if (throw_flag) {
51678 }
51679 duk_set_top(ctx, entry_top);
51680 return 0;
51681#endif
51682
51683 fail_not_configurable:
51684 if (throw_flag) {
51686 }
51687 duk_set_top(ctx, entry_top);
51688 return 0;
51689}
51690
51691/*
51692 * Internal helper to define a property with specific flags, ignoring
51693 * normal semantics such as extensibility, write protection etc.
51694 * Overwrites any existing value and attributes unless caller requests
51695 * that value only be updated if it doesn't already exists.
51696 *
51697 * Does not support:
51698 * - virtual properties (error if write attempted)
51699 * - getter/setter properties (error if write attempted)
51700 * - non-default (!= WEC) attributes for array entries (error if attempted)
51701 * - array abandoning: if array part exists, it is always extended
51702 * - array 'length' updating
51703 *
51704 * Stack: [... in_val] -> []
51705 *
51706 * Used for e.g. built-in initialization and environment record
51707 * operations.
51708 */
51709
51711 duk_context *ctx = (duk_context *) thr;
51712 duk_propdesc desc;
51713 duk_uint32_t arr_idx;
51714 duk_int_t e_idx;
51715 duk_tval *tv1 = NULL;
51716 duk_tval *tv2 = NULL;
51717 duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK; /* mask out flags not actually stored */
51718
51719 DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
51720 (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
51721 (unsigned long) flags, (duk_tval *) duk_get_tval(ctx, -1)));
51722
51723 DUK_ASSERT(thr != NULL);
51724 DUK_ASSERT(thr->heap != NULL);
51725 DUK_ASSERT(obj != NULL);
51726 DUK_ASSERT(key != NULL);
51729 DUK_ASSERT(duk_is_valid_index(ctx, -1)); /* contains value */
51730
51731 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
51732
51733 if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
51734 if (desc.e_idx >= 0) {
51735 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51736 DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
51737 goto pop_exit;
51738 }
51739 DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
51740 if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
51741 DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
51742 goto error_internal;
51743 }
51744
51745 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
51746 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
51747 } else if (desc.a_idx >= 0) {
51748 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51749 DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
51750 goto pop_exit;
51751 }
51752 DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
51753 if (propflags != DUK_PROPDESC_FLAGS_WEC) {
51754 DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
51755 (unsigned long) propflags));
51756 goto error_internal;
51757 }
51758
51759 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
51760 } else {
51761 if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51762 DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
51763 goto pop_exit;
51764 }
51765 DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> failure"));
51766 goto error_virtual;
51767 }
51768
51769 goto write_value;
51770 }
51771
51772 if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
51773 if (arr_idx != DUK__NO_ARRAY_INDEX) {
51774 DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
51775 DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
51776
51777 /* always grow the array, no sparse / abandon support here */
51778 if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
51779 duk__grow_props_for_array_item(thr, obj, arr_idx);
51780 }
51781
51782 DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
51783 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
51784 goto write_value;
51785 }
51786 }
51787
51788 DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
51789 e_idx = duk__alloc_entry_checked(thr, obj, key); /* increases key refcount */
51790 DUK_ASSERT(e_idx >= 0);
51791 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
51792 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
51793 /* new entry: previous value is garbage; set to undefined to share write_value */
51795 goto write_value;
51796
51797 write_value:
51798 /* tv1 points to value storage */
51799
51800 tv2 = duk_require_tval(ctx, -1); /* late lookup, avoid side effects */
51801 DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
51802 (duk_tval *) tv1, (duk_tval *) tv2));
51803
51804 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
51805 goto pop_exit;
51806
51807 pop_exit:
51808 duk_pop(ctx); /* remove in_val */
51809 return;
51810
51811 error_internal:
51813 return;
51814
51815 error_virtual:
51817 return;
51818}
51819
51820/*
51821 * Fast path for defining array indexed values without interning the key.
51822 * This is used by e.g. code for Array prototype and traceback creation so
51823 * must avoid interning.
51824 */
51825
51827 duk_context *ctx = (duk_context *) thr;
51828 duk_hstring *key;
51829 duk_tval *tv1, *tv2;
51830
51831 DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
51832 "arr_idx=%ld, flags=0x%02lx, val=%!T",
51833 (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
51834 (duk_tval *) duk_get_tval(ctx, -1)));
51835
51836 DUK_ASSERT(thr != NULL);
51837 DUK_ASSERT(thr->heap != NULL);
51838 DUK_ASSERT(obj != NULL);
51840
51841 if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
51842 arr_idx != DUK__NO_ARRAY_INDEX &&
51843 flags == DUK_PROPDESC_FLAGS_WEC) {
51844 DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0); /* covered by comparison */
51845
51846 DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
51847
51848 /* always grow the array, no sparse / abandon support here */
51849 if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
51850 duk__grow_props_for_array_item(thr, obj, arr_idx);
51851 }
51852
51853 DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
51854 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
51855 tv2 = duk_require_tval(ctx, -1);
51856
51857 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
51858
51859 duk_pop(ctx); /* [ ...val ] -> [ ... ] */
51860 return;
51861 }
51862
51863 DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
51864
51865 duk_push_uint(ctx, (duk_uint_t) arr_idx);
51866 key = duk_to_hstring(ctx, -1);
51867 DUK_ASSERT(key != NULL);
51868 duk_insert(ctx, -2); /* [ ... val key ] -> [ ... key val ] */
51869
51870 duk_hobject_define_property_internal(thr, obj, key, flags);
51871
51872 duk_pop(ctx); /* [ ... key ] -> [ ... ] */
51873}
51874
51875/*
51876 * Internal helper for defining an accessor property, ignoring
51877 * normal semantics such as extensibility, write protection etc.
51878 * Overwrites any existing value and attributes. This is called
51879 * very rarely, so the implementation first sets a value to undefined
51880 * and then changes the entry to an accessor (this is to save code space).
51881 */
51882
51884 duk_context *ctx = (duk_context *) thr;
51885 duk_int_t e_idx;
51886 duk_int_t h_idx;
51887
51888 DUK_DDD(DUK_DDDPRINT("define new accessor (internal): thr=%p, obj=%!O, key=%!O, "
51889 "getter=%!O, setter=%!O, flags=0x%02lx",
51890 (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
51891 (duk_heaphdr *) getter, (duk_heaphdr *) setter,
51892 (unsigned long) propflags));
51893
51894 DUK_ASSERT(thr != NULL);
51895 DUK_ASSERT(thr->heap != NULL);
51896 DUK_ASSERT(obj != NULL);
51897 DUK_ASSERT(key != NULL);
51898 DUK_ASSERT((propflags & ~DUK_PROPDESC_FLAGS_MASK) == 0);
51899 /* setter and/or getter may be NULL */
51901
51903
51904 /* force the property to 'undefined' to create a slot for it */
51905 duk_push_undefined(ctx);
51906 duk_hobject_define_property_internal(thr, obj, key, propflags);
51907 duk_hobject_find_existing_entry(thr->heap, obj, key, &e_idx, &h_idx);
51908 DUK_DDD(DUK_DDDPRINT("accessor slot: e_idx=%ld, h_idx=%ld", (long) e_idx, (long) h_idx));
51909 DUK_ASSERT(e_idx >= 0);
51910 DUK_ASSERT((duk_uint32_t) e_idx < DUK_HOBJECT_GET_ENEXT(obj));
51911
51912 /* no need to decref, as previous value is 'undefined' */
51913 DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, e_idx);
51914 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, getter);
51915 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, setter);
51916 DUK_HOBJECT_INCREF_ALLOWNULL(thr, getter);
51917 DUK_HOBJECT_INCREF_ALLOWNULL(thr, setter);
51918}
51919
51920/*
51921 * Internal helpers for managing object 'length'
51923
51924/* XXX: awkward helpers */
51925
51926DUK_INTERNAL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length) {
51927 duk_context *ctx = (duk_context *) thr;
51928 duk_push_hobject(ctx, obj);
51930 duk_push_u32(ctx, length);
51931 (void) duk_hobject_putprop(thr,
51932 DUK_GET_TVAL_NEGIDX(ctx, -3),
51933 DUK_GET_TVAL_NEGIDX(ctx, -2),
51934 DUK_GET_TVAL_NEGIDX(ctx, -1),
51935 0);
51936 duk_pop_n(ctx, 3);
51937}
51938
51940 duk_hobject_set_length(thr, obj, 0);
51941}
51942
51944 duk_context *ctx = (duk_context *) thr;
51945 duk_double_t val;
51946 duk_push_hobject(ctx, obj);
51949 DUK_GET_TVAL_NEGIDX(ctx, -2),
51950 DUK_GET_TVAL_NEGIDX(ctx, -1));
51951 val = duk_to_number(ctx, -1);
51952 duk_pop_n(ctx, 3);
51953 if (val >= 0.0 && val < DUK_DOUBLE_2TO32) {
51954 return (duk_uint32_t) val;
51955 }
51956 return 0;
51957}
51958
51959/*
51960 * Object.getOwnPropertyDescriptor() (E5 Sections 15.2.3.3, 8.10.4)
51961 *
51962 * This is an actual function call.
51963 */
51964
51966 duk_hthread *thr = (duk_hthread *) ctx;
51967 duk_hobject *obj;
51968 duk_hstring *key;
51969 duk_propdesc pd;
51970 duk_bool_t rc;
51971
51972 DUK_ASSERT(ctx != NULL);
51973 DUK_ASSERT(thr != NULL);
51974 DUK_ASSERT(thr->heap != NULL);
51975
51977 (void) duk_to_string(ctx, 1);
51978 key = duk_require_hstring(ctx, 1);
51979
51980 DUK_ASSERT(obj != NULL);
51981 DUK_ASSERT(key != NULL);
51982
51984
51986 if (!rc) {
51987 duk_push_undefined(ctx);
51988
51989 /* [obj key undefined] */
51990 return 1;
51991 }
51992
51993 duk_push_object(ctx);
51994
51995 /* [obj key value desc] */
51996
51997 if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
51998 /* If a setter/getter is missing (undefined), the descriptor must
51999 * still have the property present with the value 'undefined'.
52000 */
52001 if (pd.get) {
52002 duk_push_hobject(ctx, pd.get);
52003 } else {
52004 duk_push_undefined(ctx);
52005 }
52007 if (pd.set) {
52008 duk_push_hobject(ctx, pd.set);
52009 } else {
52010 duk_push_undefined(ctx);
52011 }
52013 } else {
52014 duk_dup(ctx, -2); /* [obj key value desc value] */
52018
52019 /* [obj key value desc] */
52020 }
52025
52026 /* [obj key value desc] */
52027 return 1;
52028}
52030/*
52031 * NormalizePropertyDescriptor() related helper.
52032 *
52033 * Internal helper which validates and normalizes a property descriptor
52034 * represented as an Ecmascript object (e.g. argument to defineProperty()).
52035 * The output of this conversion is a set of defprop_flags and possibly
52036 * some values pushed on the value stack; some subset of: property value,
52037 * getter, setter. Caller must manage stack top carefully because the
52038 * number of values pushed depends on the input property descriptor.
52039 *
52040 * The original descriptor object must not be altered in the process.
52041 */
52042
52043/* XXX: very basic optimization -> duk_get_prop_stridx_top */
52044
52047 duk_idx_t idx_in,
52048 duk_uint_t *out_defprop_flags,
52049 duk_idx_t *out_idx_value,
52050 duk_hobject **out_getter,
52051 duk_hobject **out_setter) {
52052 duk_hthread *thr = (duk_hthread *) ctx;
52053 duk_idx_t idx_value = -1;
52054 duk_hobject *getter = NULL;
52055 duk_hobject *setter = NULL;
52056 duk_bool_t is_data_desc = 0;
52057 duk_bool_t is_acc_desc = 0;
52058 duk_uint_t defprop_flags = 0;
52059
52060 DUK_ASSERT(ctx != NULL);
52061 DUK_ASSERT(out_defprop_flags != NULL);
52062 DUK_ASSERT(out_idx_value != NULL);
52063 DUK_ASSERT(out_getter != NULL);
52064 DUK_ASSERT(out_setter != NULL);
52065
52066 /* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
52067 idx_in = duk_require_normalize_index(ctx, idx_in);
52068 (void) duk_require_hobject(ctx, idx_in);
52069
52070 /* The coercion order must match the ToPropertyDescriptor() algorithm
52071 * so that side effects in coercion happen in the correct order.
52072 * (This order also happens to be compatible with duk_def_prop(),
52073 * although it doesn't matter in practice.)
52074 */
52075
52076 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_VALUE)) {
52077 is_data_desc = 1;
52078 defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
52079 idx_value = duk_get_top_index(ctx);
52080 /* Leave 'value' on stack */
52081 } else {
52082 duk_pop(ctx);
52083 }
52084
52085 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_WRITABLE)) {
52086 is_data_desc = 1;
52087 if (duk_to_boolean(ctx, -1)) {
52089 } else {
52090 defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
52091 }
52092 }
52093 duk_pop(ctx);
52094
52095 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_GET)) {
52096 duk_tval *tv = duk_require_tval(ctx, -1);
52097 duk_hobject *h_get;
52098
52099 if (DUK_TVAL_IS_UNDEFINED(tv)) {
52100 /* undefined is accepted */
52101 DUK_ASSERT(getter == NULL);
52102 } else {
52103 /* NOTE: lightfuncs are coerced to full functions because
52104 * lightfuncs don't fit into a property value slot. This
52105 * has some side effects, see test-dev-lightfunc-accessor.js.
52106 */
52107 h_get = duk_get_hobject_or_lfunc_coerce(ctx, -1);
52108 if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
52109 goto type_error;
52110 }
52111 getter = h_get;
52112 }
52113 is_acc_desc = 1;
52114 defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
52115 /* Leave 'getter' on stack */
52116 } else {
52117 duk_pop(ctx);
52118 }
52119
52120 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_SET)) {
52121 duk_tval *tv = duk_require_tval(ctx, -1);
52122 duk_hobject *h_set;
52123
52124 if (DUK_TVAL_IS_UNDEFINED(tv)) {
52125 /* undefined is accepted */
52126 DUK_ASSERT(setter == NULL);
52127 } else {
52128 /* NOTE: lightfuncs are coerced to full functions because
52129 * lightfuncs don't fit into a property value slot. This
52130 * has some side effects, see test-dev-lightfunc-accessor.js.
52131 */
52132 h_set = duk_get_hobject_or_lfunc_coerce(ctx, -1);
52133 if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
52134 goto type_error;
52135 }
52136 setter = h_set;
52137 }
52138 is_acc_desc = 1;
52139 defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
52140 /* Leave 'setter' on stack */
52141 } else {
52142 duk_pop(ctx);
52143 }
52144
52145 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_ENUMERABLE)) {
52146 if (duk_to_boolean(ctx, -1)) {
52148 } else {
52149 defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
52150 }
52151 }
52152 duk_pop(ctx);
52153
52154 if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_CONFIGURABLE)) {
52155 if (duk_to_boolean(ctx, -1)) {
52157 } else {
52158 defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
52159 }
52160 }
52161 duk_pop(ctx);
52162
52163 if (is_data_desc && is_acc_desc) {
52164 goto type_error;
52165 }
52166
52167 *out_defprop_flags = defprop_flags;
52168 *out_idx_value = idx_value;
52169 *out_getter = getter;
52170 *out_setter = setter;
52171
52172 /* [ ... value? getter? setter? ] */
52173 return;
52174
52175 type_error:
52177}
52178
52179/*
52180 * Object.defineProperty() related helper (E5 Section 15.2.3.6)
52181 *
52182 * Inlines all [[DefineOwnProperty]] exotic behaviors.
52183 *
52184 * Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
52185 * implemented directly, but Object.defineProperty() serves its purpose.
52186 * We don't need the [[DefineOwnProperty]] internally and we don't have a
52187 * property descriptor with 'missing values' so it's easier to avoid it
52188 * entirely.
52189 *
52190 * Note: this is only called for actual objects, not primitive values.
52191 * This must support virtual properties for full objects (e.g. Strings)
52192 * but not for plain values (e.g. strings). Lightfuncs, even though
52193 * primitive in a sense, are treated like objects and accepted as target
52194 * values.
52195 */
52196
52197/* XXX: this is a major target for size optimization */
52200 duk_uint_t defprop_flags,
52201 duk_hobject *obj,
52202 duk_hstring *key,
52203 duk_idx_t idx_value,
52204 duk_hobject *get,
52205 duk_hobject *set) {
52206 duk_hthread *thr = (duk_hthread *) ctx;
52207 duk_uint32_t arr_idx;
52208 duk_tval tv;
52209 duk_bool_t has_enumerable;
52210 duk_bool_t has_configurable;
52211 duk_bool_t has_writable;
52212 duk_bool_t has_value;
52213 duk_bool_t has_get;
52214 duk_bool_t has_set;
52215 duk_bool_t is_enumerable;
52216 duk_bool_t is_configurable;
52217 duk_bool_t is_writable;
52218 duk_bool_t throw_flag;
52219 duk_bool_t force_flag;
52220 duk_small_uint_t new_flags;
52221 duk_propdesc curr;
52222 duk_uint32_t arridx_new_array_length; /* != 0 => post-update for array 'length' (used when key is an array index) */
52223 duk_uint32_t arrlen_old_len;
52224 duk_uint32_t arrlen_new_len;
52225 duk_bool_t pending_write_protect;
52226
52227 DUK_ASSERT(thr != NULL);
52228 DUK_ASSERT(thr->heap != NULL);
52229 DUK_ASSERT(ctx != NULL);
52230 DUK_ASSERT(obj != NULL);
52231 DUK_ASSERT(key != NULL);
52232 /* idx_value may be < 0 (no value), set and get may be NULL */
52233
52235
52236 /* All the flags fit in 16 bits, so will fit into duk_bool_t. */
52237
52238 has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
52239 has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
52240 has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
52241 has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
52242 has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
52243 has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
52244 is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
52245 is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
52246 is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
52247 throw_flag = 1; /* Object.defineProperty() calls [[DefineOwnProperty]] with Throw=true */
52248 force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
52249
52250 arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
52251
52252 arridx_new_array_length = 0;
52253 pending_write_protect = 0;
52254 arrlen_old_len = 0;
52255 arrlen_new_len = 0;
52256
52257 DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
52258 "has_configurable=%ld is_configurable=%ld "
52259 "has_writable=%ld is_writable=%ld "
52260 "has_value=%ld value=%!T "
52261 "has_get=%ld get=%p=%!O "
52262 "has_set=%ld set=%p=%!O "
52263 "arr_idx=%ld",
52264 (long) has_enumerable, (long) is_enumerable,
52265 (long) has_configurable, (long) is_configurable,
52266 (long) has_writable, (long) is_writable,
52267 (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(ctx, idx_value) : NULL),
52268 (long) has_get, (void *) get, (duk_heaphdr *) get,
52269 (long) has_set, (void *) set, (duk_heaphdr *) set,
52270 (long) arr_idx));
52271
52272 /*
52273 * Array exotic behaviors can be implemented at this point. The local variables
52274 * are essentially a 'value copy' of the input descriptor (Desc), which is modified
52275 * by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
52276 */
52277
52278 if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
52279 goto skip_array_exotic;
52280 }
52281
52282 if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
52283 /* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
52284 if (!has_value) {
52285 DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
52286 goto skip_array_exotic;
52287 }
52288
52289 DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
52290
52291 /*
52292 * Get old and new length
52293 */
52294
52295 /* Note: reuse 'curr' as a temp propdesc */
52296 arrlen_old_len = duk__get_old_array_length(thr, obj, &curr);
52297
52298 duk_dup(ctx, idx_value);
52299 arrlen_new_len = duk__to_new_array_length_checked(thr);
52300 duk_push_u32(ctx, arrlen_new_len);
52301 duk_replace(ctx, idx_value); /* step 3.e: replace 'Desc.[[Value]]' */
52302
52303 DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
52304
52305 if (arrlen_new_len >= arrlen_old_len) {
52306 /* standard behavior, step 3.f.i */
52307 DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
52308 goto skip_array_exotic;
52309 }
52310 DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
52311
52312 /* XXX: consolidated algorithm step 15.f -> redundant? */
52313 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && !force_flag) {
52314 /* Note: 'curr' refers to 'length' propdesc */
52315 goto fail_not_writable_array_length;
52316 }
52317
52318 /* steps 3.h and 3.i */
52319 if (has_writable && !is_writable) {
52320 DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
52321 is_writable = 1;
52322 pending_write_protect = 1;
52323 }
52324
52325 /* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
52326 } else if (arr_idx != DUK__NO_ARRAY_INDEX) {
52327 /* XXX: any chance of unifying this with the 'length' key handling? */
52328
52329 /* E5 Section 15.4.5.1, step 4 */
52330 duk_uint32_t old_len;
52331
52332 /* Note: use 'curr' as a temp propdesc */
52333 old_len = duk__get_old_array_length(thr, obj, &curr);
52334
52335 if (arr_idx >= old_len) {
52336 DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
52337 "(arr_idx=%ld, old_len=%ld)",
52338 (long) arr_idx, (long) old_len));
52339
52340 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
52341 /* Note: 'curr' refers to 'length' propdesc */
52342 goto fail_not_writable_array_length;
52343 }
52344
52345 /* actual update happens once write has been completed without
52346 * error below.
52347 */
52348 DUK_ASSERT(arr_idx != 0xffffffffUL);
52349 arridx_new_array_length = arr_idx + 1;
52350 } else {
52351 DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
52352 "(arr_idx=%ld, old_len=%ld) -> standard behavior",
52353 (long) arr_idx, (long) old_len));
52354 }
52355 }
52356 skip_array_exotic:
52357
52358 /* XXX: There is currently no support for writing buffer object
52359 * indexed elements here. Attempt to do so will succeed and
52360 * write a concrete property into the buffer object. This should
52361 * be fixed at some point but because buffers are a custom feature
52362 * anyway, this is relatively unimportant.
52363 */
52364
52365 /*
52366 * Actual Object.defineProperty() default algorithm.
52367 */
52368
52369 /*
52370 * First check whether property exists; if not, simple case. This covers
52371 * steps 1-4.
52372 */
52373
52374 if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
52375 DUK_DDD(DUK_DDDPRINT("property does not exist"));
52376
52377 if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
52378 goto fail_not_extensible;
52379 }
52380
52381 /* XXX: share final setting code for value and flags? difficult because
52382 * refcount code is different. Share entry allocation? But can't allocate
52383 * until array index checked.
52384 */
52385
52386 /* steps 4.a and 4.b are tricky */
52387 if (has_set || has_get) {
52388 duk_int_t e_idx;
52389
52390 DUK_DDD(DUK_DDDPRINT("create new accessor property"));
52391
52392 DUK_ASSERT(has_set || set == NULL);
52393 DUK_ASSERT(has_get || get == NULL);
52394 DUK_ASSERT(!has_value);
52395 DUK_ASSERT(!has_writable);
52396
52397 new_flags = DUK_PROPDESC_FLAG_ACCESSOR; /* defaults, E5 Section 8.6.1, Table 7 */
52398 if (has_enumerable && is_enumerable) {
52399 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52400 }
52401 if (has_configurable && is_configurable) {
52402 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52403 }
52404
52405 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
52406 DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
52408 }
52409
52410 /* write to entry part */
52411 e_idx = duk__alloc_entry_checked(thr, obj, key);
52412 DUK_ASSERT(e_idx >= 0);
52413
52414 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
52415 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
52418
52419 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
52420 goto success_exotics;
52421 } else {
52422 duk_int_t e_idx;
52423 duk_tval *tv2;
52424
52425 DUK_DDD(DUK_DDDPRINT("create new data property"));
52426
52427 DUK_ASSERT(!has_set);
52428 DUK_ASSERT(!has_get);
52429
52430 new_flags = 0; /* defaults, E5 Section 8.6.1, Table 7 */
52431 if (has_writable && is_writable) {
52432 new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
52433 }
52434 if (has_enumerable && is_enumerable) {
52435 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52436 }
52437 if (has_configurable && is_configurable) {
52438 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52439 }
52440 if (has_value) {
52441 duk_tval *tv_tmp = duk_require_tval(ctx, idx_value);
52442 DUK_TVAL_SET_TVAL(&tv, tv_tmp);
52443 } else {
52444 DUK_TVAL_SET_UNDEFINED(&tv); /* default value */
52445 }
52446
52447 if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
52448 if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
52449#if 0
52450 DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
52451 /* may become sparse...*/
52452#endif
52453 /* XXX: handling for array part missing now; this doesn't affect
52454 * compliance but causes array entry writes using defineProperty()
52455 * to always abandon array part.
52456 */
52457 }
52458 DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
52460 /* fall through */
52461 }
52462
52463 /* write to entry part */
52464 e_idx = duk__alloc_entry_checked(thr, obj, key);
52465 DUK_ASSERT(e_idx >= 0);
52466 tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
52467 DUK_TVAL_SET_TVAL(tv2, &tv);
52468 DUK_TVAL_INCREF(thr, tv2);
52469
52470 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
52471 goto success_exotics;
52472 }
52474 }
52475
52476 /* we currently assume virtual properties are not configurable (as none of them are) */
52477 DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
52478
52479 /* [obj key desc value get set curr_value] */
52480
52481 /*
52482 * Property already exists. Steps 5-6 detect whether any changes need
52483 * to be made.
52484 */
52485
52486 if (has_enumerable) {
52487 if (is_enumerable) {
52488 if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
52489 goto need_check;
52490 }
52491 } else {
52493 goto need_check;
52494 }
52495 }
52496 }
52497 if (has_configurable) {
52498 if (is_configurable) {
52499 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
52500 goto need_check;
52501 }
52502 } else {
52504 goto need_check;
52505 }
52506 }
52507 }
52508 if (has_value) {
52509 duk_tval *tmp1;
52510 duk_tval *tmp2;
52511
52512 /* attempt to change from accessor to data property */
52513 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52514 goto need_check;
52515 }
52516
52517 tmp1 = duk_require_tval(ctx, -1); /* curr value */
52518 tmp2 = duk_require_tval(ctx, idx_value); /* new value */
52519 if (!duk_js_samevalue(tmp1, tmp2)) {
52520 goto need_check;
52521 }
52522 }
52523 if (has_writable) {
52524 /* attempt to change from accessor to data property */
52525 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52526 goto need_check;
52527 }
52528
52529 if (is_writable) {
52530 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
52531 goto need_check;
52532 }
52533 } else {
52534 if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
52535 goto need_check;
52536 }
52537 }
52538 }
52539 if (has_set) {
52540 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52541 if (set != curr.set) {
52542 goto need_check;
52543 }
52544 } else {
52545 goto need_check;
52546 }
52547 }
52548 if (has_get) {
52549 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52550 if (get != curr.get) {
52551 goto need_check;
52552 }
52553 } else {
52554 goto need_check;
52555 }
52556 }
52557
52558 /* property exists, either 'desc' is empty, or all values
52559 * match (SameValue)
52560 */
52561 goto success_no_exotics;
52562
52563 need_check:
52564
52565 /*
52566 * Some change(s) need to be made. Steps 7-11.
52567 */
52568
52569 /* shared checks for all descriptor types */
52570 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52571 if (has_configurable && is_configurable) {
52572 goto fail_not_configurable;
52573 }
52574 if (has_enumerable) {
52576 if (!is_enumerable) {
52577 goto fail_not_configurable;
52578 }
52579 } else {
52580 if (is_enumerable) {
52581 goto fail_not_configurable;
52582 }
52583 }
52584 }
52585 }
52586
52587 /* Reject attempt to change virtual properties: not part of the
52588 * standard algorithm, applies currently to e.g. virtual index
52589 * properties of buffer objects (which are virtual but writable).
52590 * (Cannot "force" modification of a virtual property.)
52591 */
52592 if (curr.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
52593 goto fail_virtual;
52594 }
52595
52596 /* Reject attempt to change a read-only object. */
52597#if defined(DUK_USE_ROM_OBJECTS)
52599 DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
52600 goto fail_not_configurable;
52601 }
52602#endif
52603
52604 /* descriptor type specific checks */
52605 if (has_set || has_get) {
52606 /* IsAccessorDescriptor(desc) == true */
52607 DUK_ASSERT(!has_writable);
52608 DUK_ASSERT(!has_value);
52609
52610 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52611 /* curr and desc are accessors */
52612 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52613 if (has_set && set != curr.set) {
52614 goto fail_not_configurable;
52615 }
52616 if (has_get && get != curr.get) {
52617 goto fail_not_configurable;
52618 }
52619 }
52620 } else {
52621 duk_bool_t rc;
52622 duk_tval *tv1;
52623 duk_tval tv_tmp;
52624
52625 /* curr is data, desc is accessor */
52626 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52627 goto fail_not_configurable;
52628 }
52629
52630 DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
52631 if (curr.a_idx >= 0) {
52632 DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
52634 duk_pop(ctx); /* remove old value */
52635 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52636 DUK_UNREF(rc);
52637 DUK_ASSERT(rc != 0);
52638 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52639 }
52640
52642
52643 /* Avoid side effects that might disturb curr.e_idx until
52644 * we're done editing the slot.
52645 */
52646 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52647 DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
52649
52654
52655 DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
52656 (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
52657
52658 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
52659
52660 /* re-lookup to update curr.flags
52661 * XXX: would be faster to update directly
52662 */
52663 duk_pop(ctx); /* remove old value */
52664 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52665 DUK_UNREF(rc);
52666 DUK_ASSERT(rc != 0);
52667 }
52668 } else if (has_value || has_writable) {
52669 /* IsDataDescriptor(desc) == true */
52670 DUK_ASSERT(!has_set);
52671 DUK_ASSERT(!has_get);
52672
52673 if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52674 duk_bool_t rc;
52675 duk_hobject *h_get;
52676 duk_hobject *h_set;
52677
52678 /* curr is accessor, desc is data */
52679 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52680 goto fail_not_configurable;
52681 }
52682
52683 /* curr is accessor -> cannot be in array part */
52684 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52685
52686 DUK_DDD(DUK_DDDPRINT("convert property to data property"));
52687
52688 /* Avoid side effects that might disturb curr.e_idx until
52689 * we're done editing the slot.
52690 */
52692 h_get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
52694 h_set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
52696
52700
52701 DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
52702 (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
52703
52704 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_get); /* side effects */
52705 DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_set); /* side effects */
52706
52707 /* re-lookup to update curr.flags
52708 * XXX: would be faster to update directly
52709 */
52710 duk_pop(ctx); /* remove old value */
52711 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52712 DUK_UNREF(rc);
52713 DUK_ASSERT(rc != 0);
52714 } else {
52715 /* curr and desc are data */
52716 if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52717 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
52718 goto fail_not_configurable;
52719 }
52720 /* Note: changing from writable to non-writable is OK */
52721 if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
52722 duk_tval *tmp1 = duk_require_tval(ctx, -1); /* curr value */
52723 duk_tval *tmp2 = duk_require_tval(ctx, idx_value); /* new value */
52724 if (!duk_js_samevalue(tmp1, tmp2)) {
52725 goto fail_not_configurable;
52726 }
52727 }
52728 }
52729 }
52730 } else {
52731 /* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
52732 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
52733 * allowed at this point.
52734 */
52735
52736 DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
52737 }
52738
52739 /*
52740 * Start doing property attributes updates. Steps 12-13.
52741 *
52742 * Start by computing new attribute flags without writing yet.
52743 * Property type conversion is done above if necessary.
52744 */
52745
52746 new_flags = curr.flags;
52747
52748 if (has_enumerable) {
52749 if (is_enumerable) {
52750 new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52751 } else {
52752 new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
52753 }
52754 }
52755 if (has_configurable) {
52756 if (is_configurable) {
52757 new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52758 } else {
52759 new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
52760 }
52761 }
52762 if (has_writable) {
52763 if (is_writable) {
52764 new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
52765 } else {
52766 new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
52767 }
52768 }
52769
52770 /* XXX: write protect after flag? -> any chance of handling it here? */
52771
52772 DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
52773 (unsigned long) new_flags));
52774
52775 /*
52776 * Check whether we need to abandon an array part (if it exists)
52777 */
52778
52779 if (curr.a_idx >= 0) {
52780 duk_bool_t rc;
52781
52782 DUK_ASSERT(curr.e_idx < 0);
52783
52784 if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
52785 duk_tval *tv1, *tv2;
52786
52787 DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
52788
52789 DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC); /* must have been, since in array part */
52790 DUK_ASSERT(!has_set);
52791 DUK_ASSERT(!has_get);
52792
52793 tv2 = duk_require_tval(ctx, idx_value);
52794 tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
52795 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
52796 goto success_exotics;
52797 }
52798
52799 DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
52801 duk_pop(ctx); /* remove old value */
52802 rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52803 DUK_UNREF(rc);
52804 DUK_ASSERT(rc != 0);
52805 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52806 }
52807
52808 DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
52809
52810 /* array case is handled comprehensively above */
52811 DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52812
52813 DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
52814 DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
52815
52816 if (has_set) {
52817 duk_hobject *tmp;
52818
52819 DUK_DDD(DUK_DDDPRINT("update existing property setter"));
52821
52822 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
52823 DUK_UNREF(tmp);
52824 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
52826 DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects */
52827 }
52828 if (has_get) {
52829 duk_hobject *tmp;
52830
52831 DUK_DDD(DUK_DDDPRINT("update existing property getter"));
52833
52834 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
52835 DUK_UNREF(tmp);
52836 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
52838 DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects */
52839 }
52840 if (has_value) {
52841 duk_tval *tv1, *tv2;
52842
52843 DUK_DDD(DUK_DDDPRINT("update existing property value"));
52845
52846 tv2 = duk_require_tval(ctx, idx_value);
52847 tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52848 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
52849 }
52850
52851 /*
52852 * Standard algorithm succeeded without errors, check for exotic post-behaviors.
52853 *
52854 * Arguments exotic behavior in E5 Section 10.6 occurs after the standard
52855 * [[DefineOwnProperty]] has completed successfully.
52856 *
52857 * Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
52858 * prior to the default [[DefineOwnProperty]], but:
52859 * - for an array index key (e.g. "10") the final 'length' update occurs here
52860 * - for 'length' key the element deletion and 'length' update occurs here
52861 */
52862
52863 success_exotics:
52864
52865 /* [obj key desc value get set curr_value] */
52866
52868 if (arridx_new_array_length > 0) {
52869 duk_tval *tmp;
52870 duk_bool_t rc;
52871
52872 /*
52873 * Note: zero works as a "no update" marker because the new length
52874 * can never be zero after a new property is written.
52875 */
52876
52877 /* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
52878
52879 DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
52880 (long) arridx_new_array_length));
52881
52882 /* Note: reuse 'curr' */
52883 rc = duk__get_own_propdesc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &curr, 0 /*flags*/); /* don't push value */
52884 DUK_UNREF(rc);
52885 DUK_ASSERT(rc != 0);
52886 DUK_ASSERT(curr.e_idx >= 0);
52887
52888 tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52890 /* no need for decref/incref because value is a number */
52891 DUK_TVAL_SET_FASTINT_U32(tmp, arridx_new_array_length);
52892 }
52893 if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
52894 /*
52895 * E5 Section 15.4.5.1, steps 3.k - 3.n. The order at the end combines
52896 * the error case 3.l.iii and the success case 3.m-3.n.
52897 *
52898 * Note: 'length' is always in entries part, so no array abandon issues for
52899 * 'writable' update.
52900 */
52901
52902 /* XXX: investigate whether write protect can be handled above, if we
52903 * just update length here while ignoring its protected status
52904 */
52905
52906 duk_tval *tmp;
52907 duk_uint32_t result_len;
52908 duk_bool_t rc;
52909
52910 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
52911 "doing array element deletion and length update"));
52912
52913 rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
52914
52915 /* update length (curr points to length, and we assume it's still valid) */
52916 DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
52917
52918 DUK_ASSERT(curr.e_idx >= 0);
52920 tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52922 /* no decref needed for a number */
52923 DUK_TVAL_SET_FASTINT_U32(tmp, result_len);
52925
52926 if (pending_write_protect) {
52927 DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
52929 }
52930
52931 /*
52932 * XXX: shrink array allocation or entries compaction here?
52933 */
52934
52935 if (!rc) {
52936 goto fail_array_length_partial;
52937 }
52938 }
52939 } else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
52940 duk_hobject *map;
52941 duk_hobject *varenv;
52942
52943 DUK_ASSERT(arridx_new_array_length == 0);
52944 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)); /* traits are separate; in particular, arguments not an array */
52945
52946 map = NULL;
52947 varenv = NULL;
52948 if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
52949 goto success_no_exotics;
52950 }
52951 DUK_ASSERT(map != NULL);
52952 DUK_ASSERT(varenv != NULL);
52953
52954 /* [obj key desc value get set curr_value varname] */
52955
52956 if (has_set || has_get) {
52957 /* = IsAccessorDescriptor(Desc) */
52958 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
52959 "changed to an accessor, delete arguments binding"));
52960
52961 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
52962 } else {
52963 /* Note: this order matters (final value before deleting map entry must be done) */
52964 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
52965 "check for value update / binding deletion"));
52966
52967 if (has_value) {
52968 duk_hstring *varname;
52969
52970 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
52971 "update bound value (variable/argument)"));
52972
52973 varname = duk_require_hstring(ctx, -1);
52974 DUK_ASSERT(varname != NULL);
52975
52976 DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
52977 "key=%!O, varname=%!O, value=%!T",
52978 (duk_heaphdr *) key,
52979 (duk_heaphdr *) varname,
52980 (duk_tval *) duk_require_tval(ctx, idx_value)));
52981
52982 /* strict flag for putvar comes from our caller (currently: fixed) */
52983 duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, idx_value), throw_flag);
52984 }
52985 if (has_writable && !is_writable) {
52986 DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
52987 "changed to non-writable, delete arguments binding"));
52988
52989 (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
52990 }
52991 }
52992
52993 /* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
52994 * but this doesn't matter now.
52995 */
52996 }
52997
52998 success_no_exotics:
52999 return;
53000
53001 fail_virtual:
53003 return;
53004
53005 fail_not_writable_array_length:
53007 return;
53008
53009 fail_not_extensible:
53011 return;
53012
53013 fail_not_configurable:
53015 return;
53016
53017 fail_array_length_partial:
53019 return;
53020}
53021
53022/*
53023 * Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
53024 */
53025
53027 duk_hthread *thr = (duk_hthread *) ctx;
53028 duk_hstring *h_v;
53029 duk_hobject *h_obj;
53030 duk_propdesc desc;
53031 duk_bool_t ret;
53032
53033 /* coercion order matters */
53034 h_v = duk_to_hstring(ctx, 0);
53035 DUK_ASSERT(h_v != NULL);
53036
53038 DUK_ASSERT(h_obj != NULL);
53039
53040 ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/); /* don't push value */
53041
53042 duk_push_boolean(ctx, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
53043 return 1;
53045
53046/*
53047 * Object.seal() and Object.freeze() (E5 Sections 15.2.3.8 and 15.2.3.9)
53048 *
53049 * Since the algorithms are similar, a helper provides both functions.
53050 * Freezing is essentially sealing + making plain properties non-writable.
53051 *
53052 * Note: virtual (non-concrete) properties which are non-configurable but
53053 * writable would pose some problems, but such properties do not currently
53054 * exist (all virtual properties are non-configurable and non-writable).
53055 * If they did exist, the non-configurability does NOT prevent them from
53056 * becoming non-writable. However, this change should be recorded somehow
53057 * so that it would turn up (e.g. when getting the property descriptor),
53058 * requiring some additional flags in the object.
53059 */
53060
53063
53064 DUK_ASSERT(thr != NULL);
53065 DUK_ASSERT(thr->heap != NULL);
53066 DUK_ASSERT(obj != NULL);
53067
53069
53070#if defined(DUK_USE_ROM_OBJECTS)
53072 DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
53074 }
53075#endif
53076
53077 /*
53078 * Abandon array part because all properties must become non-configurable.
53079 * Note that this is now done regardless of whether this is always the case
53080 * (skips check, but performance problem if caller would do this many times
53081 * for the same object; not likely).
53082 */
53083
53086
53087 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
53088 duk_uint8_t *fp;
53089
53090 /* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
53091 DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
53092
53093 /* avoid multiple computations of flags address; bypasses macros */
53094 fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
53095 if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
53097 } else {
53098 *fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
53099 }
53100 }
53101
53103
53104 /* no need to compact since we already did that in duk__abandon_array_checked()
53105 * (regardless of whether an array part existed or not.
53106 */
53107
53108 return;
53109}
53110
53111/*
53112 * Object.isSealed() and Object.isFrozen() (E5 Sections 15.2.3.11, 15.2.3.13)
53113 *
53114 * Since the algorithms are similar, a helper provides both functions.
53115 * Freezing is essentially sealing + making plain properties non-writable.
53116 *
53117 * Note: all virtual (non-concrete) properties are currently non-configurable
53118 * and non-writable (and there are no accessor virtual properties), so they don't
53119 * need to be considered here now.
53120 */
53121
53124
53125 DUK_ASSERT(obj != NULL);
53126 DUK_UNREF(thr);
53127
53128 /* Note: no allocation pressure, no need to check refcounts etc */
53129
53130 /* must not be extensible */
53131 if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
53132 return 0;
53133 }
53134
53135 /* all virtual properties are non-configurable and non-writable */
53136
53137 /* entry part must not contain any configurable properties, or
53138 * writable properties (if is_frozen).
53139 */
53140 for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
53141 duk_small_uint_t flags;
53142
53143 if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
53144 continue;
53145 }
53146
53147 /* avoid multiple computations of flags address; bypasses macros */
53148 flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
53149
53150 if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
53151 return 0;
53152 }
53153 if (is_frozen &&
53154 !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
53155 (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
53156 return 0;
53157 }
53158 }
53159
53160 /* array part must not contain any non-unused properties, as they would
53161 * be configurable and writable.
53162 */
53163 for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
53164 duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
53165 if (!DUK_TVAL_IS_UNUSED(tv)) {
53166 return 0;
53167 }
53168 }
53169
53170 return 1;
53171}
53172
53173/*
53174 * Object.preventExtensions() and Object.isExtensible() (E5 Sections 15.2.3.10, 15.2.3.13)
53175 *
53176 * Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
53177 * and the Object built-in bindings.
53179
53180/* Undefine local defines */
53181
53182#undef DUK__NO_ARRAY_INDEX
53183#undef DUK__HASH_INITIAL
53184#undef DUK__HASH_PROBE_STEP
53185#undef DUK__HASH_UNUSED
53186#undef DUK__HASH_DELETED
53187#undef DUK__VALSTACK_SPACE
53188#line 1 "duk_hstring_misc.c"
53189/*
53190 * Misc support functions
53191 */
53192
53193/* include removed: duk_internal.h */
53194
53196 duk_uint32_t boff;
53197 const duk_uint8_t *p, *p_start, *p_end;
53199
53200 /* Caller must check character offset to be inside the string. */
53201 DUK_ASSERT(thr != NULL);
53202 DUK_ASSERT(h != NULL);
53203 DUK_ASSERT_DISABLE(pos >= 0); /* unsigned */
53205
53206 boff = duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
53207 DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
53208 (long) pos, (long) boff, (duk_heaphdr *) h));
53209 DUK_ASSERT_DISABLE(boff >= 0);
53211
53212 p_start = DUK_HSTRING_GET_DATA(h);
53213 p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
53214 p = p_start + boff;
53215 DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
53216 (const void *) p_start, (const void *) p_end,
53217 (const void *) p));
53218
53219 /* This may throw an error though not for valid E5 strings. */
53220 cp = duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
53221 return cp;
53222}
53223
53224#if !defined(DUK_USE_HSTRING_CLEN)
53226 if (DUK_HSTRING_HAS_ASCII(h)) {
53227 /* Most practical strings will go here. */
53228 return DUK_HSTRING_GET_BYTELEN(h);
53229 } else {
53231 }
53232}
53233#endif /* !DUK_USE_HSTRING_CLEN */
53234#line 1 "duk_hthread_alloc.c"
53235/*
53236 * duk_hthread allocation and freeing.
53237 */
53238
53239/* include removed: duk_internal.h */
53240
53241/*
53242 * Allocate initial stacks for a thread. Note that 'thr' must be reachable
53243 * as a garbage collection may be triggered by the allocation attempts.
53244 * Returns zero (without leaking memory) if init fails.
53245 */
53246
53248 duk_size_t alloc_size;
53249 duk_size_t i;
53250
53251 DUK_ASSERT(heap != NULL);
53252 DUK_ASSERT(thr != NULL);
53253 DUK_ASSERT(thr->valstack == NULL);
53254 DUK_ASSERT(thr->valstack_end == NULL);
53256 DUK_ASSERT(thr->valstack_top == NULL);
53257 DUK_ASSERT(thr->callstack == NULL);
53258 DUK_ASSERT(thr->catchstack == NULL);
53259
53260 /* valstack */
53261 alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
53262 thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
53263 if (!thr->valstack) {
53264 goto fail;
53265 }
53266 DUK_MEMZERO(thr->valstack, alloc_size);
53268#if !defined(DUK_USE_PREFER_SIZE)
53270#endif
53271 thr->valstack_bottom = thr->valstack;
53272 thr->valstack_top = thr->valstack;
53273
53274 for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
53276 }
53277
53278 /* callstack */
53279 alloc_size = sizeof(duk_activation) * DUK_CALLSTACK_INITIAL_SIZE;
53280 thr->callstack = (duk_activation *) DUK_ALLOC(heap, alloc_size);
53281 if (!thr->callstack) {
53282 goto fail;
53283 }
53284 DUK_MEMZERO(thr->callstack, alloc_size);
53286 DUK_ASSERT(thr->callstack_top == 0);
53287
53288 /* catchstack */
53289 alloc_size = sizeof(duk_catcher) * DUK_CATCHSTACK_INITIAL_SIZE;
53290 thr->catchstack = (duk_catcher *) DUK_ALLOC(heap, alloc_size);
53291 if (!thr->catchstack) {
53292 goto fail;
53293 }
53294 DUK_MEMZERO(thr->catchstack, alloc_size);
53297
53298 return 1;
53299
53300 fail:
53301 DUK_FREE(heap, thr->valstack);
53302 DUK_FREE(heap, thr->callstack);
53303 DUK_FREE(heap, thr->catchstack);
53304
53305 thr->valstack = NULL;
53306 thr->callstack = NULL;
53307 thr->catchstack = NULL;
53308 return 0;
53309}
53310
53311/* For indirect allocs. */
53312
53313DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
53314 duk_hthread *thr = (duk_hthread *) ud;
53315 DUK_UNREF(heap);
53316 return (void *) thr->valstack;
53317}
53318
53320 duk_hthread *thr = (duk_hthread *) ud;
53321 DUK_UNREF(heap);
53322 return (void *) thr->callstack;
53323}
53324
53328 return (void *) thr->catchstack;
53330#line 1 "duk_hthread_builtins.c"
53332 * Initialize built-in objects. Current thread must have a valstack
53333 * and initialization errors may longjmp, so a setjmp() catch point
53334 * must exist.
53337/* include removed: duk_internal.h */
53339/*
53340 * Encoding constants, must match genbuiltins.py
53343#define DUK__CLASS_BITS 5
53344#define DUK__BIDX_BITS 7
53345#define DUK__STRIDX_BITS 9 /* XXX: try to optimize to 8 (would now be possible, <200 used) */
53346#define DUK__NATIDX_BITS 8
53347#define DUK__NUM_NORMAL_PROPS_BITS 6
53348#define DUK__NUM_FUNC_PROPS_BITS 6
53349#define DUK__PROP_FLAGS_BITS 3
53350#define DUK__STRING_LENGTH_BITS 8
53351#define DUK__STRING_CHAR_BITS 7
53352#define DUK__LENGTH_PROP_BITS 3
53353#define DUK__NARGS_BITS 3
53354#define DUK__PROP_TYPE_BITS 3
53355#define DUK__MAGIC_BITS 16
53356
53357#define DUK__NARGS_VARARGS_MARKER 0x07
53358#define DUK__NO_CLASS_MARKER 0x00 /* 0 = DUK_HOBJECT_CLASS_UNUSED */
53359#define DUK__NO_BIDX_MARKER 0x7f
53360#define DUK__NO_STRIDX_MARKER 0xff
53361
53362#define DUK__PROP_TYPE_DOUBLE 0
53363#define DUK__PROP_TYPE_STRING 1
53364#define DUK__PROP_TYPE_STRIDX 2
53365#define DUK__PROP_TYPE_BUILTIN 3
53366#define DUK__PROP_TYPE_UNDEFINED 4
53367#define DUK__PROP_TYPE_BOOLEAN_TRUE 5
53368#define DUK__PROP_TYPE_BOOLEAN_FALSE 6
53369#define DUK__PROP_TYPE_ACCESSOR 7
53370
53371/*
53372 * Create built-in objects by parsing an init bitstream generated
53373 * by genbuiltins.py.
53374 */
53375
53376#if defined(DUK_USE_ROM_OBJECTS)
53377#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
53378DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
53379 duk_context *ctx;
53380 duk_hobject *h1;
53381#if defined(DUK_USE_ROM_GLOBAL_CLONE)
53382 duk_hobject *h2;
53383 duk_uint8_t *props;
53384 duk_size_t alloc_size;
53385#endif
53386
53387 ctx = (duk_context *) thr;
53388
53389 /* XXX: refactor into internal helper, duk_clone_hobject() */
53390
53391#if defined(DUK_USE_ROM_GLOBAL_INHERIT)
53392 /* Inherit from ROM-based global object: less RAM usage, less transparent. */
53397 h1 = duk_get_hobject(ctx, -1);
53398 DUK_ASSERT(h1 != NULL);
53399#elif defined(DUK_USE_ROM_GLOBAL_CLONE)
53400 /* Clone the properties of the ROM-based global object to create a
53401 * fully RAM-based global object. Uses more memory than the inherit
53402 * model but more compliant.
53403 */
53408 h1 = duk_get_hobject(ctx, -1);
53409 DUK_ASSERT(h1 != NULL);
53410 h2 = thr->builtins[DUK_BIDX_GLOBAL];
53411 DUK_ASSERT(h2 != NULL);
53412
53413 /* Copy the property table verbatim; this handles attributes etc.
53414 * For ROM objects it's not necessary (or possible) to update
53415 * refcounts so leave them as is.
53416 */
53417 alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h2);
53418 DUK_ASSERT(alloc_size > 0);
53419 props = DUK_ALLOC(thr->heap, alloc_size);
53420 if (!props) {
53422 return;
53423 }
53425 DUK_MEMCPY((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h2), alloc_size);
53426
53427 /* XXX: keep property attributes or tweak them here?
53428 * Properties will now be non-configurable even when they're
53429 * normally configurable for the global object.
53430 */
53431
53433 DUK_HOBJECT_SET_PROPS(thr->heap, h1, props);
53438#else
53439#error internal error in defines
53440#endif
53441
53445 thr->builtins[DUK_BIDX_GLOBAL] = h1;
53446 DUK_HOBJECT_INCREF(thr, h1);
53447 DUK_D(DUK_DPRINT("duplicated global object: %!O", h1));
53448
53449
53450 /* Create a fresh object environment for the global scope. This is
53451 * needed so that the global scope points to the newly created RAM-based
53452 * global object.
53453 */
53457 -1); /* no prototype */
53458 h1 = duk_get_hobject(ctx, -1);
53459 DUK_ASSERT(h1 != NULL);
53460 duk_dup(ctx, -2);
53461 duk_dup(ctx, -1); /* -> [ ... new_global new_globalenv new_global new_global ] */
53463 duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); /* always provideThis=true */
53464
53468 thr->builtins[DUK_BIDX_GLOBAL_ENV] = h1;
53469 DUK_HOBJECT_INCREF(thr, h1);
53470 DUK_D(DUK_DPRINT("duplicated global env: %!O", h1));
53471
53472 duk_pop_2(ctx);
53473}
53474#endif /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
53475
53477 /* Setup builtins from ROM objects. All heaps/threads will share
53478 * the same readonly objects.
53479 */
53481
53482 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53483 duk_hobject *h;
53484 h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
53485 DUK_ASSERT(h != NULL);
53486 thr->builtins[i] = h;
53487 }
53488
53489#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
53490 /* By default the global object is read-only which is often much
53491 * more of an issue than having read-only built-in objects (like
53492 * RegExp, Date, etc). Use a RAM-based copy of the global object
53493 * and the global environment object for convenience.
53494 */
53495 duk__duplicate_ram_global_object(thr);
53496#endif
53497}
53498#else /* DUK_USE_ROM_OBJECTS */
53501
53510 duk_uint8_t *p;
53511
53513 p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, n);
53514 for (i = 0; i < n; i++) {
53515 *p++ = (duk_uint8_t) duk_bd_decode(bd, DUK__STRING_CHAR_BITS);
53516 }
53517 duk_to_string(ctx, -1);
53518}
53520 if (duk_bd_decode_flag(bd)) {
53521 duk__push_string(ctx, bd);
53522 } else {
53524 }
53525}
53529
53530 for (i = 0; i < 8; i++) {
53531 /* Encoding endianness must match target memory layout,
53532 * build scripts and genbuiltins.py must ensure this.
53533 */
53534 du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
53535 }
53536
53537 duk_push_number(ctx, du.d); /* push operation normalizes NaNs */
53538}
53539
53541 duk_context *ctx = (duk_context *) thr;
53542 duk_bitdecoder_ctx bd_ctx;
53543 duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
53544 duk_hobject *h;
53545 duk_small_uint_t i, j;
53546
53547 DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
53548
53549 DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
53550 bd->data = (const duk_uint8_t *) duk_builtins_data;
53551 bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
53552
53553 /*
53554 * First create all built-in bare objects on the empty valstack.
53555 *
53556 * Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
53557 * stack indices matching their eventual thr->builtins[] index.
53558 *
53559 * Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
53560 * will exist on the value stack during init but won't be placed
53561 * into thr->builtins[]. These are objects referenced in some way
53562 * from thr->builtins[] roots but which don't need to be indexed by
53563 * Duktape through thr->builtins[] (e.g. user custom objects).
53564 */
53565
53567
53568 DUK_DD(DUK_DDPRINT("create empty built-ins"));
53569 DUK_ASSERT_TOP(ctx, 0);
53570 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
53571 duk_small_uint_t class_num;
53572 duk_small_int_t len = -1; /* must be signed */
53573
53575 len = (duk_small_int_t) duk_bd_decode_flagged(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
53576
53577 if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
53578 duk_small_uint_t natidx;
53579 duk_int_t c_nargs; /* must hold DUK_VARARGS */
53580 duk_c_function c_func;
53581 duk_int16_t magic;
53582
53583 DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
53584 DUK_ASSERT(len >= 0);
53585
53587 c_func = duk_bi_native_functions[natidx];
53588
53589 c_nargs = (duk_small_uint_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, len /*def_value*/);
53590 if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
53591 c_nargs = DUK_VARARGS;
53592 }
53593
53594 /* XXX: set magic directly here? (it could share the c_nargs arg) */
53595 duk_push_c_function_noexotic(ctx, c_func, c_nargs);
53596
53597 h = duk_require_hobject(ctx, -1);
53598 DUK_ASSERT(h != NULL);
53599
53600 /* Currently all built-in native functions are strict.
53601 * duk_push_c_function() now sets strict flag, so
53602 * assert for it.
53603 */
53605
53606 /* XXX: function properties */
53607
53608 /* Built-in 'name' is not writable by default. Function '.name'
53609 * is writable to allow user code to set a '.name' on a native
53610 * function.
53611 */
53614 -2,
53618
53619 /* Almost all global level Function objects are constructable
53620 * but not all: Function.prototype is a non-constructable,
53621 * callable Function.
53622 */
53623 if (duk_bd_decode_flag(bd)) {
53625 } else {
53627 }
53628
53629 /* Cast converts magic to 16-bit signed value */
53630 magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0 /*def_value*/);
53631 ((duk_hnativefunction *) h)->magic = magic;
53632 } else {
53633 /* XXX: ARRAY_PART for Array prototype? */
53634
53637 -1); /* no prototype or class yet */
53638
53639 h = duk_require_hobject(ctx, -1);
53640 DUK_ASSERT(h != NULL);
53641 }
53642
53643 DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
53644
53645 if (i < DUK_NUM_BUILTINS) {
53646 thr->builtins[i] = h;
53647 DUK_HOBJECT_INCREF(thr, &h->hdr);
53648 }
53649
53650 if (len >= 0) {
53651 /*
53652 * For top-level objects, 'length' property has the following
53653 * default attributes: non-writable, non-enumerable, non-configurable
53654 * (E5 Section 15).
53655 *
53656 * However, 'length' property for Array.prototype has attributes
53657 * expected of an Array instance which are different: writable,
53658 * non-enumerable, non-configurable (E5 Section 15.4.5.2).
53659 *
53660 * This is currently determined implicitly based on class; there are
53661 * no attribute flags in the init data.
53662 */
53663
53664 duk_push_int(ctx, len);
53666 -2,
53668 (class_num == DUK_HOBJECT_CLASS_ARRAY ? /* only Array.prototype matches */
53670 }
53671
53672 /* enable exotic behaviors last */
53673
53674 if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
53676 }
53677 if (class_num == DUK_HOBJECT_CLASS_STRING) {
53679 }
53680
53681 /* some assertions */
53682
53684 /* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
53687 /* DUK_HOBJECT_FLAG_NATIVEFUNCTION varies */
53689 DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h)); /* currently, even for Array.prototype */
53690 /* DUK_HOBJECT_FLAG_STRICT varies */
53691 DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(h) || /* all native functions have NEWENV */
53696 /* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
53697 /* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
53699
53700 DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
53701 }
53702
53703 /*
53704 * Then decode the builtins init data (see genbuiltins.py) to
53705 * init objects
53706 */
53707
53708 DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
53709 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
53711 duk_small_uint_t num;
53712
53713 DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
53714 h = duk_require_hobject(ctx, i);
53715 DUK_ASSERT(h != NULL);
53716
53718 if (t != DUK__NO_BIDX_MARKER) {
53719 DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
53721 }
53722
53724 if (t != DUK__NO_BIDX_MARKER) {
53725 /* 'prototype' property for all built-in objects (which have it) has attributes:
53726 * [[Writable]] = false,
53727 * [[Enumerable]] = false,
53728 * [[Configurable]] = false
53729 */
53730 DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
53732 }
53733
53735 if (t != DUK__NO_BIDX_MARKER) {
53736 /* 'constructor' property for all built-in objects (which have it) has attributes:
53737 * [[Writable]] = true,
53738 * [[Enumerable]] = false,
53739 * [[Configurable]] = true
53740 */
53741 DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
53743 }
53744
53745 /* normal valued properties */
53747 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
53748 for (j = 0; j < num; j++) {
53749 duk_small_uint_t prop_flags;
53750
53752
53753 /*
53754 * Property attribute defaults are defined in E5 Section 15 (first
53755 * few pages); there is a default for all properties and a special
53756 * default for 'length' properties. Variation from the defaults is
53757 * signaled using a single flag bit in the bitstream.
53758 */
53759
53760 if (duk_bd_decode_flag(bd)) {
53762 } else {
53763 prop_flags = DUK_PROPDESC_FLAGS_WC;
53764 }
53765
53767
53768 DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
53769 (long) i, (long) j, duk_get_tval(ctx, -1), (unsigned long) prop_flags, (long) t));
53770
53771 switch (t) {
53772 case DUK__PROP_TYPE_DOUBLE: {
53773 duk__push_double(ctx, bd);
53774 break;
53775 }
53776 case DUK__PROP_TYPE_STRING: {
53777 duk__push_string(ctx, bd);
53778 break;
53779 }
53780 case DUK__PROP_TYPE_STRIDX: {
53781 duk__push_stridx(ctx, bd);
53782 break;
53783 }
53785 duk_small_uint_t bidx;
53786
53789 duk_dup(ctx, (duk_idx_t) bidx);
53790 break;
53791 }
53793 duk_push_undefined(ctx);
53794 break;
53795 }
53797 duk_push_true(ctx);
53798 break;
53799 }
53801 duk_push_false(ctx);
53802 break;
53803 }
53807 duk_c_function c_func_getter;
53808 duk_c_function c_func_setter;
53809
53810 /* XXX: this is a bit awkward because there is no exposed helper
53811 * in the API style, only this internal helper.
53812 */
53813 DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
53814 (long) i, duk_get_tval(ctx, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) prop_flags));
53815
53816 c_func_getter = duk_bi_native_functions[natidx_getter];
53817 c_func_setter = duk_bi_native_functions[natidx_setter];
53818 duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0); /* always 0 args */
53819 duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1); /* always 1 arg */
53820
53821 /* XXX: magic for getter/setter? use duk_def_prop()? */
53822
53823 DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0); /* genbuiltins.py ensures */
53824
53825 prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR; /* accessor flag not encoded explicitly */
53827 duk_require_hobject(ctx, i),
53828 duk_get_hstring(ctx, -3),
53829 duk_require_hobject(ctx, -2),
53830 duk_require_hobject(ctx, -1),
53831 prop_flags);
53832 duk_pop_3(ctx); /* key, getter and setter, now reachable through object */
53833 goto skip_value;
53834 }
53835 default: {
53836 /* exhaustive */
53838 }
53839 }
53840
53841 DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0);
53842 duk_xdef_prop(ctx, i, prop_flags);
53843
53844 skip_value:
53845 continue; /* avoid empty label at the end of a compound statement */
53846 }
53847
53848 /* native function properties */
53850 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
53851 for (j = 0; j < num; j++) {
53852 duk_hstring *h_key;
53853 duk_small_uint_t natidx;
53854 duk_int_t c_nargs; /* must hold DUK_VARARGS */
53855 duk_small_uint_t c_length;
53856 duk_int16_t magic;
53857 duk_c_function c_func;
53858 duk_hnativefunction *h_func;
53859#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
53860 duk_small_int_t lightfunc_eligible;
53861#endif
53862
53864 h_key = duk_get_hstring(ctx, -1);
53865 DUK_ASSERT(h_key != NULL);
53866 DUK_UNREF(h_key);
53868
53870 c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_int32_t) c_length /*def_value*/);
53871 if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
53872 c_nargs = DUK_VARARGS;
53873 }
53874
53875 c_func = duk_bi_native_functions[natidx];
53876
53877 DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
53878 (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
53879 (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
53880
53881 /* Cast converts magic to 16-bit signed value */
53882 magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0);
53883
53884#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
53885 lightfunc_eligible =
53886 ((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
53887 (c_length <= DUK_LFUNC_LENGTH_MAX) &&
53888 (magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
53889
53890 if (h_key == DUK_HTHREAD_STRING_EVAL(thr) ||
53891 h_key == DUK_HTHREAD_STRING_YIELD(thr) ||
53892 h_key == DUK_HTHREAD_STRING_RESUME(thr) ||
53893 h_key == DUK_HTHREAD_STRING_REQUIRE(thr)) {
53894 /* These functions have trouble working as lightfuncs.
53895 * Some of them have specific asserts and some may have
53896 * additional properties (e.g. 'require.id' may be written).
53897 */
53898 DUK_D(DUK_DPRINT("reject as lightfunc: key=%!O, i=%d, j=%d", (duk_heaphdr *) h_key, (int) i, (int) j));
53899 lightfunc_eligible = 0;
53900 }
53901
53902 if (lightfunc_eligible) {
53903 duk_tval tv_lfunc;
53904 duk_small_uint_t lf_nargs = (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
53905 duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
53906 DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
53907 duk_push_tval(ctx, &tv_lfunc);
53908 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)));
53909 goto lightfunc_skip;
53910 }
53911
53912 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));
53913#endif /* DUK_USE_LIGHTFUNC_BUILTINS */
53914
53915 /* [ (builtin objects) name ] */
53916
53917 duk_push_c_function_noconstruct_noexotic(ctx, c_func, c_nargs);
53918 h_func = duk_require_hnativefunction(ctx, -1);
53919 DUK_UNREF(h_func);
53920
53921 /* Currently all built-in native functions are strict.
53922 * This doesn't matter for many functions, but e.g.
53923 * String.prototype.charAt (and other string functions)
53924 * rely on being strict so that their 'this' binding is
53925 * not automatically coerced.
53926 */
53928
53929 /* No built-in functions are constructable except the top
53930 * level ones (Number, etc).
53931 */
53933
53934 /* XXX: any way to avoid decoding magic bit; there are quite
53935 * many function properties and relatively few with magic values.
53936 */
53937 h_func->magic = magic;
53938
53939 /* [ (builtin objects) name func ] */
53940
53941 duk_push_int(ctx, c_length);
53943
53944 duk_dup(ctx, -2);
53946
53947 /* XXX: other properties of function instances; 'arguments', 'caller'. */
53948
53949 DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
53950 (long) i, (long) j, (duk_tval *) duk_get_tval(ctx, -1)));
53951
53952 /* [ (builtin objects) name func ] */
53953
53954 /*
53955 * The default property attributes are correct for all
53956 * function valued properties of built-in objects now.
53957 */
53958
53959#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
53960 lightfunc_skip:
53961#endif
53962
53964
53965 /* [ (builtin objects) ] */
53966 }
53967 }
53968
53969 /*
53970 * Special post-tweaks, for cases not covered by the init data format.
53971 *
53972 * - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
53973 * toGMTString is required to have the same Function object as
53974 * toUTCString in E5 Section B.2.6. Note that while Smjs respects
53975 * this, V8 does not (the Function objects are distinct).
53976 *
53977 * - Make DoubleError non-extensible.
53978 *
53979 * - Add info about most important effective compile options to Duktape.
53980 *
53981 * - Possibly remove some properties (values or methods) which are not
53982 * desirable with current feature options but are not currently
53983 * conditional in init data.
53984 */
53985
53988
53990 DUK_ASSERT(h != NULL);
53992
53993#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
53994 DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
53996#endif
53997
53998#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
53999 DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
54001#endif
54002
54003 /* XXX: relocate */
54004 duk_push_string(ctx,
54005 /* Endianness indicator */
54006#if defined(DUK_USE_INTEGER_LE)
54007 "l"
54008#elif defined(DUK_USE_INTEGER_BE)
54009 "b"
54010#elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */
54011 "m"
54012#else
54013 "?"
54014#endif
54015#if defined(DUK_USE_DOUBLE_LE)
54016 "l"
54017#elif defined(DUK_USE_DOUBLE_BE)
54018 "b"
54019#elif defined(DUK_USE_DOUBLE_ME)
54020 "m"
54021#else
54022 "?"
54023#endif
54024 " "
54025 /* Packed or unpacked tval */
54026#if defined(DUK_USE_PACKED_TVAL)
54027 "p"
54028#else
54029 "u"
54030#endif
54031#if defined(DUK_USE_FASTINT)
54032 "f"
54033#endif
54034 " "
54035 /* Low memory options */
54036#if defined(DUK_USE_STRTAB_CHAIN)
54037 "c" /* chain */
54038#elif defined(DUK_USE_STRTAB_PROBE)
54039 "p" /* probe */
54040#else
54041 "?"
54042#endif
54043#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
54044 "n"
54045#endif
54046#if defined(DUK_USE_HEAPPTR16)
54047 "h"
54048#endif
54049#if defined(DUK_USE_DATAPTR16)
54050 "d"
54051#endif
54052#if defined(DUK_USE_FUNCPTR16)
54053 "f"
54054#endif
54055#if defined(DUK_USE_REFCOUNT16)
54056 "R"
54057#endif
54058#if defined(DUK_USE_STRHASH16)
54059 "H"
54060#endif
54061#if defined(DUK_USE_STRLEN16)
54062 "S"
54063#endif
54064#if defined(DUK_USE_BUFLEN16)
54065 "B"
54066#endif
54067#if defined(DUK_USE_OBJSIZES16)
54068 "O"
54069#endif
54070#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
54071 "L"
54072#endif
54073#if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
54074 /* XXX: This won't be shown in practice now
54075 * because this code is not run when builtins
54076 * are in ROM.
54077 */
54078 "Z"
54079#endif
54080 " "
54081 /* Object property allocation layout */
54082#if defined(DUK_USE_HOBJECT_LAYOUT_1)
54083 "p1"
54084#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
54085 "p2"
54086#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
54087 "p3"
54088#else
54089 "p?"
54090#endif
54091 " "
54092 /* Alignment guarantee */
54093#if (DUK_USE_ALIGN_BY == 4)
54094 "a4"
54095#elif (DUK_USE_ALIGN_BY == 8)
54096 "a8"
54097#elif (DUK_USE_ALIGN_BY == 1)
54098 "a1"
54099#else
54100#error invalid DUK_USE_ALIGN_BY
54101#endif
54102 " "
54103 /* Architecture, OS, and compiler strings */
54105 " "
54107 " "
54110
54111 /*
54112 * InitJS code - Ecmascript code evaluated from a built-in source
54113 * which provides e.g. backward compatibility. User can also provide
54114 * JS code to be evaluated at startup.
54115 */
54116
54117#ifdef DUK_USE_BUILTIN_INITJS
54118 /* XXX: compression */
54119 DUK_DD(DUK_DDPRINT("running built-in initjs"));
54120 duk_eval_string(ctx, (const char *) duk_initjs_data); /* initjs data is NUL terminated */
54121 duk_pop(ctx);
54122#endif /* DUK_USE_BUILTIN_INITJS */
54123
54124#ifdef DUK_USE_USER_INITJS
54125 /* XXX: compression (as an option) */
54126 DUK_DD(DUK_DDPRINT("running user initjs"));
54127 duk_eval_string_noresult(ctx, (const char *) DUK_USE_USER_INITJS);
54128#endif /* DUK_USE_USER_INITJS */
54129
54130 /*
54131 * Since built-ins are not often extended, compact them.
54132 */
54133
54134 DUK_DD(DUK_DDPRINT("compact built-ins"));
54135 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
54137 }
54138
54139 DUK_D(DUK_DPRINT("INITBUILTINS END"));
54140
54141#ifdef DUK_USE_DDPRINT
54142 for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
54143 DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
54144 (long) i, (duk_heaphdr *) duk_require_hobject(ctx, i)));
54145 }
54146#endif
54147
54148 /*
54149 * Pop built-ins from stack: they are now INCREF'd and
54150 * reachable from the builtins[] array or indirectly
54151 * through builtins[].
54152 */
54153
54154 duk_set_top(ctx, 0);
54155 DUK_ASSERT_TOP(ctx, 0);
54156}
54157#endif /* DUK_USE_ROM_OBJECTS */
54158
54161
54162 for (i = 0; i < DUK_NUM_BUILTINS; i++) {
54163 thr_to->builtins[i] = thr_from->builtins[i];
54164 DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]); /* side effect free */
54165 }
54166}
54167#line 1 "duk_hthread_misc.c"
54168/*
54169 * Thread support.
54170 */
54171
54172/* include removed: duk_internal.h */
54173
54175 DUK_ASSERT(thr != NULL);
54176
54177 /* Order of unwinding is important */
54178
54180
54181 duk_hthread_callstack_unwind(thr, 0); /* side effects, possibly errors */
54182
54183 thr->valstack_bottom = thr->valstack;
54184 duk_set_top((duk_context *) thr, 0); /* unwinds valstack, updating refcounts */
54185
54187
54188 /* Here we could remove references to built-ins, but it may not be
54189 * worth the effort because built-ins are quite likely to be shared
54190 * with another (unterminated) thread, and terminated threads are also
54191 * usually garbage collected quite quickly. Also, doing DECREFs
54192 * could trigger finalization, which would run on the current thread
54193 * and have access to only some of the built-ins. Garbage collection
54194 * deals with this correctly already.
54195 */
54196
54197 /* XXX: Shrink the stacks to minimize memory usage? May not
54198 * be worth the effort because terminated threads are usually
54199 * garbage collected quite soon.
54200 */
54201}
54202
54204 DUK_ASSERT(thr != NULL);
54205
54206 if (thr->callstack_top > 0) {
54207 return thr->callstack + thr->callstack_top - 1;
54208 } else {
54209 return NULL;
54210 }
54211}
54212
54213#if defined(DUK_USE_DEBUGGER_SUPPORT)
54214DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
54215 duk_instr_t *bcode;
54216
54217 DUK_ASSERT(thr != NULL);
54218 DUK_ASSERT(act != NULL);
54219 DUK_UNREF(thr);
54220
54221 /* XXX: store 'bcode' pointer to activation for faster lookup? */
54222 if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
54224 return (duk_uint_fast32_t) (act->curr_pc - bcode);
54225 }
54226 return 0;
54227}
54228#endif /* DUK_USE_DEBUGGER_SUPPORT */
54229
54231 duk_instr_t *bcode;
54234 DUK_ASSERT(thr != NULL);
54235 DUK_ASSERT(act != NULL);
54236 DUK_UNREF(thr);
54237
54238 if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
54240 ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
54241 if (ret > 0) {
54242 ret--;
54243 }
54244 return ret;
54245 }
54246 return 0;
54247}
54248
54249/* Write bytecode executor's curr_pc back to topmost activation (if any). */
54251 duk_activation *act;
54252
54253 DUK_ASSERT(thr != NULL);
54254
54255 if (thr->ptr_curr_pc != NULL) {
54256 /* ptr_curr_pc != NULL only when bytecode executor is active. */
54257 DUK_ASSERT(thr->callstack_top > 0);
54258 act = thr->callstack + thr->callstack_top - 1;
54259 act->curr_pc = *thr->ptr_curr_pc;
54260 }
54261}
54262
54264 duk_activation *act;
54265
54266 DUK_ASSERT(thr != NULL);
54267
54268 if (thr->ptr_curr_pc != NULL) {
54269 /* ptr_curr_pc != NULL only when bytecode executor is active. */
54270 DUK_ASSERT(thr->callstack_top > 0);
54271 act = thr->callstack + thr->callstack_top - 1;
54272 act->curr_pc = *thr->ptr_curr_pc;
54273 thr->ptr_curr_pc = NULL;
54274 }
54275}
54276#line 1 "duk_hthread_stacks.c"
54277/*
54278 * Manipulation of thread stacks (valstack, callstack, catchstack).
54279 *
54280 * Ideally unwinding of stacks should have no side effects, which would
54281 * then favor separate unwinding and shrink check primitives for each
54282 * stack type. A shrink check may realloc and thus have side effects.
54283 *
54284 * However, currently callstack unwinding itself has side effects, as it
54285 * needs to DECREF multiple objects, close environment records, etc.
54286 * Stacks must thus be unwound in the correct order by the caller.
54287 *
54288 * (XXX: This should be probably reworked so that there is a shared
54289 * unwind primitive which handles all stacks as requested, and knows
54290 * the proper order for unwinding.)
54291 *
54292 * Valstack entries above 'top' are always kept initialized to
54293 * "undefined unused". Callstack and catchstack entries above 'top'
54294 * are not zeroed and are left as garbage.
54295 *
54296 * Value stack handling is mostly a part of the API implementation.
54297 */
54298
54299/* include removed: duk_internal.h */
54300
54301/* check that there is space for at least one new entry */
54303 duk_activation *new_ptr;
54304 duk_size_t old_size;
54305 duk_size_t new_size;
54306
54307 DUK_ASSERT(thr != NULL);
54308 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
54310
54311 if (thr->callstack_top < thr->callstack_size) {
54312 return;
54313 }
54314
54315 old_size = thr->callstack_size;
54316 new_size = old_size + DUK_CALLSTACK_GROW_STEP;
54317
54318 /* this is a bit approximate (errors out before max is reached); this is OK */
54319 if (new_size >= thr->callstack_max) {
54321 }
54322
54323 DUK_DD(DUK_DDPRINT("growing callstack %ld -> %ld", (long) old_size, (long) new_size));
54324
54326 * Note: must use indirect variant of DUK_REALLOC() because underlying
54327 * pointer may be changed by mark-and-sweep.
54328 */
54329
54330 DUK_ASSERT(new_size > 0);
54331 new_ptr = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
54332 if (!new_ptr) {
54333 /* No need for a NULL/zero-size check because new_size > 0) */
54335 }
54336 thr->callstack = new_ptr;
54337 thr->callstack_size = new_size;
54338
54339 /* note: any entries above the callstack top are garbage and not zeroed */
54340}
54341
54343 duk_size_t new_size;
54344 duk_activation *p;
54345
54346 DUK_ASSERT(thr != NULL);
54347 DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
54349
54351 return;
54352 }
54353
54354 new_size = thr->callstack_top + DUK_CALLSTACK_SHRINK_SPARE;
54355 DUK_ASSERT(new_size >= thr->callstack_top);
54356
54357 DUK_DD(DUK_DDPRINT("shrinking callstack %ld -> %ld", (long) thr->callstack_size, (long) new_size));
54358
54359 /*
54360 * Note: must use indirect variant of DUK_REALLOC() because underlying
54361 * pointer may be changed by mark-and-sweep.
54362 */
54364 /* shrink failure is not fatal */
54365 p = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
54366 if (p) {
54367 thr->callstack = p;
54368 thr->callstack_size = new_size;
54369 } else {
54370 /* Because new_size != 0, if condition doesn't need to be
54371 * (p != NULL || new_size == 0).
54372 */
54373 DUK_ASSERT(new_size != 0);
54374 DUK_D(DUK_DPRINT("callstack shrink failed, ignoring"));
54375 }
54376
54377 /* note: any entries above the callstack top are garbage and not zeroed */
54378}
54379
54381 duk_size_t idx;
54382
54383 DUK_DDD(DUK_DDDPRINT("unwind callstack top of thread %p from %ld to %ld",
54384 (void *) thr,
54385 (thr != NULL ? (long) thr->callstack_top : (long) -1),
54386 (long) new_top));
54387
54388 DUK_ASSERT(thr);
54389 DUK_ASSERT(thr->heap);
54390 DUK_ASSERT_DISABLE(new_top >= 0); /* unsigned */
54391 DUK_ASSERT((duk_size_t) new_top <= thr->callstack_top); /* cannot grow */
54392
54393 /*
54394 * The loop below must avoid issues with potential callstack
54395 * reallocations. A resize (and other side effects) may happen
54396 * e.g. due to finalizer/errhandler calls caused by a refzero or
54397 * mark-and-sweep. Arbitrary finalizers may run, because when
54398 * an environment record is refzero'd, it may refer to arbitrary
54399 * values which also become refzero'd.
54400 *
54401 * So, the pointer 'p' is re-looked-up below whenever a side effect
54402 * might have changed it.
54403 */
54404
54405 idx = thr->callstack_top;
54406 while (idx > new_top) {
54407 duk_activation *act;
54408 duk_hobject *func;
54409#ifdef DUK_USE_REFERENCE_COUNTING
54410 duk_hobject *tmp;
54411#endif
54412#ifdef DUK_USE_DEBUGGER_SUPPORT
54413 duk_heap *heap;
54414#endif
54415
54416 idx--;
54417 DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
54418 DUK_ASSERT((duk_size_t) idx < thr->callstack_size); /* true, despite side effect resizes */
54419
54420 act = thr->callstack + idx;
54421 /* With lightfuncs, act 'func' may be NULL */
54422
54423#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
54424 /*
54425 * Restore 'caller' property for non-strict callee functions.
54426 */
54427
54428 func = DUK_ACT_GET_FUNC(act);
54429 if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
54430 duk_tval *tv_caller;
54431 duk_tval tv_tmp;
54432 duk_hobject *h_tmp;
54433
54435
54436 /* The act->prev_caller should only be set if the entry for 'caller'
54437 * exists (as it is only set in that case, and the property is not
54438 * configurable), but handle all the cases anyway.
54439 */
54440
54441 if (tv_caller) {
54442 DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
54443 if (act->prev_caller) {
54444 /* Just transfer the refcount from act->prev_caller to tv_caller,
54445 * so no need for a refcount update. This is the expected case.
54446 */
54447 DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
54448 act->prev_caller = NULL;
54449 } else {
54450 DUK_TVAL_SET_NULL(tv_caller); /* no incref needed */
54451 DUK_ASSERT(act->prev_caller == NULL);
54452 }
54453 DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
54454 } else {
54455 h_tmp = act->prev_caller;
54456 if (h_tmp) {
54457 act->prev_caller = NULL;
54458 DUK_HOBJECT_DECREF(thr, h_tmp); /* side effects */
54459 }
54460 }
54461 act = thr->callstack + idx; /* avoid side effects */
54462 DUK_ASSERT(act->prev_caller == NULL);
54463 }
54464#endif
54465
54466 /*
54467 * Unwind debugger state. If we unwind while stepping
54468 * (either step over or step into), pause execution.
54469 */
54470
54471#if defined(DUK_USE_DEBUGGER_SUPPORT)
54472 heap = thr->heap;
54473 if (heap->dbg_step_thread == thr &&
54474 heap->dbg_step_csindex == idx) {
54475 /* Pause for all step types: step into, step over, step out.
54476 * This is the only place explicitly handling a step out.
54477 */
54478 DUK_HEAP_SET_PAUSED(heap);
54479 DUK_ASSERT(heap->dbg_step_thread == NULL);
54480 }
54481#endif
54482
54483 /*
54484 * Close environment record(s) if they exist.
54485 *
54486 * Only variable environments are closed. If lex_env != var_env, it
54487 * cannot currently contain any register bound declarations.
54488 *
54489 * Only environments created for a NEWENV function are closed. If an
54490 * environment is created for e.g. an eval call, it must not be closed.
54491 */
54492
54493 func = DUK_ACT_GET_FUNC(act);
54494 if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
54495 DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
54496 goto skip_env_close;
54497 }
54498 /* func is NULL for lightfunc */
54499
54500 DUK_ASSERT(act->lex_env == act->var_env);
54501 if (act->var_env != NULL) {
54502 DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
54503 (void *) act->var_env, (duk_heaphdr *) act->var_env));
54504 duk_js_close_environment_record(thr, act->var_env, func, act->idx_bottom);
54505 act = thr->callstack + idx; /* avoid side effect issues */
54506 }
54507
54508#if 0
54509 if (act->lex_env != NULL) {
54510 if (act->lex_env == act->var_env) {
54511 /* common case, already closed, so skip */
54512 DUK_DD(DUK_DDPRINT("lex_env and var_env are the same and lex_env "
54513 "already closed -> skip closing lex_env"));
54514 ;
54515 } else {
54516 DUK_DD(DUK_DDPRINT("closing lex_env record %p -> %!O",
54517 (void *) act->lex_env, (duk_heaphdr *) act->lex_env));
54519 act = thr->callstack + idx; /* avoid side effect issues */
54520 }
54521 }
54522#endif
54523
54524 DUK_ASSERT((act->lex_env == NULL) ||
54529
54530 DUK_ASSERT((act->var_env == NULL) ||
54535
54536 skip_env_close:
54537
54538 /*
54539 * Update preventcount
54540 */
54541
54542 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
54543 DUK_ASSERT(thr->callstack_preventcount >= 1);
54544 thr->callstack_preventcount--;
54545 }
54546
54547 /*
54548 * Reference count updates
54549 *
54550 * Note: careful manipulation of refcounts. The top is
54551 * not updated yet, so all the activations are reachable
54552 * for mark-and-sweep (which may be triggered by decref).
54553 * However, the pointers are NULL so this is not an issue.
54554 */
54555
54556#ifdef DUK_USE_REFERENCE_COUNTING
54557 tmp = act->var_env;
54558#endif
54559 act->var_env = NULL;
54560#ifdef DUK_USE_REFERENCE_COUNTING
54562 act = thr->callstack + idx; /* avoid side effect issues */
54563#endif
54564
54565#ifdef DUK_USE_REFERENCE_COUNTING
54566 tmp = act->lex_env;
54567#endif
54568 act->lex_env = NULL;
54569#ifdef DUK_USE_REFERENCE_COUNTING
54571 act = thr->callstack + idx; /* avoid side effect issues */
54572#endif
54573
54574 /* Note: this may cause a corner case situation where a finalizer
54575 * may see a currently reachable activation whose 'func' is NULL.
54576 */
54577#ifdef DUK_USE_REFERENCE_COUNTING
54578 tmp = DUK_ACT_GET_FUNC(act);
54579#endif
54580 act->func = NULL;
54581#ifdef DUK_USE_REFERENCE_COUNTING
54583 act = thr->callstack + idx; /* avoid side effect issues */
54584 DUK_UNREF(act);
54585#endif
54586 }
54587
54588 thr->callstack_top = new_top;
54589
54591 * We could clear the book-keeping variables for the topmost activation,
54592 * but don't do so now.
54593 */
54594#if 0
54595 if (thr->callstack_top > 0) {
54596 duk_activation *act = thr->callstack + thr->callstack_top - 1;
54597 act->idx_retval = 0;
54598 }
54599#endif
54600
54601 /* Note: any entries above the callstack top are garbage and not zeroed.
54602 * Also topmost activation idx_retval is garbage (not zeroed), and must
54603 * be ignored.
54604 */
54605}
54606
54608 duk_catcher *new_ptr;
54609 duk_size_t old_size;
54610 duk_size_t new_size;
54611
54612 DUK_ASSERT(thr != NULL);
54613 DUK_ASSERT_DISABLE(thr->catchstack_top); /* avoid warning (unsigned) */
54615
54616 if (thr->catchstack_top < thr->catchstack_size) {
54617 return;
54618 }
54619
54620 old_size = thr->catchstack_size;
54621 new_size = old_size + DUK_CATCHSTACK_GROW_STEP;
54622
54623 /* this is a bit approximate (errors out before max is reached); this is OK */
54624 if (new_size >= thr->catchstack_max) {
54626 }
54627
54628 DUK_DD(DUK_DDPRINT("growing catchstack %ld -> %ld", (long) old_size, (long) new_size));
54629
54631 * Note: must use indirect variant of DUK_REALLOC() because underlying
54632 * pointer may be changed by mark-and-sweep.
54633 */
54634
54635 DUK_ASSERT(new_size > 0);
54636 new_ptr = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
54637 if (!new_ptr) {
54638 /* No need for a NULL/zero-size check because new_size > 0) */
54640 }
54641 thr->catchstack = new_ptr;
54642 thr->catchstack_size = new_size;
54643
54644 /* note: any entries above the catchstack top are garbage and not zeroed */
54645}
54646
54648 duk_size_t new_size;
54649 duk_catcher *p;
54650
54651 DUK_ASSERT(thr != NULL);
54652 DUK_ASSERT_DISABLE(thr->catchstack_top >= 0); /* avoid warning (unsigned) */
54654
54656 return;
54657 }
54658
54660 DUK_ASSERT(new_size >= thr->catchstack_top);
54661
54662 DUK_DD(DUK_DDPRINT("shrinking catchstack %ld -> %ld", (long) thr->catchstack_size, (long) new_size));
54663
54664 /*
54665 * Note: must use indirect variant of DUK_REALLOC() because underlying
54666 * pointer may be changed by mark-and-sweep.
54667 */
54669 /* shrink failure is not fatal */
54670 p = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
54671 if (p) {
54672 thr->catchstack = p;
54673 thr->catchstack_size = new_size;
54674 } else {
54675 /* Because new_size != 0, if condition doesn't need to be
54676 * (p != NULL || new_size == 0).
54677 */
54678 DUK_ASSERT(new_size != 0);
54679 DUK_D(DUK_DPRINT("catchstack shrink failed, ignoring"));
54680 }
54681
54682 /* note: any entries above the catchstack top are garbage and not zeroed */
54683}
54684
54686 duk_size_t idx;
54687
54688 DUK_DDD(DUK_DDDPRINT("unwind catchstack top of thread %p from %ld to %ld",
54689 (void *) thr,
54690 (thr != NULL ? (long) thr->catchstack_top : (long) -1),
54691 (long) new_top));
54692
54693 DUK_ASSERT(thr);
54694 DUK_ASSERT(thr->heap);
54695 DUK_ASSERT_DISABLE(new_top >= 0); /* unsigned */
54696 DUK_ASSERT((duk_size_t) new_top <= thr->catchstack_top); /* cannot grow */
54697
54698 /*
54699 * Since there are no references in the catcher structure,
54700 * unwinding is quite simple. The only thing we need to
54701 * look out for is popping a possible lexical environment
54702 * established for an active catch clause.
54703 */
54704
54705 idx = thr->catchstack_top;
54706 while (idx > new_top) {
54707 duk_catcher *p;
54708 duk_activation *act;
54709 duk_hobject *env;
54710
54711 idx--;
54712 DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
54713 DUK_ASSERT((duk_size_t) idx < thr->catchstack_size);
54714
54715 p = thr->catchstack + idx;
54716
54718 DUK_DDD(DUK_DDDPRINT("unwinding catchstack idx %ld, callstack idx %ld, callstack top %ld: lexical environment active",
54719 (long) idx, (long) p->callstack_index, (long) thr->callstack_top));
54720
54721 /* XXX: Here we have a nasty dependency: the need to manipulate
54722 * the callstack means that catchstack must always be unwound by
54723 * the caller before unwinding the callstack. This should be fixed
54724 * later.
54725 */
54726
54727 /* Note that multiple catchstack entries may refer to the same
54728 * callstack entry.
54729 */
54730 act = thr->callstack + p->callstack_index;
54731 DUK_ASSERT(act >= thr->callstack);
54732 DUK_ASSERT(act < thr->callstack + thr->callstack_top);
54733
54734 DUK_DDD(DUK_DDDPRINT("catchstack_index=%ld, callstack_index=%ld, lex_env=%!iO",
54735 (long) idx, (long) p->callstack_index,
54736 (duk_heaphdr *) act->lex_env));
54737
54738 env = act->lex_env; /* current lex_env of the activation (created for catcher) */
54739 DUK_ASSERT(env != NULL); /* must be, since env was created when catcher was created */
54740 act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env); /* prototype is lex_env before catcher created */
54741 DUK_HOBJECT_DECREF(thr, env);
54742
54743 /* There is no need to decref anything else than 'env': if 'env'
54744 * becomes unreachable, refzero will handle decref'ing its prototype.
54745 */
54746 }
54747 }
54748
54749 thr->catchstack_top = new_top;
54750
54751 /* note: any entries above the catchstack top are garbage and not zeroed */
54752}
54753#line 1 "duk_js_call.c"
54754/*
54755 * Call handling.
54756 *
54757 * Main functions are:
54758 *
54759 * - duk_handle_call_unprotected(): unprotected call to Ecmascript or
54760 * Duktape/C function
54761 * - duk_handle_call_protected(): protected call to Ecmascript or
54762 * Duktape/C function
54763 * - duk_handle_safe_call(): make a protected C call within current
54764 * activation
54765 * - duk_handle_ecma_call_setup(): Ecmascript-to-Ecmascript calls
54766 * (not always possible), including tail calls and coroutine resume
54767 *
54768 * See 'execution.rst'.
54769 *
54770 * Note: setjmp() and local variables have a nasty interaction,
54771 * see execution.rst; non-volatile locals modified after setjmp()
54772 * call are not guaranteed to keep their value.
54773 */
54774
54775/* include removed: duk_internal.h */
54776
54777/*
54778 * Forward declarations.
54779 */
54780
54782 duk_idx_t num_stack_args,
54783 duk_small_uint_t call_flags,
54784 duk_idx_t idx_func);
54786 duk_size_t entry_valstack_bottom_index,
54787 duk_size_t entry_valstack_end,
54788 duk_size_t entry_catchstack_top,
54789 duk_size_t entry_callstack_top,
54790 duk_int_t entry_call_recursion_depth,
54791 duk_hthread *entry_curr_thread,
54792 duk_uint_fast8_t entry_thread_state,
54793 duk_instr_t **entry_ptr_curr_pc,
54794 duk_idx_t idx_func,
54795 duk_jmpbuf *old_jmpbuf_ptr);
54798 duk_idx_t idx_retbase,
54799 duk_idx_t num_stack_rets,
54800 duk_size_t entry_valstack_bottom_index,
54801 duk_size_t entry_callstack_top,
54802 duk_size_t entry_catchstack_top);
54804 duk_idx_t idx_retbase,
54805 duk_idx_t num_stack_rets,
54806 duk_size_t entry_valstack_bottom_index,
54807 duk_size_t entry_callstack_top,
54808 duk_size_t entry_catchstack_top,
54809 duk_jmpbuf *old_jmpbuf_ptr);
54811 duk_idx_t idx_retbase,
54812 duk_idx_t num_stack_rets,
54813 duk_int_t entry_call_recursion_depth,
54814 duk_hthread *entry_curr_thread,
54815 duk_uint_fast8_t entry_thread_state,
54816 duk_instr_t **entry_ptr_curr_pc);
54817
54818/*
54819 * Interrupt counter fixup (for development only).
54820 */
54821
54822#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
54823DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
54824 /* Currently the bytecode executor and executor interrupt
54825 * instruction counts are off because we don't execute the
54826 * interrupt handler when we're about to exit from the initial
54827 * user call into Duktape.
54828 *
54829 * If we were to execute the interrupt handler here, the counts
54830 * would match. You can enable this block manually to check
54831 * that this is the case.
54832 */
54833
54834 DUK_ASSERT(thr != NULL);
54835 DUK_ASSERT(thr->heap != NULL);
54836
54837#if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
54838 if (entry_curr_thread == NULL) {
54839 thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
54840 thr->heap->inst_count_interrupt += thr->interrupt_init;
54841 DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
54842 "user code, instruction counts: executor=%ld, interrupt=%ld",
54843 (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
54844 DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
54846#else
54847 DUK_UNREF(thr);
54848 DUK_UNREF(entry_curr_thread);
54849#endif
54850}
54851#endif
54852
54853/*
54854 * Arguments object creation.
54855 *
54856 * Creating arguments objects involves many small details, see E5 Section
54857 * 10.6 for the specific requirements. Much of the arguments object exotic
54858 * behavior is implemented in duk_hobject_props.c, and is enabled by the
54859 * object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
54860 */
54861
54863 duk_hobject *func,
54864 duk_hobject *varenv,
54865 duk_idx_t idx_argbase, /* idx of first argument on stack */
54866 duk_idx_t num_stack_args) { /* num args starting from idx_argbase */
54867 duk_context *ctx = (duk_context *) thr;
54868 duk_hobject *arg; /* 'arguments' */
54869 duk_hobject *formals; /* formals for 'func' (may be NULL if func is a C function) */
54870 duk_idx_t i_arg;
54871 duk_idx_t i_map;
54872 duk_idx_t i_mappednames;
54873 duk_idx_t i_formals;
54874 duk_idx_t i_argbase;
54875 duk_idx_t n_formals;
54876 duk_idx_t idx;
54877 duk_bool_t need_map;
54878
54879 DUK_DDD(DUK_DDDPRINT("creating arguments object for func=%!iO, varenv=%!iO, "
54880 "idx_argbase=%ld, num_stack_args=%ld",
54881 (duk_heaphdr *) func, (duk_heaphdr *) varenv,
54882 (long) idx_argbase, (long) num_stack_args));
54883
54884 DUK_ASSERT(thr != NULL);
54885 DUK_ASSERT(func != NULL);
54887 DUK_ASSERT(varenv != NULL);
54888 DUK_ASSERT(idx_argbase >= 0); /* assumed to bottom relative */
54889 DUK_ASSERT(num_stack_args >= 0);
54890
54891 need_map = 0;
54892
54893 i_argbase = idx_argbase;
54894 DUK_ASSERT(i_argbase >= 0);
54895
54896 duk_push_hobject(ctx, func);
54898 formals = duk_get_hobject(ctx, -1);
54899 n_formals = 0;
54900 if (formals) {
54902 n_formals = (duk_idx_t) duk_require_int(ctx, -1);
54903 duk_pop(ctx);
54904 }
54905 duk_remove(ctx, -2); /* leave formals on stack for later use */
54906 i_formals = duk_require_top_index(ctx);
54907
54908 DUK_ASSERT(n_formals >= 0);
54909 DUK_ASSERT(formals != NULL || n_formals == 0);
54910
54911 DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
54912 (duk_heaphdr *) func, (duk_heaphdr *) formals,
54913 (long) n_formals));
54914
54915 /* [ ... formals ] */
54916
54917 /*
54918 * Create required objects:
54919 * - 'arguments' object: array-like, but not an array
54920 * - 'map' object: internal object, tied to 'arguments'
54921 * - 'mappedNames' object: temporary value used during construction
54922 */
54923
54924 i_arg = duk_push_object_helper(ctx,
54929 DUK_ASSERT(i_arg >= 0);
54930 arg = duk_require_hobject(ctx, -1);
54931 DUK_ASSERT(arg != NULL);
54932
54933 i_map = duk_push_object_helper(ctx,
54936 -1); /* no prototype */
54937 DUK_ASSERT(i_map >= 0);
54938
54939 i_mappednames = duk_push_object_helper(ctx,
54942 -1); /* no prototype */
54943 DUK_ASSERT(i_mappednames >= 0);
54944
54945 /* [ ... formals arguments map mappedNames ] */
54946
54947 DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
54948 "arguments at index %ld -> %!O "
54949 "map at index %ld -> %!O "
54950 "mappednames at index %ld -> %!O",
54951 (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
54952 (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
54953 (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
54954
54955 /*
54956 * Init arguments properties, map, etc.
54957 */
54958
54959 duk_push_int(ctx, num_stack_args);
54961
54962 /*
54963 * Init argument related properties
54964 */
54965
54966 /* step 11 */
54967 idx = num_stack_args - 1;
54968 while (idx >= 0) {
54969 DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
54970 (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
54971
54972 DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
54973 duk_dup(ctx, i_argbase + idx);
54974 duk_xdef_prop_index_wec(ctx, i_arg, (duk_uarridx_t) idx);
54975 DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
54976
54977 /* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
54978 if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
54979 DUK_ASSERT(formals != NULL);
54980
54981 DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
54982 (long) idx, (long) n_formals));
54983
54984 duk_get_prop_index(ctx, i_formals, idx);
54985 DUK_ASSERT(duk_is_string(ctx, -1));
54986
54987 duk_dup(ctx, -1); /* [ ... name name ] */
54988
54989 if (!duk_has_prop(ctx, i_mappednames)) {
54990 /* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
54991 * differs from the reference model
54992 */
54993
54994 /* [ ... name ] */
54995
54996 need_map = 1;
54997
54998 DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
54999 (const char *) duk_get_string(ctx, -1),
55000 (long) idx));
55001 duk_dup(ctx, -1); /* name */
55002 duk_push_uint(ctx, (duk_uint_t) idx); /* index */
55003 duk_to_string(ctx, -1);
55004 duk_xdef_prop_wec(ctx, i_mappednames); /* out of spec, must be configurable */
55005
55006 DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
55007 (long) idx,
55008 duk_get_string(ctx, -1)));
55009 duk_dup(ctx, -1); /* name */
55010 duk_xdef_prop_index_wec(ctx, i_map, (duk_uarridx_t) idx); /* out of spec, must be configurable */
55011 } else {
55012 /* duk_has_prop() popped the second 'name' */
55013 }
55014
55015 /* [ ... name ] */
55016 duk_pop(ctx); /* pop 'name' */
55017 }
55018
55019 idx--;
55020 }
55021
55022 DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
55023
55024 /* step 12 */
55025 if (need_map) {
55026 DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
55027
55028 /* should never happen for a strict callee */
55030
55031 duk_dup(ctx, i_map);
55032 duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
55033
55034 /* The variable environment for magic variable bindings needs to be
55035 * given by the caller and recorded in the arguments object.
55036 *
55037 * See E5 Section 10.6, the creation of setters/getters.
55038 *
55039 * The variable environment also provides access to the callee, so
55040 * an explicit (internal) callee property is not needed.
55041 */
55042
55043 duk_push_hobject(ctx, varenv);
55044 duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
55045 }
55046
55047 /* steps 13-14 */
55048 if (DUK_HOBJECT_HAS_STRICT(func)) {
55049 /* Callee/caller are throwers and are not deletable etc. They
55050 * could be implemented as virtual properties, but currently
55051 * there is no support for virtual properties which are accessors
55052 * (only plain virtual properties). This would not be difficult
55053 * to change in duk_hobject_props, but we can make the throwers
55054 * normal, concrete properties just as easily.
55055 *
55056 * Note that the specification requires that the *same* thrower
55057 * built-in object is used here! See E5 Section 10.6 main
55058 * algoritm, step 14, and Section 13.2.3 which describes the
55059 * thrower. See test case test-arguments-throwers.js.
55060 */
55061
55062 DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
55063
55066 } else {
55067 DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
55068 duk_push_hobject(ctx, func);
55070 }
55071
55072 /* set exotic behavior only after we're done */
55073 if (need_map) {
55074 /* Exotic behaviors are only enabled for arguments objects
55075 * which have a parameter map (see E5 Section 10.6 main
55076 * algorithm, step 12).
55077 *
55078 * In particular, a non-strict arguments object with no
55079 * mapped formals does *NOT* get exotic behavior, even
55080 * for e.g. "caller" property. This seems counterintuitive
55081 * but seems to be the case.
55082 */
55083
55084 /* cannot be strict (never mapped variables) */
55086
55087 DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
55089 } else {
55090 DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
55091 }
55092
55093 DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
55094 "arguments at index %ld -> %!O "
55095 "map at index %ld -> %!O "
55096 "mappednames at index %ld -> %!O",
55097 (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
55098 (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
55099 (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
55100
55101 /* [ args(n) [crud] formals arguments map mappednames ] */
55102
55103 duk_pop_2(ctx);
55104 duk_remove(ctx, -2);
55105
55106 /* [ args [crud] arguments ] */
55107}
55108
55109/* Helper for creating the arguments object and adding it to the env record
55110 * on top of the value stack. This helper has a very strict dependency on
55111 * the shape of the input stack.
55112 */
55114 duk_hobject *func,
55115 duk_hobject *env,
55116 duk_idx_t num_stack_args) {
55117 duk_context *ctx = (duk_context *) thr;
55118
55119 DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
55120
55121 DUK_ASSERT(thr != NULL);
55122 DUK_ASSERT(func != NULL);
55123 DUK_ASSERT(env != NULL);
55125 DUK_ASSERT(duk_get_top(ctx) >= num_stack_args + 1);
55126
55127 /* [ ... arg1 ... argN envobj ] */
55128
55130 func,
55131 env,
55132 duk_get_top(ctx) - num_stack_args - 1, /* idx_argbase */
55133 num_stack_args);
55134
55135 /* [ ... arg1 ... argN envobj argobj ] */
55136
55138 -2,
55140 DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E : /* strict: non-deletable, non-writable */
55141 DUK_PROPDESC_FLAGS_WE); /* non-strict: non-deletable, writable */
55142 /* [ ... arg1 ... argN envobj ] */
55143}
55144
55145/*
55146 * Helper for handling a "bound function" chain when a call is being made.
55147 *
55148 * Follows the bound function chain until a non-bound function is found.
55149 * Prepends the bound arguments to the value stack (at idx_func + 2),
55150 * updating 'num_stack_args' in the process. The 'this' binding is also
55151 * updated if necessary (at idx_func + 1). Note that for constructor calls
55152 * the 'this' binding is never updated by [[BoundThis]].
55153 *
55154 * XXX: bound function chains could be collapsed at bound function creation
55155 * time so that each bound function would point directly to a non-bound
55156 * function. This would make call time handling much easier.
55157 */
55158
55160 duk_idx_t idx_func,
55161 duk_idx_t *p_num_stack_args, /* may be changed by call */
55162 duk_bool_t is_constructor_call) {
55163 duk_context *ctx = (duk_context *) thr;
55164 duk_idx_t num_stack_args;
55165 duk_tval *tv_func;
55166 duk_hobject *func;
55167 duk_uint_t sanity;
55168
55169 DUK_ASSERT(thr != NULL);
55170 DUK_ASSERT(p_num_stack_args != NULL);
55171
55172 /* On entry, item at idx_func is a bound, non-lightweight function,
55173 * but we don't rely on that below.
55174 */
55175
55176 num_stack_args = *p_num_stack_args;
55177
55179 do {
55180 duk_idx_t i, len;
55181
55182 tv_func = duk_require_tval(ctx, idx_func);
55183 DUK_ASSERT(tv_func != NULL);
55184
55185 if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
55186 /* Lightweight function: never bound, so terminate. */
55187 break;
55188 } else if (DUK_TVAL_IS_OBJECT(tv_func)) {
55189 func = DUK_TVAL_GET_OBJECT(tv_func);
55190 if (!DUK_HOBJECT_HAS_BOUND(func)) {
55191 /* Normal non-bound function. */
55192 break;
55193 }
55194 } else {
55195 /* Function.prototype.bind() should never let this happen,
55196 * ugly error message is enough.
55197 */
55199 }
55200 DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv_func) != NULL);
55201
55202 /* XXX: this could be more compact by accessing the internal properties
55203 * directly as own properties (they cannot be inherited, and are not
55204 * externally visible).
55205 */
55206
55207 DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p, num_stack_args=%ld: %!T",
55208 (void *) DUK_TVAL_GET_OBJECT(tv_func), (long) num_stack_args, tv_func));
55209
55210 /* [ ... func this arg1 ... argN ] */
55211
55212 if (is_constructor_call) {
55213 /* See: tests/ecmascript/test-spec-bound-constructor.js */
55214 DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
55215 } else {
55217 duk_replace(ctx, idx_func + 1); /* idx_this = idx_func + 1 */
55218 }
55219
55220 /* [ ... func this arg1 ... argN ] */
55221
55222 /* XXX: duk_get_length? */
55223 duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_ARGS); /* -> [ ... func this arg1 ... argN _Args ] */
55224 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH); /* -> [ ... func this arg1 ... argN _Args length ] */
55225 len = (duk_idx_t) duk_require_int(ctx, -1);
55226 duk_pop(ctx);
55227 for (i = 0; i < len; i++) {
55228 /* XXX: very slow - better to bulk allocate a gap, and copy
55229 * from args_array directly (we know it has a compact array
55230 * part, etc).
55231 */
55232
55233 /* [ ... func this <some bound args> arg1 ... argN _Args ] */
55234 duk_get_prop_index(ctx, -1, i);
55235 duk_insert(ctx, idx_func + 2 + i); /* idx_args = idx_func + 2 */
55236 }
55237 num_stack_args += len; /* must be updated to work properly (e.g. creation of 'arguments') */
55238 duk_pop(ctx);
55239
55240 /* [ ... func this <bound args> arg1 ... argN ] */
55241
55243 duk_replace(ctx, idx_func); /* replace in stack */
55244
55245 DUK_DDD(DUK_DDDPRINT("bound function handled, num_stack_args=%ld, idx_func=%ld, curr func=%!T",
55246 (long) num_stack_args, (long) idx_func, duk_get_tval(ctx, idx_func)));
55247 } while (--sanity > 0);
55248
55249 if (sanity == 0) {
55251 }
55252
55253 DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(ctx, idx_func)));
55254
55255#if defined(DUK_USE_ASSERTIONS)
55256 tv_func = duk_require_tval(ctx, idx_func);
55258 if (DUK_TVAL_IS_OBJECT(tv_func)) {
55259 func = DUK_TVAL_GET_OBJECT(tv_func);
55260 DUK_ASSERT(func != NULL);
55264 }
55265#endif
55266
55267 /* write back */
55268 *p_num_stack_args = num_stack_args;
55269}
55270
55271/*
55272 * Helper for setting up var_env and lex_env of an activation,
55273 * assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
55274 */
55275
55277 duk_hobject *func,
55278 duk_activation *act) {
55279 duk_tval *tv;
55280
55281 DUK_ASSERT(thr != NULL);
55282 DUK_ASSERT(func != NULL);
55283 DUK_ASSERT(act != NULL);
55286
55288 if (tv) {
55291 act->lex_env = DUK_TVAL_GET_OBJECT(tv);
55292
55294 if (tv) {
55297 act->var_env = DUK_TVAL_GET_OBJECT(tv);
55298 } else {
55299 act->var_env = act->lex_env;
55300 }
55301 } else {
55303 act->var_env = act->lex_env;
55304 }
55305
55308}
55309
55310/*
55311 * Helper for updating callee 'caller' property.
55312 */
55313
55314#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
55315DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
55316 duk_tval *tv_caller;
55317 duk_hobject *h_tmp;
55318 duk_activation *act_callee;
55319 duk_activation *act_caller;
55320
55321 DUK_ASSERT(thr != NULL);
55322 DUK_ASSERT(func != NULL);
55323 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func)); /* bound chain resolved */
55324 DUK_ASSERT(thr->callstack_top >= 1);
55325
55326 if (DUK_HOBJECT_HAS_STRICT(func)) {
55327 /* Strict functions don't get their 'caller' updated. */
55328 return;
55329 }
55330
55331 act_callee = thr->callstack + thr->callstack_top - 1;
55332 act_caller = (thr->callstack_top >= 2 ? act_callee - 1 : NULL);
55333
55334 /* XXX: check .caller writability? */
55335
55336 /* Backup 'caller' property and update its value. */
55338 if (tv_caller) {
55339 /* If caller is global/eval code, 'caller' should be set to
55340 * 'null'.
55341 *
55342 * XXX: there is no exotic flag to infer this correctly now.
55343 * The NEWENV flag is used now which works as intended for
55344 * everything (global code, non-strict eval code, and functions)
55345 * except strict eval code. Bound functions are never an issue
55346 * because 'func' has been resolved to a non-bound function.
55347 */
55348
55349 if (act_caller) {
55350 /* act_caller->func may be NULL in some finalization cases,
55351 * just treat like we don't know the caller.
55352 */
55353 if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
55354 /* Setting to NULL causes 'caller' to be set to
55355 * 'null' as desired.
55356 */
55357 act_caller = NULL;
55358 }
55359 }
55360
55361 if (DUK_TVAL_IS_OBJECT(tv_caller)) {
55362 h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
55363 DUK_ASSERT(h_tmp != NULL);
55364 act_callee->prev_caller = h_tmp;
55365
55366 /* Previous value doesn't need refcount changes because its ownership
55367 * is transferred to prev_caller.
55368 */
55369
55370 if (act_caller) {
55371 DUK_ASSERT(act_caller->func != NULL);
55372 DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
55373 DUK_TVAL_INCREF(thr, tv_caller);
55374 } else {
55375 DUK_TVAL_SET_NULL(tv_caller); /* no incref */
55376 }
55377 } else {
55378 /* 'caller' must only take on 'null' or function value */
55380 DUK_ASSERT(act_callee->prev_caller == NULL);
55381 if (act_caller && act_caller->func) {
55382 /* Tolerate act_caller->func == NULL which happens in
55383 * some finalization cases; treat like unknown caller.
55384 */
55385 DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
55386 DUK_TVAL_INCREF(thr, tv_caller);
55387 } else {
55388 DUK_TVAL_SET_NULL(tv_caller); /* no incref */
55389 }
55390 }
55391 }
55392}
55393#endif /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
55394
55395/*
55396 * Determine the effective 'this' binding and coerce the current value
55397 * on the valstack to the effective one (in-place, at idx_this).
55398 *
55399 * The current this value in the valstack (at idx_this) represents either:
55400 * - the caller's requested 'this' binding; or
55401 * - a 'this' binding accumulated from the bound function chain
55402 *
55403 * The final 'this' binding for the target function may still be
55404 * different, and is determined as described in E5 Section 10.4.3.
55405 *
55406 * For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
55407 * that the caller has provided the correct 'this' binding explicitly
55408 * when calling, i.e.:
55409 *
55410 * - global code: this=global object
55411 * - direct eval: this=copy from eval() caller's this binding
55412 * - other eval: this=global object
55413 *
55414 * Note: this function may cause a recursive function call with arbitrary
55415 * side effects, because ToObject() may be called.
55416 */
55417
55419 duk_hobject *func,
55420 duk_idx_t idx_this) {
55421 duk_context *ctx = (duk_context *) thr;
55422 duk_tval *tv_this;
55423 duk_hobject *obj_global;
55424
55425 if (func == NULL || DUK_HOBJECT_HAS_STRICT(func)) {
55426 /* Lightfuncs are always considered strict. */
55427 DUK_DDD(DUK_DDDPRINT("this binding: strict -> use directly"));
55428 return;
55429 }
55430
55431 /* XXX: byte offset */
55432 tv_this = thr->valstack_bottom + idx_this;
55433 switch (DUK_TVAL_GET_TAG(tv_this)) {
55434 case DUK_TAG_OBJECT:
55435 case DUK_TAG_LIGHTFUNC: /* lightfuncs are treated like objects and not coerced */
55436 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
55437 break;
55438 case DUK_TAG_UNDEFINED:
55439 case DUK_TAG_NULL:
55440 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
55441 obj_global = thr->builtins[DUK_BIDX_GLOBAL];
55442 /* XXX: avoid this check somehow */
55443 if (DUK_LIKELY(obj_global != NULL)) {
55444 DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
55445 DUK_TVAL_SET_OBJECT(tv_this, obj_global);
55446 DUK_HOBJECT_INCREF(thr, obj_global);
55447 } else {
55448 /* This may only happen if built-ins are being "torn down".
55449 * This behavior is out of specification scope.
55450 */
55451 DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
55452 DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
55453 DUK_TVAL_SET_UNDEFINED(tv_this); /* nothing to incref */
55454 }
55455 break;
55456 default:
55457 DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
55458 DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
55459 duk_to_object(ctx, idx_this); /* may have side effects */
55460 break;
55461 }
55462}
55463
55464/*
55465 * Shared helper for non-bound func lookup.
55466 *
55467 * Returns duk_hobject * to the final non-bound function (NULL for lightfunc).
55468 */
55469
55471 duk_idx_t idx_func,
55472 duk_idx_t *out_num_stack_args,
55473 duk_tval **out_tv_func,
55474 duk_small_uint_t call_flags) {
55475 duk_hthread *thr = (duk_hthread *) ctx;
55476 duk_tval *tv_func;
55477 duk_hobject *func;
55478
55479 for (;;) {
55480 /* Use loop to minimize code size of relookup after bound function case */
55481 tv_func = DUK_GET_TVAL_POSIDX(ctx, idx_func);
55482 DUK_ASSERT(tv_func != NULL);
55483
55484 if (DUK_TVAL_IS_OBJECT(tv_func)) {
55485 func = DUK_TVAL_GET_OBJECT(tv_func);
55486 if (!DUK_HOBJECT_IS_CALLABLE(func)) {
55487 goto not_callable_error;
55488 }
55489 if (DUK_HOBJECT_HAS_BOUND(func)) {
55490 duk__handle_bound_chain_for_call(thr, idx_func, out_num_stack_args, call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL);
55491
55492 /* The final object may be a normal function or a lightfunc.
55493 * We need to re-lookup tv_func because it may have changed
55494 * (also value stack may have been resized). Loop again to
55495 * do that; we're guaranteed not to come here again.
55496 */
55498 DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(ctx, idx_func)));
55499 continue;
55500 }
55501 } else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
55502 func = NULL;
55503 } else {
55504 goto not_callable_error;
55505 }
55506 break;
55507 }
55508
55510 DUK_TVAL_IS_LIGHTFUNC(tv_func));
55511 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
55514
55515 *out_tv_func = tv_func;
55516 return func;
55517
55518 not_callable_error:
55519 DUK_ASSERT(tv_func != NULL);
55520#if defined(DUK_USE_PARANOID_ERRORS)
55522#else
55523 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(ctx, tv_func));
55524#endif
55526 return NULL; /* never executed */
55527}
55528
55529/*
55530 * Value stack resize and stack top adjustment helper.
55531 *
55532 * XXX: This should all be merged to duk_valstack_resize_raw().
55533 */
55534
55536 duk_idx_t num_stack_args,
55537 duk_idx_t idx_args,
55538 duk_idx_t nregs,
55539 duk_idx_t nargs,
55540 duk_hobject *func) {
55541 duk_context *ctx = (duk_context *) thr;
55542 duk_size_t vs_min_size;
55543 duk_bool_t adjusted_top = 0;
55544
55545 vs_min_size = (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
55546 idx_args; /* bottom of new func */
55547
55548 if (nregs >= 0) {
55549 DUK_ASSERT(nargs >= 0);
55550 DUK_ASSERT(nregs >= nargs);
55551 vs_min_size += nregs;
55552 } else {
55553 /* 'func' wants stack "as is" */
55554 vs_min_size += num_stack_args; /* num entries of new func at entry */
55555 }
55556 if (func == NULL || DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
55557 vs_min_size += DUK_VALSTACK_API_ENTRY_MINIMUM; /* Duktape/C API guaranteed entries (on top of args) */
55558 }
55559 vs_min_size += DUK_VALSTACK_INTERNAL_EXTRA; /* + spare */
55560
55561 /* XXX: We can't resize the value stack to a size smaller than the
55562 * current top, so the order of the resize and adjusting the stack
55563 * top depends on the current vs. final size of the value stack.
55564 * The operations could be combined to avoid this, but the proper
55565 * fix is to only grow the value stack on a function call, and only
55566 * shrink it (without throwing if the shrink fails) on function
55567 * return.
55568 */
55569
55570 if (vs_min_size < (duk_size_t) (thr->valstack_top - thr->valstack)) {
55571 DUK_DDD(DUK_DDDPRINT(("final size smaller, set top before resize")));
55572
55573 DUK_ASSERT(nregs >= 0); /* can't happen when keeping current stack size */
55574 duk_set_top(ctx, idx_args + nargs); /* clamp anything above nargs */
55575 duk_set_top(ctx, idx_args + nregs); /* extend with undefined */
55576 adjusted_top = 1;
55577 }
55578
55579 (void) duk_valstack_resize_raw((duk_context *) thr,
55580 vs_min_size,
55581 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
55582 0 /* no compact */ |
55584
55585 if (!adjusted_top) {
55586 if (nregs >= 0) {
55587 DUK_ASSERT(nregs >= nargs);
55588 duk_set_top(ctx, idx_args + nargs); /* clamp anything above nargs */
55589 duk_set_top(ctx, idx_args + nregs); /* extend with undefined */
55590 }
55591 }
55592}
55593
55594/*
55595 * Manipulate value stack so that exactly 'num_stack_rets' return
55596 * values are at 'idx_retbase' in every case, assuming there are
55597 * 'rc' return values on top of stack.
55598 *
55599 * This is a bit tricky, because the called C function operates in
55600 * the same activation record and may have e.g. popped the stack
55601 * empty (below idx_retbase).
55602 */
55603
55604DUK_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) {
55605 duk_context *ctx = (duk_context *) thr;
55606 duk_idx_t idx_rcbase;
55607
55608 DUK_ASSERT(thr != NULL);
55609 DUK_ASSERT(idx_retbase >= 0);
55610 DUK_ASSERT(num_stack_rets >= 0);
55611 DUK_ASSERT(num_actual_rets >= 0);
55612
55613 idx_rcbase = duk_get_top(ctx) - num_actual_rets; /* base of known return values */
55614
55615 DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
55616 "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
55617 (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(ctx),
55618 (long) idx_retbase, (long) idx_rcbase));
55619
55620 DUK_ASSERT(idx_rcbase >= 0); /* caller must check */
55621
55622 /* Ensure space for final configuration (idx_retbase + num_stack_rets)
55623 * and intermediate configurations.
55624 */
55626 (idx_rcbase > idx_retbase ? idx_rcbase : idx_retbase) +
55627 num_stack_rets);
55628
55629 /* Chop extra retvals away / extend with undefined. */
55630 duk_set_top(ctx, idx_rcbase + num_stack_rets);
55631
55632 if (idx_rcbase >= idx_retbase) {
55633 duk_idx_t count = idx_rcbase - idx_retbase;
55634 duk_idx_t i;
55635
55636 DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
55637 "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
55638
55639 /* nuke values at idx_retbase to get the first retval (initially
55640 * at idx_rcbase) to idx_retbase
55641 */
55642
55643 DUK_ASSERT(count >= 0);
55644
55645 for (i = 0; i < count; i++) {
55646 /* XXX: inefficient; block remove primitive */
55647 duk_remove(ctx, idx_retbase);
55648 }
55649 } else {
55650 duk_idx_t count = idx_retbase - idx_rcbase;
55651 duk_idx_t i;
55652
55653 DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
55654 "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
55655
55656 /* insert 'undefined' values at idx_rcbase to get the
55657 * return values to idx_retbase
55659
55660 DUK_ASSERT(count > 0);
55661
55662 for (i = 0; i < count; i++) {
55663 /* XXX: inefficient; block insert primitive */
55664 duk_push_undefined(ctx);
55665 duk_insert(ctx, idx_rcbase);
55666 }
55667 }
55668}
55669
55670/*
55671 * Misc shared helpers.
55672 */
55673
55674/* Get valstack index for the func argument or throw if insane stack. */
55676 duk_size_t off_stack_top;
55677 duk_size_t off_stack_args;
55678 duk_size_t off_stack_all;
55679 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55680
55681 /* Argument validation and func/args offset. */
55682 off_stack_top = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack_bottom);
55683 off_stack_args = (duk_size_t) ((duk_size_t) num_stack_args * sizeof(duk_tval));
55684 off_stack_all = off_stack_args + 2 * sizeof(duk_tval);
55685 if (DUK_UNLIKELY(off_stack_all > off_stack_top)) {
55686 /* Since stack indices are not reliable, we can't do anything useful
55687 * here. Invoke the existing setjmp catcher, or if it doesn't exist,
55688 * call the fatal error handler.
55689 */
55691 return 0;
55692 }
55693 idx_func = (duk_idx_t) ((off_stack_top - off_stack_all) / sizeof(duk_tval));
55694 return idx_func;
55695}
55696
55697/*
55698 * duk_handle_call_protected() and duk_handle_call_unprotected():
55699 * call into a Duktape/C or an Ecmascript function from any state.
55700 *
55701 * Input stack (thr):
55703 * [ func this arg1 ... argN ]
55704 *
55705 * Output stack (thr):
55706 *
55707 * [ retval ] (DUK_EXEC_SUCCESS)
55708 * [ errobj ] (DUK_EXEC_ERROR (normal error), protected call)
55709 *
55710 * Even when executing a protected call an error may be thrown in rare cases
55711 * such as an insane num_stack_args argument. If there is no catchpoint for
55712 * such errors, the fatal error handler is called.
55713 *
55714 * The error handling path should be error free, even for out-of-memory
55715 * errors, to ensure safe sandboxing. (As of Duktape 1.4.0 this is not
55716 * yet the case, see XXX notes below.)
55717 */
55718
55720 duk_idx_t num_stack_args,
55721 duk_small_uint_t call_flags) {
55722 duk_context *ctx;
55723 duk_size_t entry_valstack_bottom_index;
55724 duk_size_t entry_valstack_end;
55725 duk_size_t entry_callstack_top;
55726 duk_size_t entry_catchstack_top;
55727 duk_int_t entry_call_recursion_depth;
55728 duk_hthread *entry_curr_thread;
55729 duk_uint_fast8_t entry_thread_state;
55730 duk_instr_t **entry_ptr_curr_pc;
55731 duk_jmpbuf *old_jmpbuf_ptr = NULL;
55732 duk_jmpbuf our_jmpbuf;
55733 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55734
55735 /* XXX: Multiple tv_func lookups are now avoided by making a local
55736 * copy of tv_func. Another approach would be to compute an offset
55737 * for tv_func from valstack bottom and recomputing the tv_func
55738 * pointer quickly as valstack + offset instead of calling duk_get_tval().
55739 */
55740
55741 ctx = (duk_context *) thr;
55742 DUK_UNREF(ctx);
55743 DUK_ASSERT(thr != NULL);
55745 DUK_ASSERT(num_stack_args >= 0);
55746 /* XXX: currently NULL allocations are not supported; remove if later allowed */
55747 DUK_ASSERT(thr->valstack != NULL);
55748 DUK_ASSERT(thr->callstack != NULL);
55749 DUK_ASSERT(thr->catchstack != NULL);
55750
55751 /* Argument validation and func/args offset. */
55752 idx_func = duk__get_idx_func(thr, num_stack_args);
55753
55754 /* Preliminaries, required by setjmp() handler. Must be careful not
55755 * to throw an unintended error here.
55756 */
55757
55758 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
55759#if defined(DUK_USE_PREFER_SIZE)
55760 entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
55761#else
55762 DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
55763 entry_valstack_end = thr->valstack_size;
55764#endif
55765 entry_callstack_top = thr->callstack_top;
55766 entry_catchstack_top = thr->catchstack_top;
55767 entry_call_recursion_depth = thr->heap->call_recursion_depth;
55768 entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
55769 entry_thread_state = thr->state;
55770 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
55771
55772 DUK_DD(DUK_DDPRINT("duk_handle_call_protected: thr=%p, num_stack_args=%ld, "
55773 "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
55774 "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
55775 "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
55776 "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
55777 (void *) thr,
55778 (long) num_stack_args,
55779 (unsigned long) call_flags,
55780 (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
55781 (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
55782 (long) duk_get_top(ctx),
55783 (long) idx_func,
55784 (long) (idx_func + 2),
55785 (long) thr->heap->call_recursion_depth,
55786 (long) thr->heap->call_recursion_limit,
55787 (long) entry_valstack_bottom_index,
55788 (long) entry_callstack_top,
55789 (long) entry_catchstack_top,
55790 (long) entry_call_recursion_depth,
55791 (void *) entry_curr_thread,
55792 (long) entry_thread_state));
55793
55794 old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
55795 thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
55796
55797#if defined(DUK_USE_CPP_EXCEPTIONS)
55798 try {
55799#else
55800 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
55801 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
55802#endif
55803 /* Call handling and success path. Success path exit cleans
55804 * up almost all state.
55805 */
55806 duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
55807
55808 /* Success path handles */
55809 DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
55810 DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
55811
55812 /* Longjmp state is kept clean in success path */
55814 DUK_ASSERT(thr->heap->lj.iserror == 0);
55817
55818 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
55819
55820 return DUK_EXEC_SUCCESS;
55821#if defined(DUK_USE_CPP_EXCEPTIONS)
55822 } catch (duk_internal_exception &exc) {
55823#else
55824 } else {
55825#endif
55826 /* Error; error value is in heap->lj.value1. */
55827
55828#if defined(DUK_USE_CPP_EXCEPTIONS)
55829 DUK_UNREF(exc);
55830#endif
55831
55833 entry_valstack_bottom_index,
55834 entry_valstack_end,
55835 entry_catchstack_top,
55836 entry_callstack_top,
55837 entry_call_recursion_depth,
55838 entry_curr_thread,
55839 entry_thread_state,
55840 entry_ptr_curr_pc,
55841 idx_func,
55842 old_jmpbuf_ptr);
55843
55844 /* Longjmp state is cleaned up by error handling */
55846 DUK_ASSERT(thr->heap->lj.iserror == 0);
55849 return DUK_EXEC_ERROR;
55850 }
55851#if defined(DUK_USE_CPP_EXCEPTIONS)
55852 catch (std::exception &exc) {
55853 const char *what = exc.what();
55854 if (!what) {
55855 what = "unknown";
55856 }
55857 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
55858 try {
55859 DUK_ERROR_FMT1(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
55860 } catch (duk_internal_exception exc) {
55861 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
55862 DUK_UNREF(exc);
55864 entry_valstack_bottom_index,
55865 entry_valstack_end,
55866 entry_catchstack_top,
55867 entry_callstack_top,
55868 entry_call_recursion_depth,
55869 entry_curr_thread,
55870 entry_thread_state,
55871 entry_ptr_curr_pc,
55872 idx_func,
55873 old_jmpbuf_ptr);
55874 return DUK_EXEC_ERROR;
55875 }
55876 } catch (...) {
55877 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
55878 try {
55879 DUK_ERROR_API(thr, "caught invalid c++ exception (perhaps thrown by user code)");
55880 } catch (duk_internal_exception exc) {
55881 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
55882 DUK_UNREF(exc);
55884 entry_valstack_bottom_index,
55885 entry_valstack_end,
55886 entry_catchstack_top,
55887 entry_callstack_top,
55888 entry_call_recursion_depth,
55889 entry_curr_thread,
55890 entry_thread_state,
55891 entry_ptr_curr_pc,
55892 idx_func,
55893 old_jmpbuf_ptr);
55895 }
55896 }
55897#endif
55898}
55899
55901 duk_idx_t num_stack_args,
55902 duk_small_uint_t call_flags) {
55903 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55904
55905 /* Argument validation and func/args offset. */
55906 idx_func = duk__get_idx_func(thr, num_stack_args);
55907
55908 duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
55909}
55910
55912 duk_idx_t num_stack_args,
55913 duk_small_uint_t call_flags,
55914 duk_idx_t idx_func) {
55915 duk_context *ctx;
55916 duk_size_t entry_valstack_bottom_index;
55917 duk_size_t entry_valstack_end;
55918 duk_size_t entry_callstack_top;
55919 duk_size_t entry_catchstack_top;
55920 duk_int_t entry_call_recursion_depth;
55921 duk_hthread *entry_curr_thread;
55922 duk_uint_fast8_t entry_thread_state;
55923 duk_instr_t **entry_ptr_curr_pc;
55924 duk_idx_t nargs; /* # argument registers target function wants (< 0 => "as is") */
55925 duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => "as is") */
55926 duk_hobject *func; /* 'func' on stack (borrowed reference) */
55927 duk_tval *tv_func; /* duk_tval ptr for 'func' on stack (borrowed reference) or tv_func_copy */
55928 duk_tval tv_func_copy; /* to avoid relookups */
55929 duk_activation *act;
55930 duk_hobject *env;
55931 duk_ret_t rc;
55932
55933 ctx = (duk_context *) thr;
55934 DUK_ASSERT(thr != NULL);
55936 DUK_ASSERT(ctx != NULL);
55937 DUK_ASSERT(num_stack_args >= 0);
55938 /* XXX: currently NULL allocations are not supported; remove if later allowed */
55939 DUK_ASSERT(thr->valstack != NULL);
55940 DUK_ASSERT(thr->callstack != NULL);
55941 DUK_ASSERT(thr->catchstack != NULL);
55942
55943 DUK_DD(DUK_DDPRINT("duk__handle_call_inner: num_stack_args=%ld, call_flags=0x%08lx, top=%ld",
55944 (long) num_stack_args, (long) call_flags, (long) duk_get_top(ctx)));
55945
55946 /*
55947 * Store entry state.
55948 */
55949
55950 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
55951#if defined(DUK_USE_PREFER_SIZE)
55952 entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
55953#else
55954 DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
55955 entry_valstack_end = thr->valstack_size;
55956#endif
55957 entry_callstack_top = thr->callstack_top;
55958 entry_catchstack_top = thr->catchstack_top;
55959 entry_call_recursion_depth = thr->heap->call_recursion_depth;
55960 entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
55961 entry_thread_state = thr->state;
55962 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
55963
55964 /* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
55965 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
55966 * activation when side effects occur.
55967 */
55969
55970 DUK_DD(DUK_DDPRINT("duk__handle_call_inner: thr=%p, num_stack_args=%ld, "
55971 "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
55972 "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
55973 "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
55974 "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
55975 (void *) thr,
55976 (long) num_stack_args,
55977 (unsigned long) call_flags,
55978 (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
55979 (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
55980 (long) duk_get_top(ctx),
55981 (long) idx_func,
55982 (long) (idx_func + 2),
55983 (long) thr->heap->call_recursion_depth,
55984 (long) thr->heap->call_recursion_limit,
55985 (long) entry_valstack_bottom_index,
55986 (long) entry_callstack_top,
55987 (long) entry_catchstack_top,
55988 (long) entry_call_recursion_depth,
55989 (void *) entry_curr_thread,
55990 (long) entry_thread_state));
55991
55992
55993 /*
55994 * Thread state check and book-keeping.
55995 */
55996
55997 if (thr == thr->heap->curr_thread) {
55998 /* same thread */
55999 if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
56000 /* should actually never happen, but check anyway */
56001 goto thread_state_error;
56002 }
56003 } else {
56004 /* different thread */
56005 DUK_ASSERT(thr->heap->curr_thread == NULL ||
56006 thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
56007 if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
56008 goto thread_state_error;
56009 }
56010 DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
56011 thr->state = DUK_HTHREAD_STATE_RUNNING;
56012
56013 /* Note: multiple threads may be simultaneously in the RUNNING
56014 * state, but not in the same "resume chain".
56015 */
56016 }
56017 DUK_ASSERT(thr->heap->curr_thread == thr);
56019
56020 /*
56021 * C call recursion depth check, which provides a reasonable upper
56022 * bound on maximum C stack size (arbitrary C stack growth is only
56023 * possible by recursive handle_call / handle_safe_call calls).
56024 */
56025
56026 /* XXX: remove DUK_CALL_FLAG_IGNORE_RECLIMIT flag: there's now the
56027 * reclimit bump?
56028 */
56029
56030 DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
56031 DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
56032 if (call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) {
56033 DUK_DD(DUK_DDPRINT("ignoring reclimit for this call (probably an errhandler call)"));
56034 } else {
56035 if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit) {
56036 /* XXX: error message is a bit misleading: we reached a recursion
56037 * limit which is also essentially the same as a C callstack limit
56038 * (except perhaps with some relaxed threading assumptions).
56039 */
56041 }
56042 thr->heap->call_recursion_depth++;
56043 }
56044
56045 /*
56046 * Check the function type, handle bound function chains, and prepare
56047 * parameters for the rest of the call handling. Also figure out the
56048 * effective 'this' binding, which replaces the current value at
56049 * idx_func + 1.
56050 *
56051 * If the target function is a 'bound' one, follow the chain of 'bound'
56052 * functions until a non-bound function is found. During this process,
56053 * bound arguments are 'prepended' to existing ones, and the "this"
56054 * binding is overridden. See E5 Section 15.3.4.5.1.
56055 *
56056 * Lightfunc detection happens here too. Note that lightweight functions
56057 * can be wrapped by (non-lightweight) bound functions so we must resolve
56058 * the bound function chain first.
56059 */
56060
56061 func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
56062 DUK_TVAL_SET_TVAL(&tv_func_copy, tv_func);
56063 tv_func = &tv_func_copy; /* local copy to avoid relookups */
56064
56065 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
56068
56069 duk__coerce_effective_this_binding(thr, func, idx_func + 1);
56070 DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
56071 (duk_tval *) duk_get_tval(ctx, idx_func + 1)));
56072
56073 /* [ ... func this arg1 ... argN ] */
56074
56075 /*
56076 * Setup a preliminary activation and figure out nargs/nregs.
56077 *
56078 * Don't touch valstack_bottom or valstack_top yet so that Duktape API
56079 * calls work normally.
56080 */
56081
56083
56084 if (thr->callstack_top > 0) {
56085 /*
56086 * Update idx_retval of current activation.
56087 *
56088 * Although it might seem this is not necessary (bytecode executor
56089 * does this for Ecmascript-to-Ecmascript calls; other calls are
56090 * handled here), this turns out to be necessary for handling yield
56091 * and resume. For them, an Ecmascript-to-native call happens, and
56092 * the Ecmascript call's idx_retval must be set for things to work.
56093 */
56094
56095 (thr->callstack + thr->callstack_top - 1)->idx_retval = entry_valstack_bottom_index + idx_func;
56096 }
56097
56098 DUK_ASSERT(thr->callstack_top < thr->callstack_size);
56099 act = thr->callstack + thr->callstack_top;
56100 thr->callstack_top++;
56101 DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
56102 DUK_ASSERT(thr->valstack_top > thr->valstack_bottom); /* at least effective 'this' */
56103 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
56104
56105 act->flags = 0;
56106
56107 /* For now all calls except Ecma-to-Ecma calls prevent a yield. */
56109 if (call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) {
56111 }
56112 if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
56114 }
56115
56116 /* These base values are never used, but if the compiler doesn't know
56117 * that DUK_ERROR() won't return, these are needed to silence warnings.
56118 * On the other hand, scan-build will warn about the values not being
56119 * used, so add a DUK_UNREF.
56120 */
56121 nargs = 0; DUK_UNREF(nargs);
56122 nregs = 0; DUK_UNREF(nregs);
56123
56124 if (DUK_LIKELY(func != NULL)) {
56125 if (DUK_HOBJECT_HAS_STRICT(func)) {
56126 act->flags |= DUK_ACT_FLAG_STRICT;
56127 }
56129 nargs = ((duk_hcompiledfunction *) func)->nargs;
56130 nregs = ((duk_hcompiledfunction *) func)->nregs;
56131 DUK_ASSERT(nregs >= nargs);
56132 } else if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
56133 /* Note: nargs (and nregs) may be negative for a native,
56134 * function, which indicates that the function wants the
56135 * input stack "as is" (i.e. handles "vararg" arguments).
56136 */
56137 nargs = ((duk_hnativefunction *) func)->nargs;
56138 nregs = nargs;
56139 } else {
56140 /* XXX: this should be an assert */
56142 }
56143 } else {
56144 duk_small_uint_t lf_flags;
56145
56147 lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
56148 nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
56149 if (nargs == DUK_LFUNC_NARGS_VARARGS) {
56150 nargs = -1; /* vararg */
56151 }
56152 nregs = nargs;
56153
56154 act->flags |= DUK_ACT_FLAG_STRICT;
56155 }
56156
56157 act->func = func; /* NULL for lightfunc */
56158 act->var_env = NULL;
56159 act->lex_env = NULL;
56160#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
56161 act->prev_caller = NULL;
56162#endif
56163 act->curr_pc = NULL;
56164#if defined(DUK_USE_DEBUGGER_SUPPORT)
56165 act->prev_line = 0;
56166#endif
56167 act->idx_bottom = entry_valstack_bottom_index + idx_func + 2;
56168#if 0 /* topmost activation idx_retval is considered garbage, no need to init */
56169 act->idx_retval = 0;
56170#endif
56171 DUK_TVAL_SET_TVAL(&act->tv_func, tv_func); /* borrowed, no refcount */
56172
56173 /* XXX: remove the preventcount and make yield walk the callstack?
56174 * Or perhaps just use a single flag, not a counter, faster to just
56175 * set and restore?
56176 */
56177 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
56178 /* duk_hthread_callstack_unwind() will decrease this on unwind */
56179 thr->callstack_preventcount++;
56180 }
56181
56182 /* XXX: Is this INCREF necessary? 'func' is always a borrowed
56183 * reference reachable through the value stack? If changed, stack
56184 * unwind code also needs to be fixed to match.
56185 */
56186 DUK_HOBJECT_INCREF_ALLOWNULL(thr, func); /* act->func */
56187
56188#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
56189 if (func) {
56190 duk__update_func_caller_prop(thr, func);
56191 }
56192 act = thr->callstack + thr->callstack_top - 1;
56193#endif
56194
56195 /* [ ... func this arg1 ... argN ] */
56196
56197 /*
56198 * Environment record creation and 'arguments' object creation.
56199 * Named function expression name binding is handled by the
56200 * compiler; the compiled function's parent env will contain
56201 * the (immutable) binding already.
56202 *
56203 * This handling is now identical for C and Ecmascript functions.
56204 * C functions always have the 'NEWENV' flag set, so their
56205 * environment record initialization is delayed (which is good).
56206 *
56207 * Delayed creation (on demand) is handled in duk_js_var.c.
56208 */
56209
56210 DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func)); /* bound function chain has already been resolved */
56211
56212 if (DUK_LIKELY(func != NULL)) {
56215 /* Use a new environment but there's no 'arguments' object;
56216 * delayed environment initialization. This is the most
56217 * common case.
56218 */
56219 DUK_ASSERT(act->lex_env == NULL);
56220 DUK_ASSERT(act->var_env == NULL);
56221 } else {
56222 /* Use a new environment and there's an 'arguments' object.
56223 * We need to initialize it right now.
56224 */
56225
56226 /* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
56228 DUK_ASSERT(env != NULL);
56229
56230 /* [ ... func this arg1 ... argN envobj ] */
56231
56233 duk__handle_createargs_for_call(thr, func, env, num_stack_args);
56234
56235 /* [ ... func this arg1 ... argN envobj ] */
56236
56237 act = thr->callstack + thr->callstack_top - 1;
56238 act->lex_env = env;
56239 act->var_env = env;
56240 DUK_HOBJECT_INCREF(thr, env);
56241 DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (2) directly */
56242 duk_pop(ctx);
56243 }
56244 } else {
56245 /* Use existing env (e.g. for non-strict eval); cannot have
56246 * an own 'arguments' object (but can refer to an existing one).
56247 */
56248
56250
56251 duk__handle_oldenv_for_call(thr, func, act);
56252
56253 DUK_ASSERT(act->lex_env != NULL);
56254 DUK_ASSERT(act->var_env != NULL);
56255 }
56256 } else {
56257 /* Lightfuncs are always native functions and have "newenv". */
56258 DUK_ASSERT(act->lex_env == NULL);
56259 DUK_ASSERT(act->var_env == NULL);
56260 }
56261
56262 /* [ ... func this arg1 ... argN ] */
56263
56264 /*
56265 * Setup value stack: clamp to 'nargs', fill up to 'nregs'
56266 *
56267 * Value stack may either grow or shrink, depending on the
56268 * number of func registers and the number of actual arguments.
56269 * If nregs >= 0, func wants args clamped to 'nargs'; else it
56270 * wants all args (= 'num_stack_args').
56271 */
56272
56273 /* XXX: optimize value stack operation */
56274 /* XXX: don't want to shrink allocation here */
56275
56277 num_stack_args,
56278 idx_func + 2,
56279 nregs,
56280 nargs,
56281 func);
56282
56283 /*
56284 * Determine call type, then finalize activation, shift to
56285 * new value stack bottom, and call the target.
56286 */
56287
56288 if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
56289 /*
56290 * Ecmascript call
56291 */
56292
56293 duk_tval *tv_ret;
56294 duk_tval *tv_funret;
56295
56296 DUK_ASSERT(func != NULL);
56299
56300 thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
56301 /* keep current valstack_top */
56302 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56303 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56304 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56305
56306 /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
56307
56308 /*
56309 * Bytecode executor call.
56310 *
56311 * Execute bytecode, handling any recursive function calls and
56312 * thread resumptions. Returns when execution would return from
56313 * the entry level activation. When the executor returns, a
56314 * single return value is left on the stack top.
56315 *
56316 * The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
56317 * other types are handled internally by the executor.
56318 */
56319
56320 /* thr->ptr_curr_pc is set by bytecode executor early on entry */
56321 DUK_ASSERT(thr->ptr_curr_pc == NULL);
56322 DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
56324 DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
56325
56326 /* Unwind. */
56327
56328 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top); /* may need unwind */
56329 DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56330 DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56331 duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56333 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56335
56336 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56337 /* keep current valstack_top */
56338 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56339 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56340 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56341 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
56342
56343 /* Return value handling. */
56344
56345 /* [ ... func this (crud) retval ] */
56346
56347 tv_ret = thr->valstack_bottom + idx_func;
56348 tv_funret = thr->valstack_top - 1;
56349#if defined(DUK_USE_FASTINT)
56350 /* Explicit check for fastint downgrade. */
56351 DUK_TVAL_CHKFAST_INPLACE(tv_funret);
56352#endif
56353 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
56354 } else {
56355 /*
56356 * Native call.
56357 */
56358
56359 duk_tval *tv_ret;
56360 duk_tval *tv_funret;
56361
56362 thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
56363 /* keep current valstack_top */
56364 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56365 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56366 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56367 DUK_ASSERT(func == NULL || ((duk_hnativefunction *) func)->func != NULL);
56368
56369 /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
56370
56371 /* For native calls must be NULL so we don't sync back */
56372 DUK_ASSERT(thr->ptr_curr_pc == NULL);
56373
56374 if (func) {
56375 rc = ((duk_hnativefunction *) func)->func((duk_context *) thr);
56376 } else {
56378 rc = funcptr((duk_context *) thr);
56379 }
56380
56381 /* Automatic error throwing, retval check. */
56382
56383 if (rc < 0) {
56386 } else if (rc > 1) {
56387 DUK_ERROR_API(thr, "c function returned invalid rc");
56388 }
56389 DUK_ASSERT(rc == 0 || rc == 1);
56390
56391 /* Unwind. */
56392
56393 DUK_ASSERT(thr->catchstack_top == entry_catchstack_top); /* no need to unwind */
56394 DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56395 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56397
56398 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56399 /* keep current valstack_top */
56400 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56401 DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56402 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56403 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
56404
56405 /* Return value handling. */
56406
56407 /* XXX: should this happen in the callee's activation or after unwinding? */
56408 tv_ret = thr->valstack_bottom + idx_func;
56409 if (rc == 0) {
56410 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv_ret); /* side effects */
56411 } else {
56412 /* [ ... func this (crud) retval ] */
56413 tv_funret = thr->valstack_top - 1;
56414#if defined(DUK_USE_FASTINT)
56415 /* Explicit check for fastint downgrade. */
56416 DUK_TVAL_CHKFAST_INPLACE(tv_funret);
56417#endif
56418 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
56419 }
56420 }
56421
56422 duk_set_top(ctx, idx_func + 1); /* XXX: unnecessary, handle in adjust */
56423
56424 /* [ ... retval ] */
56425
56426 /* Ensure there is internal valstack spare before we exit; this may
56427 * throw an alloc error. The same guaranteed size must be available
56428 * as before the call. This is not optimal now: we store the valstack
56429 * allocated size during entry; this value may be higher than the
56430 * minimal guarantee for an application.
56431 */
56432
56433 /* XXX: we should never shrink here; when we error out later, we'd
56434 * need to potentially grow the value stack in error unwind which could
56435 * cause another error.
56436 */
56437
56438 (void) duk_valstack_resize_raw((duk_context *) thr,
56439 entry_valstack_end, /* same as during entry */
56440 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
56443
56444 /* Restore entry thread executor curr_pc stack frame pointer. */
56445 thr->ptr_curr_pc = entry_ptr_curr_pc;
56446
56447 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
56448 thr->state = (duk_uint8_t) entry_thread_state;
56449
56450 DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
56451 (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
56452 (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
56453
56454 thr->heap->call_recursion_depth = entry_call_recursion_depth;
56455
56456 /* If the debugger is active we need to force an interrupt so that
56457 * debugger breakpoints are rechecked. This is important for function
56458 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
56459 * GH-303. Only needed for success path, error path always causes a
56460 * breakpoint recheck in the executor. It would be enough to set this
56461 * only when returning to an Ecmascript activation, but setting the flag
56462 * on every return should have no ill effect.
56463 */
56464#if defined(DUK_USE_DEBUGGER_SUPPORT)
56465 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
56466 DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
56467 DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
56468 thr->interrupt_init -= thr->interrupt_counter;
56469 thr->interrupt_counter = 0;
56470 thr->heap->dbg_force_restart = 1;
56471 }
56472#endif
56473
56474#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
56475 duk__interrupt_fixup(thr, entry_curr_thread);
56476#endif
56477
56478 return;
56479
56480 thread_state_error:
56481 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for call (%ld)", (long) thr->state);
56483 return; /* never executed */
56484}
56485
56487 duk_size_t entry_valstack_bottom_index,
56488 duk_size_t entry_valstack_end,
56489 duk_size_t entry_catchstack_top,
56490 duk_size_t entry_callstack_top,
56491 duk_int_t entry_call_recursion_depth,
56492 duk_hthread *entry_curr_thread,
56493 duk_uint_fast8_t entry_thread_state,
56494 duk_instr_t **entry_ptr_curr_pc,
56495 duk_idx_t idx_func,
56496 duk_jmpbuf *old_jmpbuf_ptr) {
56497 duk_context *ctx;
56498 duk_tval *tv_ret;
56499
56500 ctx = (duk_context *) thr;
56501
56502 DUK_DDD(DUK_DDDPRINT("error caught during duk__handle_call_inner(): %!T",
56503 (duk_tval *) &thr->heap->lj.value1));
56504
56505 /* Other longjmp types are handled by executor before propagating
56506 * the error here.
56507 */
56509 DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
56510 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
56511
56512 /* We don't need to sync back thr->ptr_curr_pc here because
56513 * the bytecode executor always has a setjmp catchpoint which
56514 * does that before errors propagate to here.
56515 */
56516 DUK_ASSERT(thr->ptr_curr_pc == NULL);
56517
56518 /* Restore the previous setjmp catcher so that any error in
56519 * error handling will propagate outwards rather than re-enter
56520 * the same handler. However, the error handling path must be
56521 * designed to be error free so that sandboxing guarantees are
56522 * reliable, see e.g. https://github.com/svaarala/duktape/issues/476.
56523 */
56524 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56525
56526 /* XXX: callstack unwind may now throw an error when closing
56527 * scopes; this is a sandboxing issue, described in:
56528 * https://github.com/svaarala/duktape/issues/476
56529 */
56530 duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56532 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56534
56535 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56536 tv_ret = thr->valstack_bottom + idx_func; /* XXX: byte offset? */
56537 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, &thr->heap->lj.value1); /* side effects */
56538#if defined(DUK_USE_FASTINT)
56539 /* Explicit check for fastint downgrade. */
56541#endif
56542 duk_set_top(ctx, idx_func + 1); /* XXX: could be eliminated with valstack adjust */
56543
56544 /* [ ... errobj ] */
56545
56546 /* Ensure there is internal valstack spare before we exit; this may
56547 * throw an alloc error. The same guaranteed size must be available
56548 * as before the call. This is not optimal now: we store the valstack
56549 * allocated size during entry; this value may be higher than the
56550 * minimal guarantee for an application.
56551 */
56552
56553 /* XXX: this needs to be reworked so that we never shrink the value
56554 * stack on function entry so that we never need to grow it here.
56555 * Needing to grow here is a sandboxing issue because we need to
56556 * allocate which may cause an error in the error handling path
56557 * and thus propagate an error out of a protected call.
56558 */
56559
56560 (void) duk_valstack_resize_raw((duk_context *) thr,
56561 entry_valstack_end, /* same as during entry */
56562 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
56565
56566
56567 /* These are just convenience "wiping" of state. Side effects should
56568 * not be an issue here: thr->heap and thr->heap->lj have a stable
56569 * pointer. Finalizer runs etc capture even out-of-memory errors so
56570 * nothing should throw here.
56571 */
56573 thr->heap->lj.iserror = 0;
56574 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
56575 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
56576
56577 /* Restore entry thread executor curr_pc stack frame pointer. */
56578 thr->ptr_curr_pc = entry_ptr_curr_pc;
56579
56580 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
56581 thr->state = (duk_uint8_t) entry_thread_state;
56582
56583 DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
56584 (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
56585 (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
56586
56587 thr->heap->call_recursion_depth = entry_call_recursion_depth;
56588
56589 /* If the debugger is active we need to force an interrupt so that
56590 * debugger breakpoints are rechecked. This is important for function
56591 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
56592 * GH-303. Only needed for success path, error path always causes a
56593 * breakpoint recheck in the executor. It would be enough to set this
56594 * only when returning to an Ecmascript activation, but setting the flag
56595 * on every return should have no ill effect.
56596 */
56597#if defined(DUK_USE_DEBUGGER_SUPPORT)
56598 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
56599 DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
56600 DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
56601 thr->interrupt_init -= thr->interrupt_counter;
56602 thr->interrupt_counter = 0;
56603 thr->heap->dbg_force_restart = 1;
56604 }
56605#endif
56606
56607#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
56608 duk__interrupt_fixup(thr, entry_curr_thread);
56609#endif
56610}
56611
56612/*
56613 * duk_handle_safe_call(): make a "C protected call" within the
56614 * current activation.
56615 *
56616 * The allowed thread states for making a call are the same as for
56617 * duk_handle_call_xxx().
56618 *
56619 * Error handling is similar to duk_handle_call_xxx(); errors may be thrown
56620 * (and result in a fatal error) for insane arguments.
56621 */
56622
56623/* XXX: bump preventcount by one for the duration of this call? */
56624
56627 duk_idx_t num_stack_args,
56628 duk_idx_t num_stack_rets) {
56629 duk_context *ctx = (duk_context *) thr;
56630 duk_size_t entry_valstack_bottom_index;
56631 duk_size_t entry_callstack_top;
56632 duk_size_t entry_catchstack_top;
56633 duk_int_t entry_call_recursion_depth;
56634 duk_hthread *entry_curr_thread;
56635 duk_uint_fast8_t entry_thread_state;
56636 duk_instr_t **entry_ptr_curr_pc;
56637 duk_jmpbuf *old_jmpbuf_ptr = NULL;
56638 duk_jmpbuf our_jmpbuf;
56639 duk_idx_t idx_retbase;
56640 duk_int_t retval;
56641
56642 DUK_ASSERT(thr != NULL);
56643 DUK_ASSERT(ctx != NULL);
56644
56645 /* Note: careful with indices like '-x'; if 'x' is zero, it refers to bottom */
56646 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
56647 entry_callstack_top = thr->callstack_top;
56648 entry_catchstack_top = thr->catchstack_top;
56649 entry_call_recursion_depth = thr->heap->call_recursion_depth;
56650 entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
56651 entry_thread_state = thr->state;
56652 entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
56653 idx_retbase = duk_get_top(ctx) - num_stack_args; /* Note: not a valid stack index if num_stack_args == 0 */
56654
56655 /* Note: cannot portably debug print a function pointer, hence 'func' not printed! */
56656 DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
56657 "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
56658 "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
56659 "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
56660 (void *) thr,
56661 (long) num_stack_args,
56662 (long) num_stack_rets,
56663 (long) duk_get_top(ctx),
56664 (long) idx_retbase,
56665 (long) thr->heap->call_recursion_depth,
56666 (long) thr->heap->call_recursion_limit,
56667 (long) entry_valstack_bottom_index,
56668 (long) entry_callstack_top,
56669 (long) entry_catchstack_top,
56670 (long) entry_call_recursion_depth,
56671 (void *) entry_curr_thread,
56672 (long) entry_thread_state));
56673
56674 if (idx_retbase < 0) {
56675 /* Since stack indices are not reliable, we can't do anything useful
56676 * here. Invoke the existing setjmp catcher, or if it doesn't exist,
56677 * call the fatal error handler.
56678 */
56679
56681 }
56682
56683 /* setjmp catchpoint setup */
56684
56685 old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
56686 thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
56687
56688#if defined(DUK_USE_CPP_EXCEPTIONS)
56689 try {
56690#else
56691 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
56692 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
56693 /* Success path. */
56694#endif
56695 DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
56696
56698 func,
56699 idx_retbase,
56700 num_stack_rets,
56701 entry_valstack_bottom_index,
56702 entry_callstack_top,
56703 entry_catchstack_top);
56704
56705 /* Longjmp state is kept clean in success path */
56706 DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
56707 DUK_ASSERT(thr->heap->lj.iserror == 0);
56708 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
56709 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
56710
56711 /* Note: either pointer may be NULL (at entry), so don't assert */
56712 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56713
56714 retval = DUK_EXEC_SUCCESS;
56715#if defined(DUK_USE_CPP_EXCEPTIONS)
56716 } catch (duk_internal_exception &exc) {
56717 DUK_UNREF(exc);
56718#else
56719 } else {
56720 /* Error path. */
56721#endif
56723 idx_retbase,
56724 num_stack_rets,
56725 entry_valstack_bottom_index,
56726 entry_callstack_top,
56727 entry_catchstack_top,
56728 old_jmpbuf_ptr);
56729
56730 /* Longjmp state is cleaned up by error handling */
56731 DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
56732 DUK_ASSERT(thr->heap->lj.iserror == 0);
56733 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
56734 DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
56735
56736 retval = DUK_EXEC_ERROR;
56737 }
56738#if defined(DUK_USE_CPP_EXCEPTIONS)
56739 catch (std::exception &exc) {
56740 const char *what = exc.what();
56741 if (!what) {
56742 what = "unknown";
56743 }
56744 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
56745 try {
56746 DUK_ERROR_FMT1(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
56747 } catch (duk_internal_exception exc) {
56748 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
56749 DUK_UNREF(exc);
56751 idx_retbase,
56752 num_stack_rets,
56753 entry_valstack_bottom_index,
56754 entry_callstack_top,
56755 entry_catchstack_top,
56756 old_jmpbuf_ptr);
56757 retval = DUK_EXEC_ERROR;
56758 }
56759 } catch (...) {
56760 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
56761 try {
56762 DUK_ERROR_API(thr, "caught invalid c++ exception (perhaps thrown by user code)");
56763 } catch (duk_internal_exception exc) {
56764 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
56765 DUK_UNREF(exc);
56767 idx_retbase,
56768 num_stack_rets,
56769 entry_valstack_bottom_index,
56770 entry_callstack_top,
56771 entry_catchstack_top,
56772 old_jmpbuf_ptr);
56773 retval = DUK_EXEC_ERROR;
56775 }
56776#endif
56777
56778 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr); /* success/error path both do this */
56779
56781 idx_retbase,
56782 num_stack_rets,
56783 entry_call_recursion_depth,
56784 entry_curr_thread,
56785 entry_thread_state,
56786 entry_ptr_curr_pc);
56787
56788 return retval;
56789}
56790
56793 duk_idx_t idx_retbase,
56794 duk_idx_t num_stack_rets,
56795 duk_size_t entry_valstack_bottom_index,
56796 duk_size_t entry_callstack_top,
56797 duk_size_t entry_catchstack_top) {
56798 duk_context *ctx;
56799 duk_ret_t rc;
56800
56801 DUK_ASSERT(thr != NULL);
56802 ctx = (duk_context *) thr;
56804 DUK_UNREF(entry_valstack_bottom_index);
56805 DUK_UNREF(entry_callstack_top);
56806 DUK_UNREF(entry_catchstack_top);
56807
56808 /*
56809 * Thread state check and book-keeping.
56810 */
56811
56812 if (thr == thr->heap->curr_thread) {
56813 /* same thread */
56814 if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
56815 /* should actually never happen, but check anyway */
56816 goto thread_state_error;
56817 }
56818 } else {
56819 /* different thread */
56820 DUK_ASSERT(thr->heap->curr_thread == NULL ||
56822 if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
56823 goto thread_state_error;
56824 }
56825 DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
56827
56828 /* Note: multiple threads may be simultaneously in the RUNNING
56829 * state, but not in the same "resume chain".
56830 */
56831 }
56832
56833 DUK_ASSERT(thr->heap->curr_thread == thr);
56835
56836 /*
56837 * Recursion limit check.
56838 *
56839 * Note: there is no need for an "ignore recursion limit" flag
56840 * for duk_handle_safe_call now.
56841 */
56842
56846 /* XXX: error message is a bit misleading: we reached a recursion
56847 * limit which is also essentially the same as a C callstack limit
56848 * (except perhaps with some relaxed threading assumptions).
56849 */
56851 }
56852 thr->heap->call_recursion_depth++;
56853
56854 /*
56855 * Valstack spare check
56856 */
56857
56858 duk_require_stack(ctx, 0); /* internal spare */
56859
56860 /*
56861 * Make the C call
56862 */
56863
56864 rc = func(ctx);
56865
56866 DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
56867
56868 /*
56869 * Valstack manipulation for results.
56870 */
56871
56872 /* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
56873 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
56874 DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);
56875 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56876 DUK_ASSERT((duk_size_t) (thr->valstack_bottom - thr->valstack) == entry_valstack_bottom_index);
56878 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56879
56880 if (rc < 0) {
56882 }
56883 DUK_ASSERT(rc >= 0);
56884
56885 if (duk_get_top(ctx) < rc) {
56886 DUK_ERROR_API(thr, "not enough stack values for safe_call rc");
56887 }
56888
56889 DUK_ASSERT(thr->catchstack_top == entry_catchstack_top); /* no need to unwind */
56890 DUK_ASSERT(thr->callstack_top == entry_callstack_top);
56891
56892 duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);
56893 return;
56894
56895 thread_state_error:
56896 DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for safe_call (%ld)", (long) thr->state);
56898}
56899
56901 duk_idx_t idx_retbase,
56902 duk_idx_t num_stack_rets,
56903 duk_size_t entry_valstack_bottom_index,
56904 duk_size_t entry_callstack_top,
56905 duk_size_t entry_catchstack_top,
56906 duk_jmpbuf *old_jmpbuf_ptr) {
56907 duk_context *ctx;
56908
56909 DUK_ASSERT(thr != NULL);
56910 ctx = (duk_context *) thr;
56912
56913 /*
56914 * Error during call. The error value is at heap->lj.value1.
56915 *
56916 * The very first thing we do is restore the previous setjmp catcher.
56917 * This means that any error in error handling will propagate outwards
56918 * instead of causing a setjmp() re-entry above.
56919 */
56920
56921 DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
56922
56923 /* Other longjmp types are handled by executor before propagating
56924 * the error here.
56925 */
56927 DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
56928 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
56929
56930 /* Note: either pointer may be NULL (at entry), so don't assert. */
56931 thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56932
56933 DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
56934 DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
56935 duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56937 duk_hthread_callstack_unwind(thr, entry_callstack_top);
56939 thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56940
56941 /* [ ... | (crud) ] */
56942
56943 /* XXX: space in valstack? see discussion in duk_handle_call_xxx(). */
56944 duk_push_tval(ctx, &thr->heap->lj.value1);
56945
56946 /* [ ... | (crud) errobj ] */
56947
56948 DUK_ASSERT(duk_get_top(ctx) >= 1); /* at least errobj must be on stack */
56949
56950 /* check that the valstack has space for the final amount and any
56951 * intermediate space needed; this is unoptimal but should be safe
56952 */
56953 duk_require_stack_top(ctx, idx_retbase + num_stack_rets); /* final configuration */
56954 duk_require_stack(ctx, num_stack_rets);
56955
56956 duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1); /* 1 = num actual 'return values' */
56957
56958 /* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
56959
56960 /* These are just convenience "wiping" of state. Side effects should
56961 * not be an issue here: thr->heap and thr->heap->lj have a stable
56962 * pointer. Finalizer runs etc capture even out-of-memory errors so
56963 * nothing should throw here.
56964 */
56966 thr->heap->lj.iserror = 0;
56967 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
56968 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
56969}
56970
56972 duk_idx_t idx_retbase,
56973 duk_idx_t num_stack_rets,
56974 duk_int_t entry_call_recursion_depth,
56975 duk_hthread *entry_curr_thread,
56976 duk_uint_fast8_t entry_thread_state,
56977 duk_instr_t **entry_ptr_curr_pc) {
56978 duk_context *ctx;
56979
56980 DUK_ASSERT(thr != NULL);
56981 ctx = (duk_context *) thr;
56983 DUK_UNREF(ctx);
56984 DUK_UNREF(idx_retbase);
56985 DUK_UNREF(num_stack_rets);
56986
56987 /* Restore entry thread executor curr_pc stack frame pointer. */
56988 thr->ptr_curr_pc = entry_ptr_curr_pc;
56989
56990 /* XXX: because we unwind stacks above, thr->heap->curr_thread is at
56991 * risk of pointing to an already freed thread. This was indeed the
56992 * case in test-bug-multithread-valgrind.c, until duk_handle_call()
56993 * was fixed to restore thr->heap->curr_thread before rethrowing an
56994 * uncaught error.
56995 */
56996 DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
56997 thr->state = (duk_uint8_t) entry_thread_state;
56998
56999 DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
57000 (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
57001 (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
57002
57003 thr->heap->call_recursion_depth = entry_call_recursion_depth;
57004
57005 /* stack discipline consistency check */
57006 DUK_ASSERT(duk_get_top(ctx) == idx_retbase + num_stack_rets);
57007
57008 /* A debugger forced interrupt check is not needed here, as
57009 * problematic safe calls are not caused by side effects.
57010 */
57011
57012#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
57013 duk__interrupt_fixup(thr, entry_curr_thread);
57014#endif
57015}
57016
57017/*
57018 * Helper for handling an Ecmascript-to-Ecmascript call or an Ecmascript
57019 * function (initial) Duktape.Thread.resume().
57020 *
57021 * Compared to normal calls handled by duk_handle_call(), there are a
57022 * bunch of differences:
57023 *
57024 * - the call is never protected
57025 * - there is no C recursion depth increase (hence an "ignore recursion
57026 * limit" flag is not applicable)
57027 * - instead of making the call, this helper just performs the thread
57028 * setup and returns; the bytecode executor then restarts execution
57029 * internally
57030 * - ecmascript functions are never 'vararg' functions (they access
57031 * varargs through the 'arguments' object)
57032 *
57033 * The callstack of the target contains an earlier Ecmascript call in case
57034 * of an Ecmascript-to-Ecmascript call (whose idx_retval is updated), or
57035 * is empty in case of an initial Duktape.Thread.resume().
57036 *
57037 * The first thing to do here is to figure out whether an ecma-to-ecma
57038 * call is actually possible. It's not always the case if the target is
57039 * a bound function; the final function may be native. In that case,
57040 * return an error so caller can fall back to a normal call path.
57041 */
57042
57044 duk_idx_t num_stack_args,
57045 duk_small_uint_t call_flags) {
57046 duk_context *ctx = (duk_context *) thr;
57047 duk_size_t entry_valstack_bottom_index;
57048 duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
57049 duk_idx_t idx_args; /* valstack index of start of args (arg1) (relative to entry valstack_bottom) */
57050 duk_idx_t nargs; /* # argument registers target function wants (< 0 => never for ecma calls) */
57051 duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => never for ecma calls) */
57052 duk_hobject *func; /* 'func' on stack (borrowed reference) */
57053 duk_tval *tv_func; /* duk_tval ptr for 'func' on stack (borrowed reference) */
57054 duk_activation *act;
57055 duk_hobject *env;
57056 duk_bool_t use_tailcall;
57057 duk_instr_t **entry_ptr_curr_pc;
57058
57059 DUK_ASSERT(thr != NULL);
57060 DUK_ASSERT(ctx != NULL);
57061 DUK_ASSERT(!((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 && (call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0));
57062
57063 /* XXX: assume these? */
57064 DUK_ASSERT(thr->valstack != NULL);
57065 DUK_ASSERT(thr->callstack != NULL);
57066 DUK_ASSERT(thr->catchstack != NULL);
57067
57068 /* no need to handle thread state book-keeping here */
57069 DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ||
57071 thr->heap->curr_thread == thr));
57072
57073 /* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
57074 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
57075 * activation when side effects occur. If we end up not making the
57076 * call we must restore the value.
57077 */
57078 entry_ptr_curr_pc = thr->ptr_curr_pc;
57080
57081 /* if a tail call:
57082 * - an Ecmascript activation must be on top of the callstack
57083 * - there cannot be any active catchstack entries
57084 */
57085#if defined(DUK_USE_ASSERTIONS)
57086 if (call_flags & DUK_CALL_FLAG_IS_TAILCALL) {
57087 duk_size_t our_callstack_index;
57088 duk_size_t i;
57089
57090 DUK_ASSERT(thr->callstack_top >= 1);
57091 our_callstack_index = thr->callstack_top - 1;
57092 DUK_ASSERT_DISABLE(our_callstack_index >= 0);
57093 DUK_ASSERT(our_callstack_index < thr->callstack_size);
57094 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index) != NULL);
57096
57097 /* No entry in the catchstack which would actually catch a
57098 * throw can refer to the callstack entry being reused.
57099 * There *can* be catchstack entries referring to the current
57100 * callstack entry as long as they don't catch (e.g. label sites).
57101 */
57102
57103 for (i = 0; i < thr->catchstack_top; i++) {
57104 DUK_ASSERT(thr->catchstack[i].callstack_index < our_callstack_index || /* refer to callstack entries below current */
57105 DUK_CAT_GET_TYPE(thr->catchstack + i) == DUK_CAT_TYPE_LABEL); /* or a non-catching entry */
57106 }
57107 }
57108#endif /* DUK_USE_ASSERTIONS */
57109
57110 entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
57111 /* XXX: rework */
57112 idx_func = duk_normalize_index(thr, -num_stack_args - 2);
57113 idx_args = idx_func + 2;
57114
57115 DUK_DD(DUK_DDPRINT("handle_ecma_call_setup: thr=%p, "
57116 "num_stack_args=%ld, call_flags=0x%08lx (resume=%ld, tailcall=%ld), "
57117 "idx_func=%ld, idx_args=%ld, entry_valstack_bottom_index=%ld",
57118 (void *) thr,
57119 (long) num_stack_args,
57120 (unsigned long) call_flags,
57121 (long) ((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ? 1 : 0),
57122 (long) ((call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0 ? 1 : 0),
57123 (long) idx_func,
57124 (long) idx_args,
57125 (long) entry_valstack_bottom_index));
57126
57127 if (DUK_UNLIKELY(idx_func < 0 || idx_args < 0)) {
57128 /* XXX: assert? compiler is responsible for this never happening */
57130 }
57131
57132 /*
57133 * Check the function type, handle bound function chains, and prepare
57134 * parameters for the rest of the call handling. Also figure out the
57135 * effective 'this' binding, which replaces the current value at
57136 * idx_func + 1.
57137 *
57138 * If the target function is a 'bound' one, follow the chain of 'bound'
57139 * functions until a non-bound function is found. During this process,
57140 * bound arguments are 'prepended' to existing ones, and the "this"
57141 * binding is overridden. See E5 Section 15.3.4.5.1.
57142 *
57143 * If the final target function cannot be handled by an ecma-to-ecma
57144 * call, return to the caller with a return value indicating this case.
57145 * The bound chain is resolved and the caller can resume with a plain
57146 * function call.
57147 */
57148
57149 func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
57150 if (func == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
57151 DUK_DDD(DUK_DDDPRINT("final target is a lightfunc/nativefunc, cannot do ecma-to-ecma call"));
57152 thr->ptr_curr_pc = entry_ptr_curr_pc;
57153 return 0;
57154 }
57155 /* XXX: tv_func is not actually needed */
57156
57157 DUK_ASSERT(func != NULL);
57160
57161 duk__coerce_effective_this_binding(thr, func, idx_func + 1);
57162 DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
57163 duk_get_tval(ctx, idx_func + 1)));
57164
57165 nargs = ((duk_hcompiledfunction *) func)->nargs;
57166 nregs = ((duk_hcompiledfunction *) func)->nregs;
57167 DUK_ASSERT(nregs >= nargs);
57168
57169 /* [ ... func this arg1 ... argN ] */
57170
57171 /*
57172 * Preliminary activation record and valstack manipulation.
57173 * The concrete actions depend on whether the we're dealing
57174 * with a tail call (reuse an existing activation), a resume,
57175 * or a normal call.
57176 *
57177 * The basic actions, in varying order, are:
57178 *
57179 * - Check stack size for call handling
57180 * - Grow call stack if necessary (non-tail-calls)
57181 * - Update current activation (idx_retval) if necessary
57182 * (non-tail, non-resume calls)
57183 * - Move start of args (idx_args) to valstack bottom
57184 * (tail calls)
57185 *
57186 * Don't touch valstack_bottom or valstack_top yet so that Duktape API
57187 * calls work normally.
57188 */
57189
57190 /* XXX: some overlapping code; cleanup */
57191 use_tailcall = call_flags & DUK_CALL_FLAG_IS_TAILCALL;
57192#if !defined(DUK_USE_TAILCALL)
57193 DUK_ASSERT(use_tailcall == 0); /* compiler ensures this */
57194#endif
57195 if (use_tailcall) {
57196 /* tailcall cannot be flagged to resume calls, and a
57197 * previous frame must exist
57198 */
57199 DUK_ASSERT(thr->callstack_top >= 1);
57200 DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) == 0);
57201
57202 act = thr->callstack + thr->callstack_top - 1;
57203 if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
57204 /* See: test-bug-tailcall-preventyield-assert.c. */
57205 DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENTYIELD"));
57206 use_tailcall = 0;
57207 } else if (DUK_HOBJECT_HAS_NOTAIL(func)) {
57208 DUK_D(DUK_DPRINT("tail call prevented by function having a notail flag"));
57209 use_tailcall = 0;
57210 }
57211 }
57212
57213 if (use_tailcall) {
57214 duk_tval *tv1, *tv2;
57215 duk_size_t cs_index;
57216 duk_int_t i_stk; /* must be signed for loop structure */
57217 duk_idx_t i_arg;
57218
57219 /*
57220 * Tailcall handling
57221 *
57222 * Although the callstack entry is reused, we need to explicitly unwind
57223 * the current activation (or simulate an unwind). In particular, the
57224 * current activation must be closed, otherwise something like
57225 * test-bug-reduce-judofyr.js results. Also catchstack needs be unwound
57226 * because there may be non-error-catching label entries in valid tail calls.
57227 */
57228
57229 DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
57230 (long) (thr->callstack_top - 1)));
57231
57232 /* 'act' already set above */
57233
57238
57239 /* Unwind catchstack entries referring to the callstack entry we're reusing */
57240 cs_index = thr->callstack_top - 1;
57241 DUK_ASSERT(thr->catchstack_top <= DUK_INT_MAX); /* catchstack limits */
57242 for (i_stk = (duk_int_t) (thr->catchstack_top - 1); i_stk >= 0; i_stk--) {
57243 duk_catcher *cat = thr->catchstack + i_stk;
57244 if (cat->callstack_index != cs_index) {
57245 /* 'i' is the first entry we'll keep */
57246 break;
57247 }
57248 }
57249 duk_hthread_catchstack_unwind(thr, i_stk + 1);
57250
57251 /* Unwind the topmost callstack entry before reusing it */
57252 DUK_ASSERT(thr->callstack_top > 0);
57254
57255 /* Then reuse the unwound activation; callstack was not shrunk so there is always space */
57256 thr->callstack_top++;
57258 act = thr->callstack + thr->callstack_top - 1;
57259
57260 /* Start filling in the activation */
57261 act->func = func; /* don't want an intermediate exposed state with func == NULL */
57262#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57263 act->prev_caller = NULL;
57264#endif
57265 DUK_ASSERT(func != NULL);
57267 /* don't want an intermediate exposed state with invalid pc */
57269#if defined(DUK_USE_DEBUGGER_SUPPORT)
57270 act->prev_line = 0;
57271#endif
57272 DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
57273#if defined(DUK_USE_REFERENCE_COUNTING)
57274 DUK_HOBJECT_INCREF(thr, func);
57275 act = thr->callstack + thr->callstack_top - 1; /* side effects (currently none though) */
57276#endif
57277
57278#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57279#if defined(DUK_USE_TAILCALL)
57280#error incorrect options: tail calls enabled with function caller property
57281#endif
57282 /* XXX: this doesn't actually work properly for tail calls, so
57283 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
57284 * is in use.
57285 */
57286 duk__update_func_caller_prop(thr, func);
57287 act = thr->callstack + thr->callstack_top - 1;
57288#endif
57289
57290 act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
57293
57294 DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func); /* already updated */
57295 DUK_ASSERT(act->var_env == NULL); /* already NULLed (by unwind) */
57296 DUK_ASSERT(act->lex_env == NULL); /* already NULLed (by unwind) */
57297 act->idx_bottom = entry_valstack_bottom_index; /* tail call -> reuse current "frame" */
57298 DUK_ASSERT(nregs >= 0);
57299#if 0 /* topmost activation idx_retval is considered garbage, no need to init */
57300 act->idx_retval = 0;
57301#endif
57302
57303 /*
57304 * Manipulate valstack so that args are on the current bottom and the
57305 * previous caller's 'this' binding (which is the value preceding the
57306 * current bottom) is replaced with the new 'this' binding:
57307 *
57308 * [ ... this_old | (crud) func this_new arg1 ... argN ]
57309 * --> [ ... this_new | arg1 ... argN ]
57310 *
57311 * For tail calling to work properly, the valstack bottom must not grow
57312 * here; otherwise crud would accumulate on the valstack.
57313 */
57314
57315 tv1 = thr->valstack_bottom - 1;
57316 tv2 = thr->valstack_bottom + idx_func + 1;
57317 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top); /* tv1 is -below- valstack_bottom */
57318 DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
57319 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
57320
57321 for (i_arg = 0; i_arg < idx_args; i_arg++) {
57322 /* XXX: block removal API primitive */
57323 /* Note: 'func' is popped from valstack here, but it is
57324 * already reachable from the activation.
57325 */
57326 duk_remove(ctx, 0);
57327 }
57328 idx_func = 0; DUK_UNREF(idx_func); /* really 'not applicable' anymore, should not be referenced after this */
57329 idx_args = 0;
57330
57331 /* [ ... this_new | arg1 ... argN ] */
57332 } else {
57333 DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
57334 (long) (thr->callstack_top)));
57335
57337
57338 if (call_flags & DUK_CALL_FLAG_IS_RESUME) {
57339 DUK_DDD(DUK_DDDPRINT("is resume -> no update to current activation (may not even exist)"));
57340 } else {
57341 DUK_DDD(DUK_DDDPRINT("update to current activation idx_retval"));
57343 DUK_ASSERT(thr->callstack_top >= 1);
57344 act = thr->callstack + thr->callstack_top - 1;
57347 act->idx_retval = entry_valstack_bottom_index + idx_func;
57348 }
57349
57351 act = thr->callstack + thr->callstack_top;
57352 thr->callstack_top++;
57354
57358
57359 act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
57361 0);
57362 act->func = func;
57363 act->var_env = NULL;
57364 act->lex_env = NULL;
57365#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57366 act->prev_caller = NULL;
57367#endif
57368 DUK_ASSERT(func != NULL);
57371#if defined(DUK_USE_DEBUGGER_SUPPORT)
57372 act->prev_line = 0;
57373#endif
57374 act->idx_bottom = entry_valstack_bottom_index + idx_args;
57375 DUK_ASSERT(nregs >= 0);
57376#if 0 /* topmost activation idx_retval is considered garbage, no need to init */
57377 act->idx_retval = 0;
57378#endif
57379 DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
57380
57381 DUK_HOBJECT_INCREF(thr, func); /* act->func */
57382
57383#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57384 duk__update_func_caller_prop(thr, func);
57385 act = thr->callstack + thr->callstack_top - 1;
57386#endif
57387 }
57388
57389 /* [ ... func this arg1 ... argN ] (not tail call)
57390 * [ this | arg1 ... argN ] (tail call)
57391 *
57392 * idx_args updated to match
57393 */
57394
57395 /*
57396 * Environment record creation and 'arguments' object creation.
57397 * Named function expression name binding is handled by the
57398 * compiler; the compiled function's parent env will contain
57399 * the (immutable) binding already.
57400 *
57401 * Delayed creation (on demand) is handled in duk_js_var.c.
57402 */
57403
57404 /* XXX: unify handling with native call. */
57405
57406 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func)); /* bound function chain has already been resolved */
57407
57408 if (!DUK_HOBJECT_HAS_NEWENV(func)) {
57409 /* use existing env (e.g. for non-strict eval); cannot have
57410 * an own 'arguments' object (but can refer to the existing one)
57411 */
57412
57413 duk__handle_oldenv_for_call(thr, func, act);
57414
57415 DUK_ASSERT(act->lex_env != NULL);
57416 DUK_ASSERT(act->var_env != NULL);
57417 goto env_done;
57418 }
57419
57421
57422 if (!DUK_HOBJECT_HAS_CREATEARGS(func)) {
57423 /* no need to create environment record now; leave as NULL */
57424 DUK_ASSERT(act->lex_env == NULL);
57425 DUK_ASSERT(act->var_env == NULL);
57426 goto env_done;
57427 }
57428
57429 /* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
57431 DUK_ASSERT(env != NULL);
57432
57433 /* [ ... arg1 ... argN envobj ] */
57434
57435 /* original input stack before nargs/nregs handling must be
57436 * intact for 'arguments' object
57437 */
57439 duk__handle_createargs_for_call(thr, func, env, num_stack_args);
57440
57441 /* [ ... arg1 ... argN envobj ] */
57442
57443 act = thr->callstack + thr->callstack_top - 1;
57444 act->lex_env = env;
57445 act->var_env = env;
57446 DUK_HOBJECT_INCREF(thr, act->lex_env);
57447 DUK_HOBJECT_INCREF(thr, act->var_env);
57448 duk_pop(ctx);
57449
57450 env_done:
57451 /* [ ... arg1 ... argN ] */
57452
57453 /*
57454 * Setup value stack: clamp to 'nargs', fill up to 'nregs'
57455 */
57456
57458 num_stack_args,
57459 idx_args,
57460 nregs,
57461 nargs,
57462 func);
57463
57464 /*
57465 * Shift to new valstack_bottom.
57466 */
57467
57468 thr->valstack_bottom = thr->valstack_bottom + idx_args;
57469 /* keep current valstack_top */
57470 DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
57472 DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
57473
57474 /*
57475 * Return to bytecode executor, which will resume execution from
57476 * the topmost activation.
57477 */
57478
57479 return 1;
57480}
57481#line 1 "duk_js_compiler.c"
57482/*
57483 * Ecmascript compiler.
57484 *
57485 * Parses an input string and generates a function template result.
57486 * Compilation may happen in multiple contexts (global code, eval
57487 * code, function code).
57488 *
57489 * The parser uses a traditional top-down recursive parsing for the
57490 * statement level, and an operator precedence based top-down approach
57491 * for the expression level. The attempt is to minimize the C stack
57492 * depth. Bytecode is generated directly without an intermediate
57493 * representation (tree), at the cost of needing two passes over each
57494 * function.
57495 *
57496 * The top-down recursive parser functions are named "duk__parse_XXX".
57497 *
57498 * Recursion limits are in key functions to prevent arbitrary C recursion:
57499 * function body parsing, statement parsing, and expression parsing.
57501 * See doc/compiler.rst for discussion on the design.
57502 *
57503 * A few typing notes:
57504 *
57505 * - duk_regconst_t: unsigned, no marker value for "none"
57506 * - duk_reg_t: signed, < 0 = none
57507 * - PC values: duk_int_t, negative values used as markers
57510/* include removed: duk_internal.h */
57511
57512/* if highest bit of a register number is set, it refers to a constant instead */
57513#define DUK__CONST_MARKER DUK_JS_CONST_MARKER
57514
57515/* for array and object literals */
57516#define DUK__MAX_ARRAY_INIT_VALUES 20
57517#define DUK__MAX_OBJECT_INIT_PAIRS 10
57518
57519/* XXX: hack, remove when const lookup is not O(n) */
57520#define DUK__GETCONST_MAX_CONSTS_CHECK 256
57521
57522/* These limits are based on bytecode limits. Max temps is limited
57523 * by duk_hcompiledfunction nargs/nregs fields being 16 bits.
57524 */
57525#define DUK__MAX_CONSTS DUK_BC_BC_MAX
57526#define DUK__MAX_FUNCS DUK_BC_BC_MAX
57527#define DUK__MAX_TEMPS 0xffffL
57529/* Initial bytecode size allocation. */
57530#define DUK__BC_INITIAL_INSTS 256
57532#define DUK__RECURSION_INCREASE(comp_ctx,thr) do { \
57533 DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
57534 duk__recursion_increase((comp_ctx)); \
57535 } while (0)
57536
57537#define DUK__RECURSION_DECREASE(comp_ctx,thr) do { \
57538 DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
57539 duk__recursion_decrease((comp_ctx)); \
57540 } while (0)
57541
57542/* Value stack slot limits: these are quite approximate right now, and
57543 * because they overlap in control flow, some could be eliminated.
57544 */
57545#define DUK__COMPILE_ENTRY_SLOTS 8
57546#define DUK__FUNCTION_INIT_REQUIRE_SLOTS 16
57547#define DUK__FUNCTION_BODY_REQUIRE_SLOTS 16
57548#define DUK__PARSE_STATEMENTS_SLOTS 16
57549#define DUK__PARSE_EXPR_SLOTS 16
57550
57551/* Temporary structure used to pass a stack allocated region through
57552 * duk_safe_call().
57553 */
57554typedef struct {
57555 duk_small_uint_t flags;
57556 duk_compiler_ctx comp_ctx_alloc;
57557 duk_lexer_point lex_pt_alloc;
57559
57560/*
57561 * Prototypes
57562 */
57563
57564/* lexing */
57568
57569/* function helpers */
57575
57576/* code emission */
57580#if 0 /* unused */
57581DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
57582#endif
57585#if 0 /* unused */
57586DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
57587#endif
57594DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
57595DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
57596DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
57599DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
57601DUK_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);
57605
57606/* ivalue/ispec helpers */
57616 duk_ispec *x,
57617 duk_reg_t forced_reg,
57618 duk_small_uint_t flags);
57625 duk_ivalue *x,
57626 duk_reg_t forced_reg,
57627 duk_small_uint_t flags);
57629#if 0 /* unused */
57630DUK_LOCAL_DECL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57631#endif
57635
57636/* identifier handling */
57638DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
57639
57640/* label handling */
57641DUK_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);
57643DUK_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);
57645
57646/* top-down expression parser */
57651
57652/* exprtop is the top level variant which resets nud/led counts */
57655
57656/* convenience helpers */
57657#if 0 /* unused */
57658DUK_LOCAL_DECL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57659#endif
57660#if 0 /* unused */
57661DUK_LOCAL_DECL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57662#endif
57665#if 0 /* unused */
57666DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57667#endif
57671#if 0 /* unused */
57672DUK_LOCAL_DECL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57673#endif
57676#if 0 /* unused */
57677DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57678#endif
57679
57680/* expression parsing helpers */
57685
57686/* statement parsing */
57687DUK_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);
57689DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57692DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57693DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57699DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
57701DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
57702
57703DUK_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);
57709 * Parser control values for tokens. The token table is ordered by the
57710 * DUK_TOK_XXX defines.
57712 * The binding powers are for lbp() use (i.e. for use in led() context).
57713 * Binding powers are positive for typing convenience, and bits at the
57714 * top should be reserved for flags. Binding power step must be higher
57715 * than 1 so that binding power "lbp - 1" can be used for right associative
57716 * operators. Currently a step of 2 is used (which frees one more bit for
57717 * flags).
57720/* XXX: actually single step levels would work just fine, clean up */
57722/* binding power "levels" (see doc/compiler.rst) */
57723#define DUK__BP_INVALID 0 /* always terminates led() */
57724#define DUK__BP_EOF 2
57725#define DUK__BP_CLOSING 4 /* token closes expression, e.g. ')', ']' */
57726#define DUK__BP_FOR_EXPR DUK__BP_CLOSING /* bp to use when parsing a top level Expression */
57727#define DUK__BP_COMMA 6
57728#define DUK__BP_ASSIGNMENT 8
57729#define DUK__BP_CONDITIONAL 10
57730#define DUK__BP_LOR 12
57731#define DUK__BP_LAND 14
57732#define DUK__BP_BOR 16
57733#define DUK__BP_BXOR 18
57734#define DUK__BP_BAND 20
57735#define DUK__BP_EQUALITY 22
57736#define DUK__BP_RELATIONAL 24
57737#define DUK__BP_SHIFT 26
57738#define DUK__BP_ADDITIVE 28
57739#define DUK__BP_MULTIPLICATIVE 30
57740#define DUK__BP_POSTFIX 32
57741#define DUK__BP_CALL 34
57742#define DUK__BP_MEMBER 36
57743
57744#define DUK__TOKEN_LBP_BP_MASK 0x1f
57745#define DUK__TOKEN_LBP_FLAG_NO_REGEXP (1 << 5) /* regexp literal must not follow this token */
57746#define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6) /* terminates expression; e.g. post-increment/-decrement */
57747#define DUK__TOKEN_LBP_FLAG_UNUSED (1 << 7) /* spare */
57748
57749#define DUK__TOKEN_LBP_GET_BP(x) ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
57750
57751#define DUK__MK_LBP(bp) ((bp) >> 1) /* bp is assumed to be even */
57752#define DUK__MK_LBP_FLAGS(bp,flags) (((bp) >> 1) | (flags))
57753
57754DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
57755 DUK__MK_LBP(DUK__BP_EOF), /* DUK_TOK_EOF */
57757 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BREAK */
57758 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CASE */
57759 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CATCH */
57760 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONTINUE */
57761 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEBUGGER */
57762 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEFAULT */
57763 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DELETE */
57764 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DO */
57765 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ELSE */
57766 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FINALLY */
57767 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FOR */
57768 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FUNCTION */
57769 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IF */
57770 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_IN */
57771 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_INSTANCEOF */
57772 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_NEW */
57773 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_RETURN */
57774 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SWITCH */
57776 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_THROW */
57777 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TRY */
57778 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TYPEOF */
57779 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VAR */
57780 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
57781 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VOID */
57782 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WHILE */
57783 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WITH */
57784 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CLASS */
57785 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ENUM */
57786 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXPORT */
57787 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXTENDS */
57788 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPORT */
57789 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SUPER */
57793 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_GET */
57794 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SET */
57795 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPLEMENTS */
57796 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_INTERFACE */
57797 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LET */
57798 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PACKAGE */
57799 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PRIVATE */
57800 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PROTECTED */
57801 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PUBLIC */
57802 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_STATIC */
57803 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_YIELD */
57804 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LCURLY */
57806 DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_LBRACKET */
57808 DUK__MK_LBP(DUK__BP_CALL), /* DUK_TOK_LPAREN */
57810 DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_PERIOD */
57811 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SEMICOLON */
57812 DUK__MK_LBP(DUK__BP_COMMA), /* DUK_TOK_COMMA */
57813 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LT */
57814 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GT */
57815 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LE */
57816 DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GE */
57817 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_EQ */
57818 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_NEQ */
57819 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SEQ */
57820 DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SNEQ */
57821 DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_ADD */
57822 DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_SUB */
57823 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MUL */
57824 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_DIV */
57825 DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MOD */
57826 DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_INCREMENT */
57827 DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_DECREMENT */
57828 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ALSHIFT */
57829 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ARSHIFT */
57830 DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_RSHIFT */
57831 DUK__MK_LBP(DUK__BP_BAND), /* DUK_TOK_BAND */
57832 DUK__MK_LBP(DUK__BP_BOR), /* DUK_TOK_BOR */
57833 DUK__MK_LBP(DUK__BP_BXOR), /* DUK_TOK_BXOR */
57834 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LNOT */
57835 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BNOT */
57836 DUK__MK_LBP(DUK__BP_LAND), /* DUK_TOK_LAND */
57837 DUK__MK_LBP(DUK__BP_LOR), /* DUK_TOK_LOR */
57838 DUK__MK_LBP(DUK__BP_CONDITIONAL), /* DUK_TOK_QUESTION */
57839 DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_COLON */
57840 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EQUALSIGN */
57841 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ADD_EQ */
57842 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_SUB_EQ */
57843 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MUL_EQ */
57844 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_DIV_EQ */
57845 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MOD_EQ */
57846 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ALSHIFT_EQ */
57847 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ARSHIFT_EQ */
57848 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_RSHIFT_EQ */
57849 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BAND_EQ */
57850 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BOR_EQ */
57851 DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BXOR_EQ */
57858 * Misc helpers
57860
57862 DUK_ASSERT(comp_ctx != NULL);
57863 DUK_ASSERT(comp_ctx->recursion_depth >= 0);
57864 if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
57866 }
57867 comp_ctx->recursion_depth++;
57868}
57869
57871 DUK_ASSERT(comp_ctx != NULL);
57872 DUK_ASSERT(comp_ctx->recursion_depth > 0);
57873 comp_ctx->recursion_depth--;
57874}
57875
57877 DUK_UNREF(comp_ctx);
57878 DUK_ASSERT(h != NULL);
57880}
57881
57883 DUK_ASSERT(h != NULL);
57884 return (comp_ctx->curr_func.is_strict &&
57886}
57887
57888/*
57889 * Parser duk__advance() token eating functions
57890 */
57891
57892/* XXX: valstack handling is awkward. Add a valstack helper which
57893 * avoids dup():ing; valstack_copy(src, dst)?
57894 */
57895
57897 duk_hthread *thr = comp_ctx->thr;
57898 duk_context *ctx = (duk_context *) thr;
57899 duk_bool_t regexp;
57900
57901 DUK_ASSERT(comp_ctx->curr_token.t >= 0 && comp_ctx->curr_token.t <= DUK_TOK_MAXVAL); /* MAXVAL is inclusive */
57902
57903 /*
57904 * Use current token to decide whether a RegExp can follow.
57905 *
57906 * We can use either 't' or 't_nores'; the latter would not
57907 * recognize keywords. Some keywords can be followed by a
57908 * RegExp (e.g. "return"), so using 't' is better. This is
57909 * not trivial, see doc/compiler.rst.
57910 */
57911
57912 regexp = 1;
57914 regexp = 0;
57915 }
57916 if (comp_ctx->curr_func.reject_regexp_in_adv) {
57917 comp_ctx->curr_func.reject_regexp_in_adv = 0;
57918 regexp = 0;
57919 }
57920
57921 if (expect >= 0 && comp_ctx->curr_token.t != expect) {
57922 DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
57923 (long) expect, (long) comp_ctx->curr_token.t));
57925 }
57926
57927 /* make current token the previous; need to fiddle with valstack "backing store" */
57928 DUK_MEMCPY(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
57929 duk_copy(ctx, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
57930 duk_copy(ctx, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
57931
57932 /* parse new token */
57934 &comp_ctx->curr_token,
57935 comp_ctx->curr_func.is_strict,
57936 regexp);
57937
57938 DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
57939 "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
57940 (long) comp_ctx->curr_token.t,
57941 (long) comp_ctx->curr_token.t_nores,
57942 (long) comp_ctx->curr_token.start_line,
57943 (long) comp_ctx->curr_token.lineterm,
57944 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok11_idx),
57945 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok12_idx),
57946 (long) comp_ctx->prev_token.t,
57947 (long) comp_ctx->prev_token.t_nores,
57948 (long) comp_ctx->prev_token.start_line,
57949 (long) comp_ctx->prev_token.lineterm,
57950 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok21_idx),
57951 (duk_tval *) duk_get_tval(ctx, comp_ctx->tok22_idx)));
57953
57954/* advance, expecting current token to be a specific token; parse next token in regexp context */
57956 duk__advance_helper(comp_ctx, expect);
57957}
57958
57959/* advance, whatever the current token is; parse next token in regexp context */
57960DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
57961 duk__advance_helper(comp_ctx, -1);
57962}
57963
57964/*
57965 * Helpers for duk_compiler_func.
57966 */
57967
57968/* init function state: inits valstack allocations */
57970 duk_compiler_func *func = &comp_ctx->curr_func;
57971 duk_hthread *thr = comp_ctx->thr;
57972 duk_context *ctx = (duk_context *) thr;
57973 duk_idx_t entry_top;
57974
57975 entry_top = duk_get_top(ctx);
57976
57977 DUK_MEMZERO(func, sizeof(*func)); /* intentional overlap with earlier memzero */
57978#ifdef DUK_USE_EXPLICIT_NULL_INIT
57979 func->h_name = NULL;
57980 func->h_consts = NULL;
57981 func->h_funcs = NULL;
57982 func->h_decls = NULL;
57983 func->h_labelnames = NULL;
57984 func->h_labelinfos = NULL;
57985 func->h_argnames = NULL;
57986 func->h_varmap = NULL;
57987#endif
57988
57990
57992 /* code_idx = entry_top + 0 */
57993
57994 duk_push_array(ctx);
57995 func->consts_idx = entry_top + 1;
57996 func->h_consts = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 1);
57997 DUK_ASSERT(func->h_consts != NULL);
57998
57999 duk_push_array(ctx);
58000 func->funcs_idx = entry_top + 2;
58001 func->h_funcs = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 2);
58002 DUK_ASSERT(func->h_funcs != NULL);
58003 DUK_ASSERT(func->fnum_next == 0);
58004
58005 duk_push_array(ctx);
58006 func->decls_idx = entry_top + 3;
58007 func->h_decls = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 3);
58008 DUK_ASSERT(func->h_decls != NULL);
58009
58010 duk_push_array(ctx);
58011 func->labelnames_idx = entry_top + 4;
58012 func->h_labelnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 4);
58013 DUK_ASSERT(func->h_labelnames != NULL);
58014
58016 func->labelinfos_idx = entry_top + 5;
58017 func->h_labelinfos = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 5);
58018 DUK_ASSERT(func->h_labelinfos != NULL);
58020
58021 duk_push_array(ctx);
58022 func->argnames_idx = entry_top + 6;
58023 func->h_argnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 6);
58024 DUK_ASSERT(func->h_argnames != NULL);
58025
58027 func->varmap_idx = entry_top + 7;
58028 func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 7);
58029 DUK_ASSERT(func->h_varmap != NULL);
58030}
58031
58032/* reset function state (prepare for pass 2) */
58034 duk_compiler_func *func = &comp_ctx->curr_func;
58035 duk_hthread *thr = comp_ctx->thr;
58036 duk_context *ctx = (duk_context *) thr;
58037
58038 /* reset bytecode buffer but keep current size; pass 2 will
58039 * require same amount or more.
58040 */
58041 DUK_BW_RESET_SIZE(thr, &func->bw_code);
58042
58044 /* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
58045 func->fnum_next = 0;
58046 /* duk_hobject_set_length_zero(thr, func->h_funcs); */
58048 duk_hbuffer_reset(thr, func->h_labelinfos);
58049 /* keep func->h_argnames; it is fixed for all passes */
58050
58051 /* truncated in case pass 3 needed */
58053 duk_replace(ctx, func->varmap_idx);
58054 func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, func->varmap_idx);
58055 DUK_ASSERT(func->h_varmap != NULL);
58056}
58057
58058/* cleanup varmap from any null entries, compact it, etc; returns number
58059 * of final entries after cleanup.
58060 */
58062 duk_hthread *thr = comp_ctx->thr;
58063 duk_context *ctx = (duk_context *) thr;
58064 duk_hobject *h_varmap;
58065 duk_hstring *h_key;
58066 duk_tval *tv;
58067 duk_uint32_t i, e_next;
58068 duk_int_t ret;
58069
58070 /* [ ... varmap ] */
58071
58072 h_varmap = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
58073 DUK_ASSERT(h_varmap != NULL);
58074
58075 ret = 0;
58076 e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
58077 for (i = 0; i < e_next; i++) {
58078 h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
58079 if (!h_key) {
58080 continue;
58081 }
58082
58083 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
58084
58085 /* The entries can either be register numbers or 'null' values.
58086 * Thus, no need to DECREF them and get side effects. DECREF'ing
58087 * the keys (strings) can cause memory to be freed but no side
58088 * effects as strings don't have finalizers. This is why we can
58089 * rely on the object properties not changing from underneath us.
58090 */
58091
58092 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
58093 if (!DUK_TVAL_IS_NUMBER(tv)) {
58095 DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
58096 DUK_HSTRING_DECREF(thr, h_key);
58097 /* when key is NULL, value is garbage so no need to set */
58098 } else {
58099 ret++;
58100 }
58101 }
58102
58103 duk_compact(ctx, -1);
58104
58105 return ret;
58106}
58107
58108/* convert duk_compiler_func into a function template, leaving the result
58109 * on top of stack.
58110 */
58111/* XXX: awkward and bloated asm -- use faster internal accesses */
58112DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind) {
58113 duk_compiler_func *func = &comp_ctx->curr_func;
58114 duk_hthread *thr = comp_ctx->thr;
58115 duk_context *ctx = (duk_context *) thr;
58116 duk_hcompiledfunction *h_res;
58117 duk_hbuffer_fixed *h_data;
58118 duk_size_t consts_count;
58119 duk_size_t funcs_count;
58120 duk_size_t code_count;
58121 duk_size_t code_size;
58122 duk_size_t data_size;
58123 duk_size_t i;
58124 duk_tval *p_const;
58125 duk_hobject **p_func;
58126 duk_instr_t *p_instr;
58127 duk_compiler_instr *q_instr;
58128 duk_tval *tv;
58129
58130 DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
58131
58132 /*
58133 * Push result object and init its flags
58134 */
58135
58136 /* Valstack should suffice here, required on function valstack init */
58137
58138 (void) duk_push_compiledfunction(ctx);
58139 h_res = (duk_hcompiledfunction *) DUK_GET_HOBJECT_NEGIDX(ctx, -1); /* XXX: specific getter */
58140 DUK_ASSERT(h_res != NULL);
58141
58142 if (func->is_function) {
58143 DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
58145
58146 if (!func->is_arguments_shadowed) {
58147 /* arguments object would be accessible; note that shadowing
58148 * bindings are arguments or function declarations, neither
58149 * of which are deletable, so this is safe.
58150 */
58151
58152 if (func->id_access_arguments || func->may_direct_eval) {
58153 DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
58154 "indirectly -> set CREATEARGS"));
58156 }
58157 }
58158 } else if (func->is_eval && func->is_strict) {
58159 DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
58161 } else {
58162 /* non-strict eval: env is caller's env or global env (direct vs. indirect call)
58163 * global code: env is is global env
58164 */
58165 DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
58167 }
58168
58169 if (func->is_function && !func->is_decl && func->h_name != NULL && !force_no_namebind) {
58170 /* Object literal set/get functions have a name (property
58171 * name) but must not have a lexical name binding, see
58172 * test-bug-getset-func-name.js.
58173 */
58174 DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
58176 }
58177
58178 if (func->is_strict) {
58179 DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
58181 }
58182
58183 if (func->is_notail) {
58184 DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
58186 }
58187
58188 /*
58189 * Build function fixed size 'data' buffer, which contains bytecode,
58190 * constants, and inner function references.
58191 *
58192 * During the building phase 'data' is reachable but incomplete.
58193 * Only incref's occur during building (no refzero or GC happens),
58194 * so the building process is atomic.
58195 */
58196
58197 consts_count = duk_hobject_get_length(thr, func->h_consts);
58198 funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
58199 code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
58200 code_size = code_count * sizeof(duk_instr_t);
58201
58202 data_size = consts_count * sizeof(duk_tval) +
58203 funcs_count * sizeof(duk_hobject *) +
58204 code_size;
58205
58206 DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
58207 "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
58208 (long) consts_count, (long) funcs_count, (long) code_size,
58209 (long) consts_count, (long) sizeof(duk_tval),
58210 (long) funcs_count, (long) sizeof(duk_hobject *),
58211 (long) code_size, (long) data_size));
58212
58213 duk_push_fixed_buffer(ctx, data_size);
58214 h_data = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
58215 DUK_ASSERT(h_data != NULL);
58216
58217 DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
58218 DUK_HEAPHDR_INCREF(thr, h_data);
58219
58220 p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
58221 for (i = 0; i < consts_count; i++) {
58222 DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* const limits */
58224 DUK_ASSERT(tv != NULL);
58225 DUK_TVAL_SET_TVAL(p_const, tv);
58226 p_const++;
58227 DUK_TVAL_INCREF(thr, tv); /* may be a string constant */
58228
58229 DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
58230 }
58231
58232 p_func = (duk_hobject **) p_const;
58233 DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_res, p_func);
58234 for (i = 0; i < funcs_count; i++) {
58235 duk_hobject *h;
58236 DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX); /* func limits */
58238 DUK_ASSERT(tv != NULL);
58240 h = DUK_TVAL_GET_OBJECT(tv);
58241 DUK_ASSERT(h != NULL);
58243 *p_func++ = h;
58244 DUK_HOBJECT_INCREF(thr, h);
58245
58246 DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
58247 (void *) h, (duk_heaphdr *) h));
58248 }
58249
58250 p_instr = (duk_instr_t *) p_func;
58251 DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_res, p_instr);
58252
58253 /* copy bytecode instructions one at a time */
58254 q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
58255 for (i = 0; i < code_count; i++) {
58256 p_instr[i] = q_instr[i].ins;
58257 }
58258 /* Note: 'q_instr' is still used below */
58259
58260 DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
58261
58262 duk_pop(ctx); /* 'data' (and everything in it) is reachable through h_res now */
58263
58264 /*
58265 * Init object properties
58266 *
58267 * Properties should be added in decreasing order of access frequency.
58268 * (Not very critical for function templates.)
58269 */
58270
58271 DUK_DDD(DUK_DDDPRINT("init function properties"));
58272
58273 /* [ ... res ] */
58274
58275 /* _Varmap: omitted if function is guaranteed not to do slow path identifier
58276 * accesses or if it would turn out to be empty of actual register mappings
58277 * after a cleanup. When debugging is enabled, we always need the varmap to
58278 * be able to lookup variables at any point.
58279 */
58280#if defined(DUK_USE_DEBUGGER_SUPPORT)
58281 if (1) {
58282#else
58283 if (func->id_access_slow || /* directly uses slow accesses */
58284 func->may_direct_eval || /* may indirectly slow access through a direct eval */
58285 funcs_count > 0) { /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
58286#endif
58287 duk_int_t num_used;
58288 duk_dup(ctx, func->varmap_idx);
58289 num_used = duk__cleanup_varmap(comp_ctx);
58290 DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
58291 (duk_tval *) duk_get_tval(ctx, -1), (long) num_used));
58292
58293 if (num_used > 0) {
58295 } else {
58296 DUK_DDD(DUK_DDDPRINT("varmap is empty after cleanup -> no need to add"));
58297 duk_pop(ctx);
58298 }
58299 }
58300
58301 /* _Formals: omitted if function is guaranteed not to need a (non-strict) arguments object */
58302 if (1) {
58303 /* XXX: Add a proper condition. If formals list is omitted, recheck
58304 * handling for 'length' in duk_js_push_closure(); it currently relies
58305 * on _Formals being set. Removal may need to be conditional to debugging
58306 * being enabled/disabled too.
58307 */
58308 duk_dup(ctx, func->argnames_idx);
58310 }
58311
58312 /* name */
58313 if (func->h_name) {
58314 duk_push_hstring(ctx, func->h_name);
58316 }
58317
58318 /* _Source */
58319#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
58320 if (0) {
58321 /* XXX: Currently function source code is not stored, as it is not
58322 * required by the standard. Source code should not be stored by
58323 * default (user should enable it explicitly), and the source should
58324 * probably be compressed with a trivial text compressor; average
58325 * compression of 20-30% is quite easy to achieve even with a trivial
58326 * compressor (RLE + backwards lookup).
58327 *
58328 * Debugging needs source code to be useful: sometimes input code is
58329 * not found in files as it may be generated and then eval()'d, given
58330 * by dynamic C code, etc.
58331 *
58332 * Other issues:
58333 *
58334 * - Need tokenizer indices for start and end to substring
58335 * - Always normalize function declaration part?
58336 * - If we keep _Formals, only need to store body
58337 */
58338
58339 /*
58340 * For global or eval code this is straightforward. For functions
58341 * created with the Function constructor we only get the source for
58342 * the body and must manufacture the "function ..." part.
58343 *
58344 * For instance, for constructed functions (v8):
58345 *
58346 * > a = new Function("foo", "bar", "print(foo)");
58347 * [Function]
58348 * > a.toString()
58349 * 'function anonymous(foo,bar) {\nprint(foo)\n}'
58350 *
58351 * Similarly for e.g. getters (v8):
58352 *
58353 * > x = { get a(foo,bar) { print(foo); } }
58354 * { a: [Getter] }
58355 * > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
58356 * 'function a(foo,bar) { print(foo); }'
58357 */
58358
58359#if 0
58360 duk_push_string(ctx, "XXX");
58362#endif
58363 }
58364#endif /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
58365
58366 /* _Pc2line */
58367#if defined(DUK_USE_PC2LINE)
58368 if (1) {
58369 /*
58370 * Size-optimized pc->line mapping.
58371 */
58372
58374 duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count); /* -> pushes fixed buffer */
58376
58377 /* XXX: if assertions enabled, walk through all valid PCs
58378 * and check line mapping.
58379 */
58380 }
58381#endif /* DUK_USE_PC2LINE */
58382
58383 /* fileName */
58384 if (comp_ctx->h_filename) {
58385 /*
58386 * Source filename (or equivalent), for identifying thrown errors.
58387 */
58388
58389 duk_push_hstring(ctx, comp_ctx->h_filename);
58391 }
58392
58393 /*
58394 * Init remaining result fields
58395 *
58396 * 'nregs' controls how large a register frame is allocated.
58397 *
58398 * 'nargs' controls how many formal arguments are written to registers:
58399 * r0, ... r(nargs-1). The remaining registers are initialized to
58400 * undefined.
58401 */
58402
58403 DUK_ASSERT(func->temp_max >= 0);
58404 h_res->nregs = (duk_uint16_t) func->temp_max;
58405 h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
58406 DUK_ASSERT(h_res->nregs >= h_res->nargs); /* pass2 allocation handles this */
58407#if defined(DUK_USE_DEBUGGER_SUPPORT)
58408 h_res->start_line = (duk_uint32_t) func->min_line;
58409 h_res->end_line = (duk_uint32_t) func->max_line;
58410#endif
58411
58412 DUK_DD(DUK_DDPRINT("converted function: %!ixT",
58413 (duk_tval *) duk_get_tval(ctx, -1)));
58414
58415 /*
58416 * Compact the function template.
58417 */
58418
58419 duk_compact(ctx, -1);
58420
58421 /*
58422 * Debug dumping
58423 */
58424
58425#ifdef DUK_USE_DDDPRINT
58426 {
58428 duk_instr_t *p, *p_start, *p_end;
58429
58430 h = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
58433
58434 p = p_start;
58435 while (p < p_end) {
58436 DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld",
58437 (long) (p - p_start),
58438 (duk_instr_t) (*p),
58439 (unsigned long) (*p),
58440 (long) DUK_DEC_OP(*p),
58441 (long) DUK_DEC_OP(*p),
58442 (long) DUK_DEC_A(*p),
58443 (long) DUK_DEC_B(*p),
58444 (long) DUK_DEC_C(*p)));
58445 p++;
58446 }
58447 }
58448#endif
58449}
58450
58451/*
58452 * Code emission helpers
58453 *
58454 * Some emission helpers understand the range of target and source reg/const
58455 * values and automatically emit shuffling code if necessary. This is the
58456 * case when the slot in question (A, B, C) is used in the standard way and
58457 * for opcodes the emission helpers explicitly understand (like DUK_OP_CALL).
58458 *
58459 * The standard way is that:
58460 * - slot A is a target register
58461 * - slot B is a source register/constant
58462 * - slot C is a source register/constant
58463 *
58464 * If a slot is used in a non-standard way the caller must indicate this
58465 * somehow. If a slot is used as a target instead of a source (or vice
58466 * versa), this can be indicated with a flag to trigger proper shuffling
58467 * (e.g. DUK__EMIT_FLAG_B_IS_TARGET). If the value in the slot is not
58468 * register/const related at all, the caller must ensure that the raw value
58469 * fits into the corresponding slot so as to not trigger shuffling. The
58470 * caller must set a "no shuffle" flag to ensure compilation fails if
58471 * shuffling were to be triggered because of an internal error.
58473 * For slots B and C the raw slot size is 9 bits but one bit is reserved for
58474 * the reg/const indicator. To use the full 9-bit range for a raw value,
58475 * shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
58476 * Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
58477 *
58478 * There is call handling specific understanding in the A-B-C emitter to
58479 * convert call setup and call instructions into indirect ones if necessary.
58480 */
58482/* Code emission flags, passed in the 'opcode' field. Opcode + flags
58483 * fit into 16 bits for now, so use duk_small_uint.t.
58484 */
58485#define DUK__EMIT_FLAG_NO_SHUFFLE_A (1 << 8)
58486#define DUK__EMIT_FLAG_NO_SHUFFLE_B (1 << 9)
58487#define DUK__EMIT_FLAG_NO_SHUFFLE_C (1 << 10)
58488#define DUK__EMIT_FLAG_A_IS_SOURCE (1 << 11) /* slot A is a source (default: target) */
58489#define DUK__EMIT_FLAG_B_IS_TARGET (1 << 12) /* slot B is a target (default: source) */
58490#define DUK__EMIT_FLAG_C_IS_TARGET (1 << 13) /* slot C is a target (default: source) */
58491#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 */
58492#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT (1 << 15) /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
58493
58494/* XXX: clarify on when and where DUK__CONST_MARKER is allowed */
58495/* XXX: opcode specific assertions on when consts are allowed */
58497/* XXX: macro smaller than call? */
58499 duk_compiler_func *func;
58500 func = &comp_ctx->curr_func;
58501 return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
58502}
58503
58505 DUK_ASSERT(pc >= 0);
58506 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)));
58507 return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
58508}
58509
58510/* emit instruction; could return PC but that's not needed in the majority
58511 * of cases.
58512 */
58513DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
58514#if defined(DUK_USE_PC2LINE)
58515 duk_int_t line;
58516#endif
58517 duk_compiler_instr *instr;
58518
58519 DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
58520 (unsigned long) ins,
58521 (long) comp_ctx->curr_token.start_line,
58522 (long) comp_ctx->prev_token.start_line,
58523 (long) duk__get_current_pc(comp_ctx),
58524 (duk_instr_t) ins));
58525
58526 instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
58527 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
58528
58529#if defined(DUK_USE_PC2LINE)
58530 /* The line number tracking is a bit inconsistent right now, which
58531 * affects debugger accuracy. Mostly call sites emit opcodes when
58532 * they have parsed a token (say a terminating semicolon) and called
58533 * duk__advance(). In this case the line number of the previous
58534 * token is the most accurate one (except in prologue where
58535 * prev_token.start_line is 0). This is probably not 100% correct
58536 * right now.
58537 */
58538 /* approximation, close enough */
58539 line = comp_ctx->prev_token.start_line;
58540 if (line == 0) {
58541 line = comp_ctx->curr_token.start_line;
58542 }
58543#endif
58544
58545 instr->ins = ins;
58546#if defined(DUK_USE_PC2LINE)
58547 instr->line = line;
58548#endif
58549#if defined(DUK_USE_DEBUGGER_SUPPORT)
58550 if (line < comp_ctx->curr_func.min_line) {
58551 comp_ctx->curr_func.min_line = line;
58552 }
58553 if (line > comp_ctx->curr_func.max_line) {
58554 comp_ctx->curr_func.max_line = line;
58555 }
58556#endif
58557
58558 /* Limit checks for bytecode byte size and line number. */
58560 goto fail_bc_limit;
58561 }
58562#if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
58563#if defined(DUK_USE_BUFLEN16)
58564 /* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
58566 goto fail_bc_limit;
58567 }
58568#else
58570 goto fail_bc_limit;
58571 }
58572#endif
58573#endif
58574
58575 return;
58576
58577 fail_bc_limit:
58579}
58580
58581/* Update function min/max line from current token. Needed to improve
58582 * function line range information for debugging, so that e.g. opening
58583 * curly brace is covered by line range even when no opcodes are emitted
58584 * for the line containing the brace.
58585 */
58587#if defined(DUK_USE_DEBUGGER_SUPPORT)
58588 duk_int_t line;
58589
58590 line = comp_ctx->curr_token.start_line;
58591 if (line == 0) {
58592 return;
58593 }
58594 if (line < comp_ctx->curr_func.min_line) {
58595 comp_ctx->curr_func.min_line = line;
58596 }
58597 if (line > comp_ctx->curr_func.max_line) {
58598 comp_ctx->curr_func.max_line = line;
58599 }
58600#else
58601 DUK_UNREF(comp_ctx);
58602#endif
58603}
58604
58605#if 0 /* unused */
58606DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
58607 duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
58608}
58609#endif
58610
58611/* Important main primitive. */
58613 duk_instr_t ins = 0;
58614 duk_int_t a_out = -1;
58615 duk_int_t b_out = -1;
58616 duk_int_t c_out = -1;
58617 duk_int_t tmp;
58618
58619 DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
58620 (unsigned long) op_flags, (long) a, (long) b, (long) c));
58621
58622 /* We could rely on max temp/const checks: if they don't exceed BC
58623 * limit, nothing here can either (just asserts would be enough).
58624 * Currently we check for the limits, which provides additional
58625 * protection against creating invalid bytecode due to compiler
58626 * bugs.
58627 */
58628
58629 DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
58630 DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
58631
58632 /* Input shuffling happens before the actual operation, while output
58633 * shuffling happens afterwards. Output shuffling decisions are still
58634 * made at the same time to reduce branch clutter; output shuffle decisions
58635 * are recorded into X_out variables.
58636 */
58637
58638 /* Slot A */
58639
58640#if defined(DUK_USE_SHUFFLE_TORTURE)
58641 if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
58642#else
58643 if (a <= DUK_BC_A_MAX) {
58644#endif
58645 ;
58646 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
58647 DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
58648 goto error_outofregs;
58649 } else if (a <= DUK_BC_BC_MAX) {
58650 comp_ctx->curr_func.needs_shuffle = 1;
58651 tmp = comp_ctx->curr_func.shuffle1;
58652 if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
58653 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
58654 } else {
58655 duk_small_int_t op = op_flags & 0xff;
58656 if (op == DUK_OP_CSVAR || op == DUK_OP_CSREG || op == DUK_OP_CSPROP) {
58657 /* Special handling for call setup instructions. The target
58658 * is expressed indirectly, but there is no output shuffling.
58659 */
58660 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) == 0);
58661 duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
58665 op_flags++; /* indirect opcode follows direct */
58666 } else {
58667 /* Output shuffle needed after main operation */
58668 a_out = a;
58669 }
58670 }
58671 a = tmp;
58672 } else {
58673 DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
58674 goto error_outofregs;
58675 }
58676
58677 /* Slot B */
58678
58679 if (b & DUK__CONST_MARKER) {
58680 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
58681 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
58682 DUK_ASSERT((op_flags & 0xff) != DUK_OP_CALL);
58683 DUK_ASSERT((op_flags & 0xff) != DUK_OP_NEW);
58684 b = b & ~DUK__CONST_MARKER;
58685#if defined(DUK_USE_SHUFFLE_TORTURE)
58686 if (0) {
58687#else
58688 if (b <= 0xff) {
58689#endif
58690 ins |= DUK_ENC_OP_A_B_C(0, 0, 0x100, 0); /* const flag for B */
58691 } else if (b <= DUK_BC_BC_MAX) {
58692 comp_ctx->curr_func.needs_shuffle = 1;
58693 tmp = comp_ctx->curr_func.shuffle2;
58694 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
58695 b = tmp;
58696 } else {
58697 DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
58698 goto error_outofregs;
58699 }
58700 } else {
58701#if defined(DUK_USE_SHUFFLE_TORTURE)
58702 if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
58703#else
58704 if (b <= 0xff) {
58705#endif
58706 ;
58707 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
58708 if (b > DUK_BC_B_MAX) {
58709 /* Note: 0xff != DUK_BC_B_MAX */
58710 DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
58711 goto error_outofregs;
58712 }
58713 } else if (b <= DUK_BC_BC_MAX) {
58714 comp_ctx->curr_func.needs_shuffle = 1;
58715 tmp = comp_ctx->curr_func.shuffle2;
58716 if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
58717 /* Output shuffle needed after main operation */
58718 b_out = b;
58719 }
58720 if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET) || (op_flags & DUK__EMIT_FLAG_B_IS_TARGETSOURCE)) {
58721 duk_small_int_t op = op_flags & 0xff;
58722 if (op == DUK_OP_CALL || op == DUK_OP_NEW ||
58723 op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
58724 /* Special handling for CALL/NEW/MPUTOBJ/MPUTARR shuffling.
58725 * For each, slot B identifies the first register of a range
58726 * of registers, so normal shuffling won't work. Instead,
58727 * an indirect version of the opcode is used.
58728 */
58729 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
58730 duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
58735 op_flags++; /* indirect opcode follows direct */
58736 } else {
58737 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
58738 }
58739 }
58740 b = tmp;
58741 } else {
58742 DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
58743 goto error_outofregs;
58744 }
58745 }
58746
58747 /* Slot C */
58748
58749 if (c & DUK__CONST_MARKER) {
58750 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
58751 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
58752 c = c & ~DUK__CONST_MARKER;
58753#if defined(DUK_USE_SHUFFLE_TORTURE)
58754 if (0) {
58755#else
58756 if (c <= 0xff) {
58757#endif
58758 ins |= DUK_ENC_OP_A_B_C(0, 0, 0, 0x100); /* const flag for C */
58759 } else if (c <= DUK_BC_BC_MAX) {
58760 comp_ctx->curr_func.needs_shuffle = 1;
58761 tmp = comp_ctx->curr_func.shuffle3;
58762 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
58763 c = tmp;
58764 } else {
58765 DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
58766 goto error_outofregs;
58767 }
58768 } else {
58769#if defined(DUK_USE_SHUFFLE_TORTURE)
58770 if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
58771#else
58772 if (c <= 0xff) {
58773#endif
58774 ;
58775 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
58776 if (c > DUK_BC_C_MAX) {
58777 /* Note: 0xff != DUK_BC_C_MAX */
58778 DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
58779 goto error_outofregs;
58780 }
58781 } else if (c <= DUK_BC_BC_MAX) {
58782 comp_ctx->curr_func.needs_shuffle = 1;
58783 tmp = comp_ctx->curr_func.shuffle3;
58784 if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
58785 /* Output shuffle needed after main operation */
58786 c_out = c;
58787 } else {
58788 duk_small_int_t op = op_flags & 0xff;
58789 if (op == DUK_OP_EXTRA &&
58791 /* Special shuffling for INITGET/INITSET, where slot C
58792 * identifies a register pair and cannot be shuffled
58793 * normally. Use an indirect variant instead.
58794 */
58795 DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
58796 duk__emit_load_int32_noshuffle(comp_ctx, tmp, c);
58799 a++; /* indirect opcode follows direct */
58800 } else {
58801 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
58802 }
58803 }
58804 c = tmp;
58805 } else {
58806 DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
58807 goto error_outofregs;
58808 }
58809 }
58810
58811 /* Main operation */
58812
58813 DUK_ASSERT_DISABLE(a >= DUK_BC_A_MIN); /* unsigned */
58815 DUK_ASSERT_DISABLE(b >= DUK_BC_B_MIN); /* unsigned */
58817 DUK_ASSERT_DISABLE(c >= DUK_BC_C_MIN); /* unsigned */
58819
58820 ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
58821 duk__emit(comp_ctx, ins);
58822
58823 /* NEXTENUM needs a jump slot right after the main instruction.
58824 * When the JUMP is taken, output spilling is not needed so this
58825 * workaround is possible. The jump slot PC is exceptionally
58826 * plumbed through comp_ctx to minimize call sites.
58827 */
58828 if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
58829 comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
58830 duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
58831 }
58832
58833 /* Output shuffling: only one output register is realistically possible.
58834 *
58835 * (Zero would normally be an OK marker value: if the target register
58836 * was zero, it would never be shuffled. But with DUK_USE_SHUFFLE_TORTURE
58837 * this is no longer true, so use -1 as a marker instead.)
58838 */
58839
58840 if (a_out >= 0) {
58841 DUK_ASSERT(b_out < 0);
58842 DUK_ASSERT(c_out < 0);
58844 } else if (b_out >= 0) {
58845 DUK_ASSERT(a_out < 0);
58846 DUK_ASSERT(c_out < 0);
58847 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
58848 } else if (c_out >= 0) {
58849 DUK_ASSERT(b_out < 0);
58850 DUK_ASSERT(c_out < 0);
58851 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
58852 }
58854 return;
58855
58856 error_outofregs:
58858}
58859
58861 duk__emit_a_b_c(comp_ctx, op_flags | DUK__EMIT_FLAG_NO_SHUFFLE_C, a, b, 0);
58862}
58863
58864#if 0 /* unused */
58865DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
58867}
58868#endif
58869
58871 duk_instr_t ins;
58872 duk_int_t tmp;
58873
58874 /* allow caller to give a const number with the DUK__CONST_MARKER */
58875 bc = bc & (~DUK__CONST_MARKER);
58876
58877 DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
58878 DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
58879 DUK_ASSERT_DISABLE(bc >= DUK_BC_BC_MIN); /* unsigned */
58881 DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
58882
58883 if (bc <= DUK_BC_BC_MAX) {
58884 ;
58885 } else {
58886 /* No BC shuffling now. */
58887 goto error_outofregs;
58888 }
58889
58890#if defined(DUK_USE_SHUFFLE_TORTURE)
58891 if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
58892#else
58893 if (a <= DUK_BC_A_MAX) {
58894#endif
58895 ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
58896 duk__emit(comp_ctx, ins);
58897 } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
58898 goto error_outofregs;
58899 } else if (a <= DUK_BC_BC_MAX) {
58900 comp_ctx->curr_func.needs_shuffle = 1;
58901 tmp = comp_ctx->curr_func.shuffle1;
58902 ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
58903 if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
58904 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
58905 duk__emit(comp_ctx, ins);
58906 } else {
58907 duk__emit(comp_ctx, ins);
58908 duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
58909 }
58910 } else {
58911 goto error_outofregs;
58912 }
58913 return;
58914
58915 error_outofregs:
58917}
58918
58920 duk_instr_t ins;
58921
58922 DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN); /* unsigned */
58924 DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN); /* unsigned */
58925 DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
58926 DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
58927
58928 if (abc <= DUK_BC_ABC_MAX) {
58929 ;
58930 } else {
58931 goto error_outofregs;
58932 }
58933 ins = DUK_ENC_OP_ABC(op, abc);
58934 DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
58935 (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
58936 (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
58937 (long) abc, (duk_instr_t) ins));
58938 duk__emit(comp_ctx, ins);
58939 return;
58940
58941 error_outofregs:
58943}
58944
58946 DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58947 DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
58948 /* Setting "no shuffle A" is covered by the assert, but it's needed
58949 * with DUK_USE_SHUFFLE_TORTURE.
58950 */
58951 duk__emit_a_b_c(comp_ctx,
58952 DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff), /* transfer flags */
58953 extraop_flags & 0xff,
58955 c);
58956}
58957
58959 DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58960 DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
58961 /* Setting "no shuffle A" is covered by the assert, but it's needed
58962 * with DUK_USE_SHUFFLE_TORTURE.
58963 */
58964 duk__emit_a_b_c(comp_ctx,
58965 DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff), /* transfer flags */
58966 extraop_flags & 0xff,
58967 b,
58968 0);
58969}
58970
58972 DUK_ASSERT_DISABLE(extraop >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58973 DUK_ASSERT(extraop <= DUK_BC_EXTRAOP_MAX);
58974 /* Setting "no shuffle A" is covered by the assert, but it's needed
58975 * with DUK_USE_SHUFFLE_TORTURE.
58976 */
58977 duk__emit_a_bc(comp_ctx,
58979 extraop,
58980 bc);
58981}
58982
58984 DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN); /* unsigned */
58985 DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
58986 /* Setting "no shuffle A" is covered by the assert, but it's needed
58987 * with DUK_USE_SHUFFLE_TORTURE.
58988 */
58989 duk__emit_a_b_c(comp_ctx,
58991 DUK__EMIT_FLAG_NO_SHUFFLE_C | (extraop_flags & ~0xff), /* transfer flags */
58992 extraop_flags & 0xff,
58993 0,
58994 0);
58995}
58996
58997DUK_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) {
58998 /* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
58999 * would only shuffle once (instead of twice). The current code works
59000 * though, and has a smaller compiler footprint.
59002
59003 if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
59004 (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
59005 DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
59006 duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
59007 } else {
59008 duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
59009 duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
59010 DUK_ASSERT(lo >= 0);
59011 DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
59012 (long) reg, (long) val, (long) hi, (long) lo));
59013 duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
59014 duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
59015 }
59016}
59017
59018DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
59019 duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
59020}
59021
59022#if defined(DUK_USE_SHUFFLE_TORTURE)
59023/* Used by duk__emit*() calls so that we don't shuffle the loadints that
59024 * are needed to handle indirect opcodes.
59025 */
59026DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
59027 duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
59028}
59029#else
59030DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
59031 /* When torture not enabled, can just use the same helper because
59032 * 'reg' won't get spilled.
59034 DUK_ASSERT(reg <= DUK_BC_A_MAX);
59035 duk__emit_load_int32(comp_ctx, reg, val);
59036}
59037#endif
59038
59039DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
59040 duk_int_t curr_pc;
59041 duk_int_t offset;
59042
59043 curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
59044 offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
59048}
59049
59051 duk_int_t ret;
59052
59053 ret = duk__get_current_pc(comp_ctx); /* useful for patching jumps later */
59054 duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
59055 return ret;
59056}
59057
59058/* Insert an empty jump in the middle of code emitted earlier. This is
59059 * currently needed for compiling for-in.
59060 */
59062#if defined(DUK_USE_PC2LINE)
59063 duk_int_t line;
59064#endif
59065 duk_compiler_instr *instr;
59066 duk_size_t offset;
59067
59068 offset = jump_pc * sizeof(duk_compiler_instr),
59069 instr = (duk_compiler_instr *) (void *)
59071 &comp_ctx->curr_func.bw_code,
59072 offset,
59073 sizeof(duk_compiler_instr));
59074
59075#if defined(DUK_USE_PC2LINE)
59076 line = comp_ctx->curr_token.start_line; /* approximation, close enough */
59077#endif
59078 instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
59079#if defined(DUK_USE_PC2LINE)
59080 instr->line = line;
59081#endif
59082
59083 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
59085 goto fail_bc_limit;
59086 }
59087 return;
59088
59089 fail_bc_limit:
59091}
59092
59093/* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
59094 * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
59095 */
59096DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
59097 duk_compiler_instr *instr;
59098 duk_int_t offset;
59099
59100 /* allow negative PCs, behave as a no-op */
59101 if (jump_pc < 0) {
59102 DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
59103 (long) jump_pc, (long) target_pc));
59104 return;
59105 }
59106 DUK_ASSERT(jump_pc >= 0);
59108 /* XXX: range assert */
59109 instr = duk__get_instr_ptr(comp_ctx, jump_pc);
59110 DUK_ASSERT(instr != NULL);
59111
59112 /* XXX: range assert */
59113 offset = target_pc - jump_pc - 1;
59114
59115 instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
59116 DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
59117 (long) jump_pc, (long) target_pc, (long) offset));
59118}
59119
59121 duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
59122}
59123
59124DUK_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) {
59125 duk_compiler_instr *instr;
59126
59127 DUK_ASSERT((reg_catch & DUK__CONST_MARKER) == 0);
59128
59129 instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
59131 DUK_ASSERT(instr != NULL);
59132 if (const_varname & DUK__CONST_MARKER) {
59133 /* Have a catch variable. */
59134 const_varname = const_varname & (~DUK__CONST_MARKER);
59135 if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
59136 /* Catch attempts to use out-of-range reg/const. Without this
59137 * check Duktape 0.12.0 could generate invalid code which caused
59138 * an assert failure on execution. This error is triggered e.g.
59139 * for functions with a lot of constants and a try-catch statement.
59140 * Shuffling or opcode semantics change is needed to fix the issue.
59141 * See: test-bug-trycatch-many-constants.js.
59142 */
59143 DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
59144 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
59146 }
59147 instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
59148 } else {
59149 /* No catch variable, e.g. a try-finally; replace LDCONST with
59150 * NOP to avoid a bogus LDCONST.
59151 */
59154
59155 instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
59156 DUK_ASSERT(instr != NULL);
59158 DUK_ASSERT(flags <= DUK_BC_A_MAX);
59159 instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
59160}
59163 duk__emit_a_b_c(comp_ctx,
59165 0 /*false*/,
59166 regconst,
59167 0 /*unused*/);
59168}
59169
59171 duk__emit_a_b_c(comp_ctx,
59173 1 /*true*/,
59174 regconst,
59175 0 /*unused*/);
59176}
59177
59180}
59181
59182/*
59183 * Peephole optimizer for finished bytecode.
59184 *
59185 * Does not remove opcodes; currently only straightens out unconditional
59186 * jump chains which are generated by several control structures.
59187 */
59188
59191 duk_small_uint_t iter;
59192 duk_int_t i, n;
59193 duk_int_t count_opt;
59194
59195 bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
59196#if defined(DUK_USE_BUFLEN16)
59197 /* No need to assert, buffer size maximum is 0xffff. */
59198#else
59199 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 */
59200#endif
59201 n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
59202
59203 for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
59204 count_opt = 0;
59205
59206 for (i = 0; i < n; i++) {
59207 duk_instr_t ins;
59208 duk_int_t target_pc1;
59209 duk_int_t target_pc2;
59210
59211 ins = bc[i].ins;
59212 if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
59213 continue;
59214 }
59215
59216 target_pc1 = i + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
59217 DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
59218 DUK_ASSERT(target_pc1 >= 0);
59219 DUK_ASSERT(target_pc1 < n);
59220
59221 /* Note: if target_pc1 == i, we'll optimize a jump to itself.
59222 * This does not need to be checked for explicitly; the case
59223 * is rare and max iter breaks us out.
59224 */
59225
59226 ins = bc[target_pc1].ins;
59227 if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
59228 continue;
59229 }
59230
59231 target_pc2 = target_pc1 + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
59232
59233 DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
59234 (long) i, (long) target_pc1, (long) target_pc2));
59235
59236 bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
59238 count_opt++;
59241 DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
59243 if (count_opt == 0) {
59244 break;
59245 }
59246 }
59247}
59248
59250 * Intermediate value helpers
59252
59253#define DUK__ISREG(comp_ctx,x) (((x) & DUK__CONST_MARKER) == 0)
59254#define DUK__ISCONST(comp_ctx,x) (((x) & DUK__CONST_MARKER) != 0)
59255#define DUK__ISTEMP(comp_ctx,x) (DUK__ISREG((comp_ctx), (x)) && (duk_regconst_t) (x) >= (duk_regconst_t) ((comp_ctx)->curr_func.temp_first))
59256#define DUK__GETTEMP(comp_ctx) ((comp_ctx)->curr_func.temp_next)
59257#define DUK__SETTEMP(comp_ctx,x) ((comp_ctx)->curr_func.temp_next = (x)) /* dangerous: must only lower (temp_max not updated) */
59258#define DUK__SETTEMP_CHECKMAX(comp_ctx,x) duk__settemp_checkmax((comp_ctx),(x))
59259#define DUK__ALLOCTEMP(comp_ctx) duk__alloctemp((comp_ctx))
59260#define DUK__ALLOCTEMPS(comp_ctx,count) duk__alloctemps((comp_ctx),(count))
59261
59262/* Flags for intermediate value coercions. A flag for using a forced reg
59263 * is not needed, the forced_reg argument suffices and generates better
59264 * code (it is checked as it is used).
59265 */
59266#define DUK__IVAL_FLAG_ALLOW_CONST (1 << 0) /* allow a constant to be returned */
59267#define DUK__IVAL_FLAG_REQUIRE_TEMP (1 << 1) /* require a (mutable) temporary as a result (or a const if allowed) */
59268#define DUK__IVAL_FLAG_REQUIRE_SHORT (1 << 2) /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
59269
59270/* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(ctx,x) */
59271
59272#if 0 /* enable manually for dumping */
59273#define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
59274#define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
59276DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
59277 DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
59278 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
59280}
59281DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
59282 DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
59283 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
59284 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
59285 (long) x->t, (long) x->op,
59286 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
59288 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
59289 duk_get_tval((duk_context *) comp_ctx->thr, x->x2.valstack_idx)));
59290}
59291#else
59292#define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
59293#define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
59294#endif
59295
59296DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
59297 duk_context *ctx = (duk_context *) comp_ctx->thr;
59298
59299 dst->t = src->t;
59300 dst->regconst = src->regconst;
59301 duk_copy(ctx, src->valstack_idx, dst->valstack_idx);
59302}
59303
59305 duk_context *ctx = (duk_context *) comp_ctx->thr;
59306
59307 dst->t = src->t;
59308 dst->op = src->op;
59309 dst->x1.t = src->x1.t;
59310 dst->x1.regconst = src->x1.regconst;
59311 dst->x2.t = src->x2.t;
59312 dst->x2.regconst = src->x2.regconst;
59313 duk_copy(ctx, src->x1.valstack_idx, dst->x1.valstack_idx);
59314 duk_copy(ctx, src->x2.valstack_idx, dst->x2.valstack_idx);
59315}
59316
59317/* XXX: to util */
59320 duk_int32_t t;
59321
59322 c = DUK_FPCLASSIFY(x);
59323 if (c == DUK_FP_NORMAL || (c == DUK_FP_ZERO && !DUK_SIGNBIT(x))) {
59324 /* Don't allow negative zero as it will cause trouble with
59325 * LDINT+LDINTX. But positive zero is OK.
59326 */
59327 t = (duk_int32_t) x;
59328 if ((duk_double_t) t == x) {
59329 *ival = t;
59330 return 1;
59331 }
59332 }
59333
59334 return 0;
59335}
59336
59339
59340 res = comp_ctx->curr_func.temp_next;
59341 comp_ctx->curr_func.temp_next += num;
59343 if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) { /* == DUK__MAX_TEMPS is OK */
59345 }
59346
59347 /* maintain highest 'used' temporary, needed to figure out nregs of function */
59348 if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
59349 comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
59351
59352 return res;
59353}
59354
59356 return duk__alloctemps(comp_ctx, 1);
59357}
59358
59359DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next) {
59360 comp_ctx->curr_func.temp_next = temp_next;
59361 if (temp_next > comp_ctx->curr_func.temp_max) {
59362 comp_ctx->curr_func.temp_max = temp_next;
59363 }
59364}
59365
59366/* get const for value at valstack top */
59368 duk_hthread *thr = comp_ctx->thr;
59369 duk_context *ctx = (duk_context *) thr;
59370 duk_compiler_func *f = &comp_ctx->curr_func;
59371 duk_tval *tv1;
59372 duk_int_t i, n, n_check;
59373
59374 n = (duk_int_t) duk_get_length(ctx, f->consts_idx);
59375
59376 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
59377 DUK_ASSERT(tv1 != NULL);
59378
59379#if defined(DUK_USE_FASTINT)
59380 /* Explicit check for fastint downgrade. */
59382#endif
59383
59384 /* Sanity workaround for handling functions with a large number of
59385 * constants at least somewhat reasonably. Otherwise checking whether
59386 * we already have the constant would grow very slow (as it is O(N^2)).
59387 */
59389 for (i = 0; i < n_check; i++) {
59391
59392 /* Strict equality is NOT enough, because we cannot use the same
59393 * constant for e.g. +0 and -0.
59394 */
59395 if (duk_js_samevalue(tv1, tv2)) {
59396 DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
59397 (duk_tval *) tv1, (long) i));
59398 duk_pop(ctx);
59399 return (duk_regconst_t) (i | DUK__CONST_MARKER);
59400 }
59401 }
59402
59403 if (n > DUK__MAX_CONSTS) {
59405 }
59406
59407 DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
59408 (duk_tval *) tv1, (long) n));
59409 (void) duk_put_prop_index(ctx, f->consts_idx, n); /* invalidates tv1, tv2 */
59410 return (duk_regconst_t) (n | DUK__CONST_MARKER);
59411}
59412
59413/* Get the value represented by an duk_ispec to a register or constant.
59414 * The caller can control the result by indicating whether or not:
59415 *
59416 * (1) a constant is allowed (sometimes the caller needs the result to
59417 * be in a register)
59418 *
59419 * (2) a temporary register is required (usually when caller requires
59420 * the register to be safely mutable; normally either a bound
59421 * register or a temporary register are both OK)
59422 *
59423 * (3) a forced register target needs to be used
59424 *
59425 * Bytecode may be emitted to generate the necessary value. The return
59426 * value is either a register or a constant.
59427 */
59428
59431 duk_ispec *x,
59432 duk_reg_t forced_reg,
59433 duk_small_uint_t flags) {
59434 duk_hthread *thr = comp_ctx->thr;
59435 duk_context *ctx = (duk_context *) thr;
59436
59437 DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
59438 "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
59439 (long) x->t,
59440 (long) x->regconst,
59441 (duk_tval *) duk_get_tval(ctx, x->valstack_idx),
59442 (long) forced_reg,
59443 (unsigned long) flags,
59444 (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
59445 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
59446 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
59447
59448 switch (x->t) {
59449 case DUK_ISPEC_VALUE: {
59450 duk_tval *tv;
59451
59452 tv = DUK_GET_TVAL_POSIDX(ctx, x->valstack_idx);
59453 DUK_ASSERT(tv != NULL);
59454
59455 switch (DUK_TVAL_GET_TAG(tv)) {
59456 case DUK_TAG_UNDEFINED: {
59457 /* Note: although there is no 'undefined' literal, undefined
59458 * values can occur during compilation as a result of e.g.
59459 * the 'void' operator.
59460 */
59461 duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59463 return (duk_regconst_t) dest;
59464 }
59465 case DUK_TAG_NULL: {
59466 duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59468 return (duk_regconst_t) dest;
59469 }
59470 case DUK_TAG_BOOLEAN: {
59471 duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59472 duk__emit_extraop_bc(comp_ctx,
59474 (duk_regconst_t) dest);
59475 return (duk_regconst_t) dest;
59476 }
59477 case DUK_TAG_POINTER: {
59479 break;
59480 }
59481 case DUK_TAG_STRING: {
59482 duk_hstring *h;
59483 duk_reg_t dest;
59484 duk_regconst_t constidx;
59485
59486 h = DUK_TVAL_GET_STRING(tv);
59487 DUK_UNREF(h);
59488 DUK_ASSERT(h != NULL);
59489
59490#if 0 /* XXX: to be implemented? */
59491 /* Use special opcodes to load short strings */
59492 if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
59493 /* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
59494 } else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
59495 /* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
59496 }
59497#endif
59498 duk_dup(ctx, x->valstack_idx);
59499 constidx = duk__getconst(comp_ctx);
59500
59501 if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
59502 return constidx;
59503 }
59504
59505 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59506 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
59507 return (duk_regconst_t) dest;
59508 }
59509 case DUK_TAG_OBJECT: {
59511 break;
59512 }
59513 case DUK_TAG_BUFFER: {
59515 break;
59516 }
59517 case DUK_TAG_LIGHTFUNC: {
59519 break;
59520 }
59521#if defined(DUK_USE_FASTINT)
59522 case DUK_TAG_FASTINT:
59523#endif
59524 default: {
59525 /* number */
59526 duk_reg_t dest;
59527 duk_regconst_t constidx;
59528 duk_double_t dval;
59529 duk_int32_t ival;
59530
59533 dval = DUK_TVAL_GET_NUMBER(tv);
59534
59535 if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
59536 /* A number can be loaded either through a constant, using
59537 * LDINT, or using LDINT+LDINTX. LDINT is always a size win,
59538 * LDINT+LDINTX is not if the constant is used multiple times.
59539 * Currently always prefer LDINT+LDINTX over a double constant.
59540 */
59541
59542 if (duk__is_whole_get_int32(dval, &ival)) {
59543 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59544 duk__emit_load_int32(comp_ctx, dest, ival);
59545 return (duk_regconst_t) dest;
59546 }
59547 }
59548
59549 duk_dup(ctx, x->valstack_idx);
59550 constidx = duk__getconst(comp_ctx);
59551
59552 if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
59553 return constidx;
59554 } else {
59555 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59556 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
59557 return (duk_regconst_t) dest;
59558 }
59559 }
59560 } /* end switch */
59561 }
59562 case DUK_ISPEC_REGCONST: {
59563 if (forced_reg >= 0) {
59564 if (x->regconst & DUK__CONST_MARKER) {
59565 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
59566 } else if (x->regconst != (duk_regconst_t) forced_reg) {
59567 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
59568 } else {
59569 ; /* already in correct reg */
59570 }
59571 return (duk_regconst_t) forced_reg;
59572 }
59573
59574 DUK_ASSERT(forced_reg < 0);
59575 if (x->regconst & DUK__CONST_MARKER) {
59576 if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
59577 duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
59579 return (duk_regconst_t) dest;
59580 }
59581 return x->regconst;
59582 }
59583
59584 DUK_ASSERT(forced_reg < 0 && !(x->regconst & DUK__CONST_MARKER));
59585 if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISTEMP(comp_ctx, x->regconst)) {
59586 duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
59587 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, (duk_regconst_t) dest, x->regconst);
59588 return (duk_regconst_t) dest;
59589 }
59590 return x->regconst;
59591 }
59592 default: {
59593 break;
59595 }
59596
59598 return 0;
59599}
59600
59602 DUK_ASSERT(forced_reg >= 0);
59603 (void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
59604}
59605
59606/* Coerce an duk_ivalue to a 'plain' value by generating the necessary
59607 * arithmetic operations, property access, or variable access bytecode.
59608 * The duk_ivalue argument ('x') is converted into a plain value as a
59609 * side effect.
59610 */
59612 duk_hthread *thr = comp_ctx->thr;
59613 duk_context *ctx = (duk_context *) thr;
59614
59615 DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
59616 "forced_reg=%ld",
59617 (long) x->t, (long) x->op,
59618 (long) x->x1.t, (long) x->x1.regconst,
59619 (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
59620 (long) x->x2.t, (long) x->x2.regconst,
59621 (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
59622 (long) forced_reg));
59623
59624 switch (x->t) {
59625 case DUK_IVAL_PLAIN: {
59626 return;
59627 }
59628 /* XXX: support unary arithmetic ivalues (useful?) */
59629 case DUK_IVAL_ARITH:
59631 duk_regconst_t arg1;
59632 duk_regconst_t arg2;
59633 duk_reg_t dest;
59634 duk_tval *tv1;
59635 duk_tval *tv2;
59636
59637 DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
59638
59639 /* inline arithmetic check for constant values */
59640 /* XXX: use the exactly same arithmetic function here as in executor */
59641 if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
59642 tv1 = DUK_GET_TVAL_POSIDX(ctx, x->x1.valstack_idx);
59643 tv2 = DUK_GET_TVAL_POSIDX(ctx, x->x2.valstack_idx);
59644 DUK_ASSERT(tv1 != NULL);
59645 DUK_ASSERT(tv2 != NULL);
59646
59647 DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
59648 (duk_tval *) tv1,
59649 (duk_tval *) tv2));
59650
59651 if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
59654 duk_double_t d3;
59655 duk_bool_t accept = 1;
59656
59657 DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
59658 (double) d1, (double) d2, (long) x->op));
59659 switch (x->op) {
59660 case DUK_OP_ADD: d3 = d1 + d2; break;
59661 case DUK_OP_SUB: d3 = d1 - d2; break;
59662 case DUK_OP_MUL: d3 = d1 * d2; break;
59663 case DUK_OP_DIV: d3 = d1 / d2; break;
59664 default: accept = 0; break;
59665 }
59666
59667 if (accept) {
59669 du.d = d3;
59671 d3 = du.d;
59672
59673 x->t = DUK_IVAL_PLAIN;
59675 DUK_TVAL_SET_NUMBER(tv1, d3); /* old value is number: no refcount */
59676 return;
59677 }
59678 } else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
59679 /* inline string concatenation */
59680 duk_dup(ctx, x->x1.valstack_idx);
59681 duk_dup(ctx, x->x2.valstack_idx);
59682 duk_concat(ctx, 2);
59683 duk_replace(ctx, x->x1.valstack_idx);
59684 x->t = DUK_IVAL_PLAIN;
59686 return;
59687 }
59688 }
59689
59692
59693 /* If forced reg, use it as destination. Otherwise try to
59694 * use either coerced ispec if it is a temporary.
59695 *
59696 * When using extraops, avoid reusing arg2 as dest because that
59697 * would lead to an LDREG shuffle below. We still can't guarantee
59698 * dest != arg2 because we may have a forced_reg.
59699 */
59700 if (forced_reg >= 0) {
59701 dest = forced_reg;
59702 } else if (DUK__ISTEMP(comp_ctx, arg1)) {
59703 dest = (duk_reg_t) arg1;
59704 } else if (DUK__ISTEMP(comp_ctx, arg2) && x->t != DUK_IVAL_ARITH_EXTRAOP) {
59705 dest = (duk_reg_t) arg2;
59706 } else {
59707 dest = DUK__ALLOCTEMP(comp_ctx);
59708 }
59709
59710 /* Extraop arithmetic opcodes must have destination same as
59711 * first source. If second source matches destination we need
59712 * a temporary register to avoid clobbering the second source.
59713 *
59714 * XXX: change calling code to avoid this situation in most cases.
59715 */
59716
59717 if (x->t == DUK_IVAL_ARITH_EXTRAOP) {
59718 if (!(DUK__ISREG(comp_ctx, arg1) && (duk_reg_t) arg1 == dest)) {
59719 if (DUK__ISREG(comp_ctx, arg2) && (duk_reg_t) arg2 == dest) {
59720 /* arg2 would be clobbered so reassign it to a temp. */
59721 duk_reg_t tempreg;
59722 tempreg = DUK__ALLOCTEMP(comp_ctx);
59723 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, tempreg, arg2);
59724 arg2 = tempreg;
59725 }
59726
59727 if (DUK__ISREG(comp_ctx, arg1)) {
59728 duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, arg1);
59729 } else {
59730 DUK_ASSERT(DUK__ISCONST(comp_ctx, arg1));
59731 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, arg1);
59732 }
59733 }
59734
59735 /* Note: special DUK__EMIT_FLAG_B_IS_TARGETSOURCE
59736 * used to indicate that B is both a source and a
59737 * target register. When shuffled, it needs to be
59738 * both input and output shuffled.
59739 */
59740 DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
59741 duk__emit_extraop_b_c(comp_ctx,
59744 (duk_regconst_t) dest,
59745 (duk_regconst_t) arg2);
59746
59747 } else {
59748 DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
59749 duk__emit_a_b_c(comp_ctx, x->op, (duk_regconst_t) dest, arg1, arg2);
59750 }
59751
59752 x->t = DUK_IVAL_PLAIN;
59753 x->x1.t = DUK_ISPEC_REGCONST;
59754 x->x1.regconst = (duk_regconst_t) dest;
59755 return;
59756 }
59757 case DUK_IVAL_PROP: {
59758 /* XXX: very similar to DUK_IVAL_ARITH - merge? */
59759 duk_regconst_t arg1;
59760 duk_regconst_t arg2;
59761 duk_reg_t dest;
59762
59763 /* Need a short reg/const, does not have to be a mutable temp. */
59766
59767 /* Pick a destination register. If either base value or key
59768 * happens to be a temp value, reuse it as the destination.
59769 *
59770 * XXX: The temp must be a "mutable" one, i.e. such that no
59771 * other expression is using it anymore. Here this should be
59772 * the case because the value of a property access expression
59773 * is neither the base nor the key, but the lookup result.
59774 */
59775
59776 if (forced_reg >= 0) {
59777 dest = forced_reg;
59778 } else if (DUK__ISTEMP(comp_ctx, arg1)) {
59779 dest = (duk_reg_t) arg1;
59780 } else if (DUK__ISTEMP(comp_ctx, arg2)) {
59781 dest = (duk_reg_t) arg2;
59782 } else {
59783 dest = DUK__ALLOCTEMP(comp_ctx);
59784 }
59785
59786 duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROP, (duk_regconst_t) dest, arg1, arg2);
59787
59788 x->t = DUK_IVAL_PLAIN;
59789 x->x1.t = DUK_ISPEC_REGCONST;
59790 x->x1.regconst = (duk_regconst_t) dest;
59791 return;
59792 }
59793 case DUK_IVAL_VAR: {
59794 /* x1 must be a string */
59795 duk_reg_t dest;
59796 duk_reg_t reg_varbind;
59797 duk_regconst_t rc_varname;
59798
59800
59801 duk_dup(ctx, x->x1.valstack_idx);
59802 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
59803 x->t = DUK_IVAL_PLAIN;
59804 x->x1.t = DUK_ISPEC_REGCONST;
59805 x->x1.regconst = (duk_regconst_t) reg_varbind;
59806 } else {
59807 dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59808 duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, (duk_regconst_t) dest, rc_varname);
59809 x->t = DUK_IVAL_PLAIN;
59811 x->x1.regconst = (duk_regconst_t) dest;
59812 }
59813 return;
59814 }
59816 default: {
59817 DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
59818 break;
59819 }
59820 }
59821
59823 return;
59824}
59825
59826/* evaluate to plain value, no forced register (temp/bound reg both ok) */
59828 duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
59829}
59830
59831/* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
59834
59835 /* If duk__ivalue_toplain_raw() allocates a temp, forget it and
59836 * restore next temp state.
59837 */
59838 temp = DUK__GETTEMP(comp_ctx);
59839 duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
59840 DUK__SETTEMP(comp_ctx, temp);
59841}
59842
59843/* Coerce an duk_ivalue to a register or constant; result register may
59844 * be a temp or a bound register.
59845 *
59846 * The duk_ivalue argument ('x') is converted into a regconst as a
59847 * side effect.
59848 */
59851 duk_ivalue *x,
59852 duk_reg_t forced_reg,
59853 duk_small_uint_t flags) {
59854 duk_hthread *thr = comp_ctx->thr;
59855 duk_context *ctx = (duk_context *) thr;
59856 duk_regconst_t reg;
59857 DUK_UNREF(thr);
59858 DUK_UNREF(ctx);
59859
59860 DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
59861 "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
59862 (long) x->t, (long) x->op,
59863 (long) x->x1.t, (long) x->x1.regconst,
59864 (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
59865 (long) x->x2.t, (long) x->x2.regconst,
59866 (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
59867 (long) forced_reg,
59868 (unsigned long) flags,
59869 (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
59870 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
59871 (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
59872
59873 /* first coerce to a plain value */
59874 duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
59876
59877 /* then to a register */
59878 reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
59879 x->x1.t = DUK_ISPEC_REGCONST;
59880 x->x1.regconst = reg;
59881
59882 return reg;
59886 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
59888
59889#if 0 /* unused */
59890DUK_LOCAL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
59891 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
59892}
59893#endif
59894
59896 DUK_ASSERT(forced_reg >= 0);
59897 (void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
59898}
59899
59901 return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
59902}
59906}
59907
59908/* The issues below can be solved with better flags */
59909
59910/* XXX: many operations actually want toforcedtemp() -- brand new temp? */
59911/* XXX: need a toplain_ignore() which will only coerce a value to a temp
59912 * register if it might have a side effect. Side-effect free values do not
59913 * need to be coerced.
59914 */
59915
59916/*
59917 * Identifier handling
59918 */
59919
59921 duk_hthread *thr = comp_ctx->thr;
59922 duk_context *ctx = (duk_context *) thr;
59923 duk_hstring *h_varname;
59924 duk_reg_t ret;
59925
59926 DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
59927 (duk_tval *) duk_get_tval(ctx, -1)));
59928
59929 /*
59930 * Special name handling
59931 */
59932
59933 h_varname = duk_get_hstring(ctx, -1);
59934 DUK_ASSERT(h_varname != NULL);
59935
59936 if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
59937 DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
59938 comp_ctx->curr_func.id_access_arguments = 1;
59939 }
59940
59941 /*
59942 * Inside one or more 'with' statements fall back to slow path always.
59943 * (See e.g. test-stmt-with.js.)
59944 */
59945
59946 if (comp_ctx->curr_func.with_depth > 0) {
59947 DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
59948 goto slow_path;
59949 }
59950
59951 /*
59952 * Any catch bindings ("catch (e)") also affect identifier binding.
59953 *
59954 * Currently, the varmap is modified for the duration of the catch
59955 * clause to ensure any identifier accesses with the catch variable
59956 * name will use slow path.
59957 */
59958
59959 duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
59960 if (duk_is_number(ctx, -1)) {
59961 ret = duk_to_int(ctx, -1);
59962 duk_pop(ctx);
59963 } else {
59964 duk_pop(ctx);
59965 goto slow_path;
59966 }
59967
59968 DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
59969 return ret;
59970
59971 slow_path:
59972 DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path"));
59973
59974 comp_ctx->curr_func.id_access_slow = 1;
59975 return (duk_reg_t) -1;
59976}
59977
59978/* Lookup an identifier name in the current varmap, indicating whether the
59979 * identifier is register-bound and if not, allocating a constant for the
59980 * identifier name. Returns 1 if register-bound, 0 otherwise. Caller can
59981 * also check (out_reg_varbind >= 0) to check whether or not identifier is
59982 * register bound. The caller must NOT use out_rc_varname at all unless
59983 * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
59984 * is unsigned and doesn't have a "unused" / none value.
59985 */
59986DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
59987 duk_hthread *thr = comp_ctx->thr;
59988 duk_context *ctx = (duk_context *) thr;
59989 duk_reg_t reg_varbind;
59990 duk_regconst_t rc_varname;
59991
59992 /* [ ... varname ] */
59993
59994 duk_dup_top(ctx);
59995 reg_varbind = duk__lookup_active_register_binding(comp_ctx);
59996
59997 if (reg_varbind >= 0) {
59998 *out_reg_varbind = reg_varbind;
59999 *out_rc_varname = 0; /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
60000 duk_pop(ctx);
60001 return 1;
60002 } else {
60003 rc_varname = duk__getconst(comp_ctx);
60004 *out_reg_varbind = -1;
60005 *out_rc_varname = rc_varname;
60006 return 0;
60007 }
60008}
60009
60010/*
60011 * Label handling
60012 *
60013 * Labels are initially added with flags prohibiting both break and continue.
60014 * When the statement type is finally uncovered (after potentially multiple
60015 * labels), all the labels are updated to allow/prohibit break and continue.
60016 */
60017
60018DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {
60019 duk_hthread *thr = comp_ctx->thr;
60020 duk_context *ctx = (duk_context *) thr;
60021 duk_size_t n;
60022 duk_size_t new_size;
60023 duk_uint8_t *p;
60024 duk_labelinfo *li_start, *li;
60025
60026 /* Duplicate (shadowing) labels are not allowed, except for the empty
60027 * labels (which are used as default labels for switch and iteration
60028 * statements).
60029 *
60030 * We could also allow shadowing of non-empty pending labels without any
60031 * other issues than breaking the required label shadowing requirements
60032 * of the E5 specification, see Section 12.12.
60033 */
60034
60035 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
60036 li_start = (duk_labelinfo *) (void *) p;
60037 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60038 n = (duk_size_t) (li - li_start);
60039
60040 while (li > li_start) {
60041 li--;
60042
60043 if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
60045 }
60046 }
60047
60048 duk_push_hstring(ctx, h_label);
60049 DUK_ASSERT(n <= DUK_UARRIDX_MAX); /* label limits */
60050 (void) duk_put_prop_index(ctx, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
60051
60052 new_size = (n + 1) * sizeof(duk_labelinfo);
60053 duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
60054 /* XXX: spare handling, slow now */
60055
60056 /* relookup after possible realloc */
60057 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
60058 li_start = (duk_labelinfo *) (void *) p;
60059 DUK_UNREF(li_start); /* silence scan-build warning */
60060 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60061 li--;
60062
60063 /* Labels can be used for iteration statements but also for other statements,
60064 * in particular a label can be used for a block statement. All cases of a
60065 * named label accept a 'break' so that flag is set here. Iteration statements
60066 * also allow 'continue', so that flag is updated when we figure out the
60067 * statement type.
60068 */
60069
60071 li->label_id = label_id;
60072 li->h_label = h_label;
60073 li->catch_depth = comp_ctx->curr_func.catch_depth; /* catch depth from current func */
60074 li->pc_label = pc_label;
60075
60076 DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
60077 (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
60078 (long) li->catch_depth, (long) li->pc_label));
60079}
60080
60081/* Update all labels with matching label_id. */
60083 duk_uint8_t *p;
60084 duk_labelinfo *li_start, *li;
60085
60086 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
60087 li_start = (duk_labelinfo *) (void *) p;
60088 li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60089
60090 /* Match labels starting from latest; once label_id no longer matches, we can
60091 * safely exit without checking the rest of the labels (only the topmost labels
60092 * are ever updated).
60093 */
60094 while (li > li_start) {
60095 li--;
60096
60097 if (li->label_id != label_id) {
60098 break;
60099 }
60100
60101 DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
60102 (void *) li, (long) label_id, (long) flags));
60103
60104 li->flags = flags;
60105 }
60107
60108/* Lookup active label information. Break/continue distinction is necessary to handle switch
60109 * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
60110 *
60111 * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
60112 * iteration and switch statements) can. A break will match the closest unlabelled or labelled
60113 * statement. A continue will match the closest unlabelled or labelled iteration statement. It is
60114 * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
60115 * be duplicated, the continue cannot match any valid label outside the switch.
60116 *
60117 * A side effect of these rules is that a LABEL statement related to a switch should never actually
60118 * catch a continue abrupt completion at run-time. Hence an INVALID opcode can be placed in the
60119 * continue slot of the switch's LABEL statement.
60120 */
60121
60122/* XXX: awkward, especially the bunch of separate output values -> output struct? */
60123DUK_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) {
60124 duk_hthread *thr = comp_ctx->thr;
60125 duk_context *ctx = (duk_context *) thr;
60126 duk_uint8_t *p;
60127 duk_labelinfo *li_start, *li_end, *li;
60128 duk_bool_t match = 0;
60129
60130 DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
60131 (duk_heaphdr *) h_label, (long) is_break));
60132
60133 DUK_UNREF(ctx);
60134
60135 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
60136 li_start = (duk_labelinfo *) (void *) p;
60137 li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60138 li = li_end;
60139
60140 /* Match labels starting from latest label because there can be duplicate empty
60141 * labels in the label set.
60142 */
60143 while (li > li_start) {
60144 li--;
60145
60146 if (li->h_label != h_label) {
60147 DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
60148 (long) (li - li_start),
60149 (duk_heaphdr *) li->h_label,
60150 (duk_heaphdr *) h_label));
60151 continue;
60152 }
60153
60154 DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
60155 (long) (li - li_start), (duk_heaphdr *) h_label));
60156
60157 /* currently all labels accept a break, so no explicit check for it now */
60159
60160 if (is_break) {
60161 /* break matches always */
60162 match = 1;
60163 break;
60164 } else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
60165 /* iteration statements allow continue */
60166 match = 1;
60167 break;
60168 } else {
60169 /* continue matched this label -- we can only continue if this is the empty
60170 * label, for which duplication is allowed, and thus there is hope of
60171 * finding a match deeper in the label stack.
60172 */
60173 if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
60175 } else {
60176 DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
60177 "allow a continue -> continue lookup deeper in label stack"));
60178 }
60180 }
60181 /* XXX: match flag is awkward, rework */
60182 if (!match) {
60184 }
60185
60186 DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
60187 (duk_heaphdr *) h_label, (long) li->label_id,
60188 (long) li->catch_depth, (long) li->pc_label));
60189
60190 *out_label_id = li->label_id;
60191 *out_label_catch_depth = li->catch_depth;
60192 *out_label_pc = li->pc_label;
60193 *out_is_closest = (li == li_end - 1);
60194}
60195
60197 duk_hthread *thr = comp_ctx->thr;
60198 duk_context *ctx = (duk_context *) thr;
60199 duk_size_t new_size;
60201 /* XXX: duk_set_length */
60202 new_size = sizeof(duk_labelinfo) * (duk_size_t) len;
60203 duk_push_int(ctx, len);
60205 duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
60206}
60207
60208/*
60209 * Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
60210 *
60211 * - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
60212 * - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
60213 * - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
60214 */
60215
60216/* object literal key tracking flags */
60217#define DUK__OBJ_LIT_KEY_PLAIN (1 << 0) /* key encountered as a plain property */
60218#define DUK__OBJ_LIT_KEY_GET (1 << 1) /* key encountered as a getter */
60219#define DUK__OBJ_LIT_KEY_SET (1 << 2) /* key encountered as a setter */
60220
60222 duk_hthread *thr = comp_ctx->thr;
60223 duk_reg_t reg_obj; /* result reg */
60224 duk_reg_t reg_temp; /* temp reg */
60225 duk_reg_t temp_start; /* temp reg value for start of loop */
60226 duk_small_uint_t max_init_values; /* max # of values initialized in one MPUTARR set */
60227 duk_small_uint_t num_values; /* number of values in current MPUTARR set */
60228 duk_uarridx_t curr_idx; /* current (next) array index */
60229 duk_uarridx_t start_idx; /* start array index of current MPUTARR set */
60230 duk_uarridx_t init_idx; /* last array index explicitly initialized, +1 */
60231 duk_bool_t require_comma; /* next loop requires a comma */
60232
60233 /* DUK_TOK_LBRACKET already eaten, current token is right after that */
60235
60236 max_init_values = DUK__MAX_ARRAY_INIT_VALUES; /* XXX: depend on available temps? */
60237
60238 reg_obj = DUK__ALLOCTEMP(comp_ctx);
60239 duk__emit_extraop_b_c(comp_ctx,
60241 reg_obj,
60242 0); /* XXX: patch initial size afterwards? */
60243 temp_start = DUK__GETTEMP(comp_ctx);
60244
60245 /*
60246 * Emit initializers in sets of maximum max_init_values.
60247 * Corner cases such as single value initializers do not have
60248 * special handling now.
60249 *
60250 * Elided elements must not be emitted as 'undefined' values,
60251 * because such values would be enumerable (which is incorrect).
60252 * Also note that trailing elisions must be reflected in the
60253 * length of the final array but cause no elements to be actually
60254 * inserted.
60255 */
60256
60257 curr_idx = 0;
60258 init_idx = 0; /* tracks maximum initialized index + 1 */
60259 start_idx = 0;
60260 require_comma = 0;
60261
60262 for (;;) {
60263 num_values = 0;
60264 DUK__SETTEMP(comp_ctx, temp_start);
60265
60266 if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
60267 break;
60268 }
60269
60270 for (;;) {
60271 if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
60272 /* the outer loop will recheck and exit */
60273 break;
60274 }
60275
60276 /* comma check */
60277 if (require_comma) {
60278 if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
60279 /* comma after a value, expected */
60280 duk__advance(comp_ctx);
60281 require_comma = 0;
60282 continue;
60283 } else {
60284 goto syntax_error;
60285 }
60286 } else {
60287 if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
60288 /* elision - flush */
60289 curr_idx++;
60290 duk__advance(comp_ctx);
60291 /* if num_values > 0, MPUTARR emitted by outer loop after break */
60292 break;
60293 }
60294 }
60295 /* else an array initializer element */
60296
60297 /* initial index */
60298 if (num_values == 0) {
60299 start_idx = curr_idx;
60300 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60301 duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
60302 }
60303
60304 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
60305 DUK__SETTEMP(comp_ctx, reg_temp);
60306 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
60307 DUK__SETTEMP(comp_ctx, reg_temp + 1);
60308
60309 num_values++;
60310 curr_idx++;
60311 require_comma = 1;
60312
60313 if (num_values >= max_init_values) {
60314 /* MPUTARR emitted by outer loop */
60315 break;
60316 }
60317 }
60318
60319 if (num_values > 0) {
60320 /* - A is a source register (it's not a write target, but used
60321 * to identify the target object) but can be shuffled.
60322 * - B cannot be shuffled normally because it identifies a range
60323 * of registers, the emitter has special handling for this
60324 * (the "no shuffle" flag must not be set).
60325 * - C is a non-register number and cannot be shuffled, but
60326 * never needs to be.
60327 */
60328 duk__emit_a_b_c(comp_ctx,
60332 (duk_regconst_t) reg_obj,
60333 (duk_regconst_t) temp_start,
60334 (duk_regconst_t) num_values);
60335 init_idx = start_idx + num_values;
60336
60337 /* num_values and temp_start reset at top of outer loop */
60338 }
60339 }
60340
60342 duk__advance(comp_ctx);
60343
60344 DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
60345 (long) curr_idx, (long) init_idx));
60346
60347 /* trailing elisions? */
60348 if (curr_idx > init_idx) {
60349 /* yes, must set array length explicitly */
60350 DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
60351 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60352 duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
60353 duk__emit_extraop_b_c(comp_ctx,
60355 (duk_regconst_t) reg_obj,
60356 (duk_regconst_t) reg_temp);
60357 }
60358
60359 DUK__SETTEMP(comp_ctx, temp_start);
60360
60361 res->t = DUK_IVAL_PLAIN;
60362 res->x1.t = DUK_ISPEC_REGCONST;
60363 res->x1.regconst = (duk_regconst_t) reg_obj;
60364 return;
60365
60366 syntax_error:
60368}
60369
60370/* duplicate/invalid key checks; returns 1 if syntax error */
60372 duk_hthread *thr = comp_ctx->thr;
60373 duk_context *ctx = (duk_context *) thr;
60374 duk_small_uint_t key_flags;
60375
60376 /* [ ... key_obj key ] */
60377
60378 DUK_ASSERT(duk_is_string(ctx, -1));
60379
60380 /*
60381 * 'key_obj' tracks keys encountered so far by associating an
60382 * integer with flags with already encountered keys. The checks
60383 * below implement E5 Section 11.1.5, step 4 for production:
60384 *
60385 * PropertyNameAndValueList: PropertyNameAndValueList , PropertyAssignment
60386 */
60387
60388 duk_dup(ctx, -1); /* [ ... key_obj key key ] */
60389 duk_get_prop(ctx, -3); /* [ ... key_obj key val ] */
60390 key_flags = duk_to_int(ctx, -1);
60391 duk_pop(ctx); /* [ ... key_obj key ] */
60392
60393 if (new_key_flags & DUK__OBJ_LIT_KEY_PLAIN) {
60394 if ((key_flags & DUK__OBJ_LIT_KEY_PLAIN) && comp_ctx->curr_func.is_strict) {
60395 /* step 4.a */
60396 DUK_DDD(DUK_DDDPRINT("duplicate key: plain key appears twice in strict mode"));
60397 return 1;
60398 }
60399 if (key_flags & (DUK__OBJ_LIT_KEY_GET | DUK__OBJ_LIT_KEY_SET)) {
60400 /* step 4.c */
60401 DUK_DDD(DUK_DDDPRINT("duplicate key: plain key encountered after setter/getter"));
60402 return 1;
60403 }
60404 } else {
60405 if (key_flags & DUK__OBJ_LIT_KEY_PLAIN) {
60406 /* step 4.b */
60407 DUK_DDD(DUK_DDDPRINT("duplicate key: getter/setter encountered after plain key"));
60408 return 1;
60409 }
60410 if (key_flags & new_key_flags) {
60411 /* step 4.d */
60412 DUK_DDD(DUK_DDDPRINT("duplicate key: getter/setter encountered twice"));
60413 return 1;
60414 }
60415 }
60416
60417 new_key_flags |= key_flags;
60418 DUK_DDD(DUK_DDDPRINT("setting/updating key %!T flags: 0x%08lx -> 0x%08lx",
60419 (duk_tval *) duk_get_tval(ctx, -1),
60420 (unsigned long) key_flags,
60421 (unsigned long) new_key_flags));
60422 duk_dup(ctx, -1);
60423 duk_push_int(ctx, new_key_flags); /* [ ... key_obj key key flags ] */
60424 duk_put_prop(ctx, -4); /* [ ... key_obj key ] */
60425
60426 return 0;
60427}
60428
60430 duk_hthread *thr = comp_ctx->thr;
60431 duk_context *ctx = (duk_context *) thr;
60432 duk_reg_t reg_obj; /* result reg */
60433 duk_reg_t reg_key; /* temp reg for key literal */
60434 duk_reg_t reg_temp; /* temp reg */
60435 duk_reg_t temp_start; /* temp reg value for start of loop */
60436 duk_small_uint_t max_init_pairs; /* max # of key-value pairs initialized in one MPUTOBJ set */
60437 duk_small_uint_t num_pairs; /* number of pairs in current MPUTOBJ set */
60438 duk_bool_t first; /* first value: comma must not precede the value */
60439 duk_bool_t is_set, is_get; /* temps */
60440
60441 DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
60442
60443 max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS; /* XXX: depend on available temps? */
60444
60445 reg_obj = DUK__ALLOCTEMP(comp_ctx);
60446 duk__emit_extraop_b_c(comp_ctx,
60448 reg_obj,
60449 0); /* XXX: patch initial size afterwards? */
60450 temp_start = DUK__GETTEMP(comp_ctx);
60451
60452 /* temp object for tracking / detecting duplicate keys */
60453 duk_push_object(ctx);
60454
60455 /*
60456 * Emit initializers in sets of maximum max_init_pairs keys.
60457 * Setter/getter is handled separately and terminates the
60458 * current set of initializer values. Corner cases such as
60459 * single value initializers do not have special handling now.
60460 */
60461
60462 first = 1;
60463 for (;;) {
60464 num_pairs = 0;
60465 DUK__SETTEMP(comp_ctx, temp_start);
60466
60467 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60468 break;
60469 }
60470
60471 for (;;) {
60472 /*
60473 * Three possible element formats:
60474 * 1) PropertyName : AssignmentExpression
60475 * 2) get PropertyName () { FunctionBody }
60476 * 3) set PropertyName ( PropertySetParameterList ) { FunctionBody }
60477 *
60478 * PropertyName can be IdentifierName (includes reserved words), a string
60479 * literal, or a number literal. Note that IdentifierName allows 'get' and
60480 * 'set' too, so we need to look ahead to the next token to distinguish:
60481 *
60482 * { get : 1 }
60483 *
60484 * and
60485 *
60486 * { get foo() { return 1 } }
60487 * { get get() { return 1 } } // 'get' as getter propertyname
60488 *
60489 * Finally, a trailing comma is allowed.
60490 *
60491 * Key name is coerced to string at compile time (and ends up as a
60492 * a string constant) even for numeric keys (e.g. "{1:'foo'}").
60493 * These could be emitted using e.g. LDINT, but that seems hardly
60494 * worth the effort and would increase code size.
60495 */
60496
60497 DUK_DDD(DUK_DDDPRINT("object literal inner loop, curr_token->t = %ld",
60498 (long) comp_ctx->curr_token.t));
60499
60500 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60501 /* the outer loop will recheck and exit */
60502 break;
60503 }
60504 if (num_pairs >= max_init_pairs) {
60505 /* MPUTOBJ emitted by outer loop */
60506 break;
60507 }
60508
60509 if (first) {
60510 first = 0;
60511 } else {
60512 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
60513 goto syntax_error;
60514 }
60515 duk__advance(comp_ctx);
60516 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60517 /* trailing comma followed by rcurly */
60518 break;
60519 }
60520 }
60521
60522 /* advance to get one step of lookup */
60523 duk__advance(comp_ctx);
60524
60525 /* NOTE: "get" and "set" are not officially ReservedWords and the lexer
60526 * currently treats them always like ordinary identifiers (DUK_TOK_GET
60527 * and DUK_TOK_SET are unused). They need to be detected based on the
60528 * identifier string content.
60529 */
60530
60531 is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
60532 comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
60533 is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
60534 comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
60535 if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
60536 /* getter/setter */
60537 duk_int_t fnum;
60538
60539 if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER ||
60540 comp_ctx->curr_token.t_nores == DUK_TOK_STRING) {
60541 /* same handling for identifiers and strings */
60542 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
60543 duk_push_hstring(ctx, comp_ctx->curr_token.str1);
60544 } else if (comp_ctx->curr_token.t == DUK_TOK_NUMBER) {
60545 duk_push_number(ctx, comp_ctx->curr_token.num);
60546 duk_to_string(ctx, -1);
60547 } else {
60548 goto syntax_error;
60549 }
60550
60551 DUK_ASSERT(duk_is_string(ctx, -1));
60554 goto syntax_error;
60555 }
60556 reg_key = duk__getconst(comp_ctx);
60557
60558 if (num_pairs > 0) {
60559 /* - A is a source register (it's not a write target, but used
60560 * to identify the target object) but can be shuffled.
60561 * - B cannot be shuffled normally because it identifies a range
60562 * of registers, the emitter has special handling for this
60563 * (the "no shuffle" flag must not be set).
60564 * - C is a non-register number and cannot be shuffled, but
60565 * never needs to be.
60566 */
60567 duk__emit_a_b_c(comp_ctx,
60571 reg_obj,
60572 temp_start,
60573 num_pairs);
60574 num_pairs = 0;
60575 DUK__SETTEMP(comp_ctx, temp_start);
60576 }
60577
60578 /* curr_token = get/set name */
60579 fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*is_decl*/, 1 /*is_setget*/);
60580
60581 DUK_ASSERT(DUK__GETTEMP(comp_ctx) == temp_start);
60582 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60583 duk__emit_a_bc(comp_ctx,
60585 (duk_regconst_t) reg_temp,
60586 (duk_regconst_t) reg_key);
60587 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60588 duk__emit_a_bc(comp_ctx,
60590 (duk_regconst_t) reg_temp,
60591 (duk_regconst_t) fnum);
60592
60593 /* Slot C is used in a non-standard fashion (range of regs),
60594 * emitter code has special handling for it (must not set the
60595 * "no shuffle" flag).
60596 */
60597 duk__emit_extraop_b_c(comp_ctx,
60599 reg_obj,
60600 temp_start); /* temp_start+0 = key, temp_start+1 = closure */
60601
60602 DUK__SETTEMP(comp_ctx, temp_start);
60603 } else {
60604 /* normal key/value */
60605 if (comp_ctx->prev_token.t_nores == DUK_TOK_IDENTIFIER ||
60606 comp_ctx->prev_token.t_nores == DUK_TOK_STRING) {
60607 /* same handling for identifiers and strings */
60608 DUK_ASSERT(comp_ctx->prev_token.str1 != NULL);
60609 duk_push_hstring(ctx, comp_ctx->prev_token.str1);
60610 } else if (comp_ctx->prev_token.t == DUK_TOK_NUMBER) {
60611 duk_push_number(ctx, comp_ctx->prev_token.num);
60612 duk_to_string(ctx, -1);
60613 } else {
60614 goto syntax_error;
60615 }
60616
60617 DUK_ASSERT(duk_is_string(ctx, -1));
60619 goto syntax_error;
60620 }
60621 reg_key = duk__getconst(comp_ctx);
60622
60623 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60624 duk__emit_a_bc(comp_ctx,
60626 (duk_regconst_t) reg_temp,
60627 (duk_regconst_t) reg_key);
60629
60630 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
60631 DUK__SETTEMP(comp_ctx, reg_temp);
60632 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
60633 DUK__SETTEMP(comp_ctx, reg_temp + 1);
60634
60635 num_pairs++;
60636 }
60637 }
60638
60639 if (num_pairs > 0) {
60640 /* See MPUTOBJ comments above. */
60641 duk__emit_a_b_c(comp_ctx,
60645 reg_obj,
60646 temp_start,
60647 num_pairs);
60648
60649 /* num_pairs and temp_start reset at top of outer loop */
60650 }
60651 }
60652
60653 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
60654 duk__advance(comp_ctx);
60655
60656 DUK__SETTEMP(comp_ctx, temp_start);
60657
60659 res->x1.t = DUK_ISPEC_REGCONST;
60660 res->x1.regconst = (duk_regconst_t) reg_obj;
60661
60662 DUK_DDD(DUK_DDDPRINT("final tracking object: %!T",
60663 (duk_tval *) duk_get_tval(ctx, -1)));
60664 duk_pop(ctx);
60665 return;
60666
60667 syntax_error:
60669}
60670
60671/* Parse argument list. Arguments are written to temps starting from
60672 * "next temp". Returns number of arguments parsed. Expects left paren
60673 * to be already eaten, and eats the right paren before returning.
60674 */
60676 duk_int_t nargs = 0;
60677 duk_reg_t reg_temp;
60678
60679 /* Note: expect that caller has already eaten the left paren */
60680
60681 DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
60682 (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
60683
60684 for (;;) {
60685 if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
60686 break;
60687 }
60688 if (nargs > 0) {
60690 }
60691
60692 /* We want the argument expression value to go to "next temp"
60693 * without additional moves. That should almost always be the
60694 * case, but we double check after expression parsing.
60695 *
60696 * This is not the cleanest possible approach.
60697 */
60698
60699 reg_temp = DUK__ALLOCTEMP(comp_ctx); /* bump up "allocated" reg count, just in case */
60700 DUK__SETTEMP(comp_ctx, reg_temp);
60701
60702 /* binding power must be high enough to NOT allow comma expressions directly */
60703 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp); /* always allow 'in', coerce to 'tr' just in case */
60704
60705 DUK__SETTEMP(comp_ctx, reg_temp + 1);
60706 nargs++;
60707
60708 DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
60709 }
60710
60711 /* eat the right paren */
60713
60714 DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
60715
60716 return nargs;
60717}
60718
60720 /* empty expressions can be detected conveniently with nud/led counts */
60721 return (comp_ctx->curr_func.nud_count == 0) &&
60722 (comp_ctx->curr_func.led_count == 0);
60723}
60724
60725DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
60726 duk_hthread *thr = comp_ctx->thr;
60727 duk_context *ctx = (duk_context *) thr;
60728 duk_token *tk;
60729 duk_reg_t temp_at_entry;
60730 duk_small_int_t tok;
60731 duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
60732
60733 /*
60734 * ctx->prev_token token to process with duk__expr_nud()
60735 * ctx->curr_token updated by caller
60736 *
60737 * Note: the token in the switch below has already been eaten.
60738 */
60739
60740 temp_at_entry = DUK__GETTEMP(comp_ctx);
60741
60742 comp_ctx->curr_func.nud_count++;
60743
60744 tk = &comp_ctx->prev_token;
60745 tok = tk->t;
60746 res->t = DUK_IVAL_NONE;
60747
60748 DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
60749 (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
60750
60751 switch (tok) {
60752
60753 /* PRIMARY EXPRESSIONS */
60754
60755 case DUK_TOK_THIS: {
60756 duk_reg_t reg_temp;
60757 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60758 duk__emit_extraop_bc(comp_ctx,
60760 (duk_regconst_t) reg_temp);
60761 res->t = DUK_IVAL_PLAIN;
60762 res->x1.t = DUK_ISPEC_REGCONST;
60763 res->x1.regconst = (duk_regconst_t) reg_temp;
60764 return;
60765 }
60766 case DUK_TOK_IDENTIFIER: {
60767 res->t = DUK_IVAL_VAR;
60768 res->x1.t = DUK_ISPEC_VALUE;
60769 duk_push_hstring(ctx, tk->str1);
60770 duk_replace(ctx, res->x1.valstack_idx);
60771 return;
60772 }
60773 case DUK_TOK_NULL: {
60774 duk_push_null(ctx);
60775 goto plain_value;
60776 }
60777 case DUK_TOK_TRUE: {
60778 duk_push_true(ctx);
60779 goto plain_value;
60780 }
60781 case DUK_TOK_FALSE: {
60782 duk_push_false(ctx);
60783 goto plain_value;
60784 }
60785 case DUK_TOK_NUMBER: {
60786 duk_push_number(ctx, tk->num);
60787 goto plain_value;
60788 }
60789 case DUK_TOK_STRING: {
60790 DUK_ASSERT(tk->str1 != NULL);
60791 duk_push_hstring(ctx, tk->str1);
60792 goto plain_value;
60793 }
60794 case DUK_TOK_REGEXP: {
60795#ifdef DUK_USE_REGEXP_SUPPORT
60796 duk_reg_t reg_temp;
60797 duk_regconst_t rc_re_bytecode; /* const */
60798 duk_regconst_t rc_re_source; /* const */
60799
60800 DUK_ASSERT(tk->str1 != NULL);
60801 DUK_ASSERT(tk->str2 != NULL);
60802
60803 DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
60804 (duk_heaphdr *) tk->str1,
60805 (duk_heaphdr *) tk->str2));
60806
60807 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60808 duk_push_hstring(ctx, tk->str1);
60809 duk_push_hstring(ctx, tk->str2);
60810
60811 /* [ ... pattern flags ] */
60812
60813 duk_regexp_compile(thr);
60814
60815 /* [ ... escaped_source bytecode ] */
60816
60817 rc_re_bytecode = duk__getconst(comp_ctx);
60818 rc_re_source = duk__getconst(comp_ctx);
60819
60820 duk__emit_a_b_c(comp_ctx,
60822 (duk_regconst_t) reg_temp /*a*/,
60823 rc_re_bytecode /*b*/,
60824 rc_re_source /*c*/);
60825
60826 res->t = DUK_IVAL_PLAIN;
60827 res->x1.t = DUK_ISPEC_REGCONST;
60828 res->x1.regconst = (duk_regconst_t) reg_temp;
60829 return;
60830#else /* DUK_USE_REGEXP_SUPPORT */
60831 goto syntax_error;
60832#endif /* DUK_USE_REGEXP_SUPPORT */
60833 }
60834 case DUK_TOK_LBRACKET: {
60835 DUK_DDD(DUK_DDDPRINT("parsing array literal"));
60836 duk__nud_array_literal(comp_ctx, res);
60837 return;
60838 }
60839 case DUK_TOK_LCURLY: {
60840 DUK_DDD(DUK_DDDPRINT("parsing object literal"));
60841 duk__nud_object_literal(comp_ctx, res);
60842 return;
60843 }
60844 case DUK_TOK_LPAREN: {
60845 duk_bool_t prev_allow_in;
60846
60847 comp_ctx->curr_func.paren_level++;
60848 prev_allow_in = comp_ctx->curr_func.allow_in;
60849 comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
60850
60851 duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */
60852
60854 comp_ctx->curr_func.allow_in = prev_allow_in;
60855 comp_ctx->curr_func.paren_level--;
60856 return;
60857 }
60858
60859 /* MEMBER/NEW/CALL EXPRESSIONS */
60860
60861 case DUK_TOK_NEW: {
60862 /*
60863 * Parsing an expression starting with 'new' is tricky because
60864 * there are multiple possible productions deriving from
60865 * LeftHandSideExpression which begin with 'new'.
60866 *
60867 * We currently resort to one-token lookahead to distinguish the
60868 * cases. Hopefully this is correct. The binding power must be
60869 * such that parsing ends at an LPAREN (CallExpression) but not at
60870 * a PERIOD or LBRACKET (MemberExpression).
60871 *
60872 * See doc/compiler.rst for discussion on the parsing approach,
60873 * and testcases/test-dev-new.js for a bunch of documented tests.
60874 */
60875
60876 duk_reg_t reg_target;
60877 duk_int_t nargs;
60878
60879 DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
60880
60881 reg_target = DUK__ALLOCTEMP(comp_ctx);
60882 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
60883 DUK__SETTEMP(comp_ctx, reg_target + 1);
60884
60885 if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
60886 /* 'new' MemberExpression Arguments */
60887 DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
60888 duk__advance(comp_ctx);
60889 nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp", reg_target + 1 */
60890 /* right paren eaten */
60891 } else {
60892 /* 'new' MemberExpression */
60893 DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
60894 nargs = 0;
60895 }
60896
60897 /* Opcode slot C is used in a non-standard way, so shuffling
60898 * is not allowed.
60899 */
60900 duk__emit_a_b_c(comp_ctx,
60902 0 /*unused*/,
60903 reg_target /*target*/,
60904 nargs /*num_args*/);
60905
60906 DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
60907
60908 res->t = DUK_IVAL_PLAIN;
60909 res->x1.t = DUK_ISPEC_REGCONST;
60910 res->x1.regconst = (duk_regconst_t) reg_target;
60911 return;
60912 }
60913
60914 /* FUNCTION EXPRESSIONS */
60915
60916 case DUK_TOK_FUNCTION: {
60917 /* Function expression. Note that any statement beginning with 'function'
60918 * is handled by the statement parser as a function declaration, or a
60919 * non-standard function expression/statement (or a SyntaxError). We only
60920 * handle actual function expressions (occurring inside an expression) here.
60921 *
60922 * O(depth^2) parse count for inner functions is handled by recording a
60923 * lexer offset on the first compilation pass, so that the function can
60924 * be efficiently skipped on the second pass. This is encapsulated into
60925 * duk__parse_func_like_fnum().
60926 */
60927
60928 duk_reg_t reg_temp;
60929 duk_int_t fnum;
60930
60931 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60932
60933 /* curr_token follows 'function' */
60934 fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*is_decl*/, 0 /*is_setget*/);
60935 DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
60936
60937 duk__emit_a_bc(comp_ctx,
60939 (duk_regconst_t) reg_temp /*a*/,
60940 (duk_regconst_t) fnum /*bc*/);
60941
60942 res->t = DUK_IVAL_PLAIN;
60943 res->x1.t = DUK_ISPEC_REGCONST;
60944 res->x1.regconst = (duk_regconst_t) reg_temp;
60945 return;
60946 }
60947
60948 /* UNARY EXPRESSIONS */
60949
60950 case DUK_TOK_DELETE: {
60951 /* Delete semantics are a bit tricky. The description in E5 specification
60952 * is kind of confusing, because it distinguishes between resolvability of
60953 * a reference (which is only known at runtime) seemingly at compile time
60954 * (= SyntaxError throwing).
60955 */
60956 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
60957 if (res->t == DUK_IVAL_VAR) {
60958 /* not allowed in strict mode, regardless of whether resolves;
60959 * in non-strict mode DELVAR handles both non-resolving and
60960 * resolving cases (the specification description is a bit confusing).
60961 */
60962
60963 duk_reg_t reg_temp;
60964 duk_reg_t reg_varbind;
60965 duk_regconst_t rc_varname;
60966
60967 if (comp_ctx->curr_func.is_strict) {
60969 }
60970
60971 DUK__SETTEMP(comp_ctx, temp_at_entry);
60972 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60973
60974 duk_dup(ctx, res->x1.valstack_idx);
60975 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
60976 /* register bound variables are non-configurable -> always false */
60977 duk__emit_extraop_bc(comp_ctx,
60979 (duk_regconst_t) reg_temp);
60980 } else {
60981 duk_dup(ctx, res->x1.valstack_idx);
60982 rc_varname = duk__getconst(comp_ctx);
60983 duk__emit_a_b(comp_ctx,
60985 (duk_regconst_t) reg_temp,
60986 (duk_regconst_t) rc_varname);
60987 }
60988 res->t = DUK_IVAL_PLAIN;
60989 res->x1.t = DUK_ISPEC_REGCONST;
60990 res->x1.regconst = (duk_regconst_t) reg_temp;
60991 } else if (res->t == DUK_IVAL_PROP) {
60992 duk_reg_t reg_temp;
60993 duk_reg_t reg_obj;
60994 duk_regconst_t rc_key;
60995
60996 DUK__SETTEMP(comp_ctx, temp_at_entry);
60997 reg_temp = DUK__ALLOCTEMP(comp_ctx);
60998 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
60999 rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
61000 duk__emit_a_b_c(comp_ctx,
61002 (duk_regconst_t) reg_temp,
61003 (duk_regconst_t) reg_obj,
61004 rc_key);
61005
61006 res->t = DUK_IVAL_PLAIN;
61007 res->x1.t = DUK_ISPEC_REGCONST;
61008 res->x1.regconst = (duk_regconst_t) reg_temp;
61009 } else {
61010 /* non-Reference deletion is always 'true', even in strict mode */
61011 duk_push_true(ctx);
61012 goto plain_value;
61013 }
61014 return;
61015 }
61016 case DUK_TOK_VOID: {
61017 duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61018 duk_push_undefined(ctx);
61019 goto plain_value;
61020 }
61021 case DUK_TOK_TYPEOF: {
61022 /* 'typeof' must handle unresolvable references without throwing
61023 * a ReferenceError (E5 Section 11.4.3). Register mapped values
61024 * will never be unresolvable so special handling is only required
61025 * when an identifier is a "slow path" one.
61026 */
61027 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61028
61029 if (res->t == DUK_IVAL_VAR) {
61030 duk_reg_t reg_varbind;
61031 duk_regconst_t rc_varname;
61032 duk_reg_t reg_temp;
61033
61034 duk_dup(ctx, res->x1.valstack_idx);
61035 if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61036 DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
61037 "at compile time, need to use special run-time handling"));
61038 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61039 duk__emit_extraop_b_c(comp_ctx,
61041 reg_temp,
61042 rc_varname);
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
61050 args = (DUK_EXTRAOP_TYPEOF << 8) + 0;
61051 goto unary_extraop;
61052 }
61053 case DUK_TOK_INCREMENT: {
61054 args = (DUK_OP_PREINCR << 8) + 0;
61055 goto preincdec;
61056 }
61057 case DUK_TOK_DECREMENT: {
61058 args = (DUK_OP_PREDECR << 8) + 0;
61059 goto preincdec;
61060 }
61061 case DUK_TOK_ADD: {
61062 /* unary plus */
61063 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61064 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
61065 duk_is_number(ctx, res->x1.valstack_idx)) {
61066 /* unary plus of a number is identity */
61067 ;
61068 return;
61069 }
61070 args = (DUK_EXTRAOP_UNP << 8) + 0;
61071 goto unary_extraop;
61072 }
61073 case DUK_TOK_SUB: {
61074 /* unary minus */
61075 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61076 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
61077 duk_is_number(ctx, res->x1.valstack_idx)) {
61078 /* this optimization is important to handle negative literals
61079 * (which are not directly provided by the lexical grammar)
61080 */
61081 duk_tval *tv_num;
61083
61084 tv_num = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
61085 DUK_ASSERT(tv_num != NULL);
61087 du.d = DUK_TVAL_GET_NUMBER(tv_num);
61088 du.d = -du.d;
61090 DUK_TVAL_SET_NUMBER(tv_num, du.d);
61091 return;
61092 }
61093 args = (DUK_EXTRAOP_UNM << 8) + 0;
61094 goto unary_extraop;
61095 }
61096 case DUK_TOK_BNOT: {
61097 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61098 args = (DUK_EXTRAOP_BNOT << 8) + 0;
61099 goto unary_extraop;
61100 }
61101 case DUK_TOK_LNOT: {
61102 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61103 if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
61104 /* Very minimal inlining to handle common idioms '!0' and '!1',
61105 * and also boolean arguments like '!false' and '!true'.
61106 */
61107 duk_tval *tv_val;
61108
61109 tv_val = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
61110 DUK_ASSERT(tv_val != NULL);
61111 if (DUK_TVAL_IS_NUMBER(tv_val)) {
61112 duk_double_t d;
61113 d = DUK_TVAL_GET_NUMBER(tv_val);
61114 if (d == 0.0) {
61115 /* Matches both +0 and -0 on purpose. */
61116 DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
61118 return;
61119 } else if (d == 1.0) {
61120 DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
61122 return;
61123 }
61124 } else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
61126 v = DUK_TVAL_GET_BOOLEAN(tv_val);
61127 DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
61128 DUK_ASSERT(v == 0 || v == 1);
61129 DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
61130 return;
61131 }
61132 }
61133 args = (DUK_EXTRAOP_LNOT << 8) + 0;
61134 goto unary_extraop;
61135 }
61136
61137 } /* end switch */
61138
61140 return;
61141
61142 unary_extraop:
61143 {
61144 /* Note: must coerce to a (writable) temp register, so that e.g. "!x" where x
61145 * is a reg-mapped variable works correctly (does not mutate the variable register).
61146 */
61147
61148 duk_reg_t reg_temp;
61149 reg_temp = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
61150 duk__emit_extraop_bc(comp_ctx,
61151 (args >> 8),
61152 (duk_regconst_t) reg_temp);
61153 res->t = DUK_IVAL_PLAIN;
61154 res->x1.t = DUK_ISPEC_REGCONST;
61155 res->x1.regconst = (duk_regconst_t) reg_temp;
61156 return;
61157 }
61158
61159 preincdec:
61160 {
61161 /* preincrement and predecrement */
61162 duk_reg_t reg_res;
61163 duk_small_uint_t args_op = args >> 8;
61164
61165 /* Specific assumptions for opcode numbering. */
61170
61171 reg_res = DUK__ALLOCTEMP(comp_ctx);
61172
61173 duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
61174 if (res->t == DUK_IVAL_VAR) {
61175 duk_hstring *h_varname;
61176 duk_reg_t reg_varbind;
61177 duk_regconst_t rc_varname;
61178
61179 h_varname = duk_get_hstring(ctx, res->x1.valstack_idx);
61180 DUK_ASSERT(h_varname != NULL);
61181
61182 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
61183 goto syntax_error;
61184 }
61185
61186 duk_dup(ctx, res->x1.valstack_idx);
61187 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61188 duk__emit_a_bc(comp_ctx,
61189 args_op, /* e.g. DUK_OP_PREINCR */
61190 (duk_regconst_t) reg_res,
61191 (duk_regconst_t) reg_varbind);
61192 } else {
61193 duk__emit_a_bc(comp_ctx,
61194 args_op + 4, /* e.g. DUK_OP_PREINCV */
61195 (duk_regconst_t) reg_res,
61196 rc_varname);
61197 }
61198
61199 DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
61200 (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
61201 } else if (res->t == DUK_IVAL_PROP) {
61202 duk_reg_t reg_obj; /* allocate to reg only (not const) */
61203 duk_regconst_t rc_key;
61204 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
61205 rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
61206 duk__emit_a_b_c(comp_ctx,
61207 args_op + 8, /* e.g. DUK_OP_PREINCP */
61208 (duk_regconst_t) reg_res,
61209 (duk_regconst_t) reg_obj,
61210 rc_key);
61211 } else {
61212 /* Technically return value is not needed because INVLHS will
61213 * unconditially throw a ReferenceError. Coercion is necessary
61214 * for proper semantics (consider ToNumber() called for an object).
61215 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
61216 */
61217
61218 duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
61219 duk__emit_extraop_bc(comp_ctx,
61221 reg_res); /* for side effects, result ignored */
61222 duk__emit_extraop_only(comp_ctx,
61224 }
61225 res->t = DUK_IVAL_PLAIN;
61226 res->x1.t = DUK_ISPEC_REGCONST;
61227 res->x1.regconst = (duk_regconst_t) reg_res;
61228 DUK__SETTEMP(comp_ctx, reg_res + 1);
61229 return;
61230 }
61231
61232 plain_value:
61233 {
61234 /* Stack top contains plain value */
61235 res->t = DUK_IVAL_PLAIN;
61236 res->x1.t = DUK_ISPEC_VALUE;
61237 duk_replace(ctx, res->x1.valstack_idx);
61238 return;
61239 }
61240
61241 syntax_error:
61243}
61244
61245/* XXX: add flag to indicate whether caller cares about return value; this
61246 * affects e.g. handling of assignment expressions. This change needs API
61247 * changes elsewhere too.
61248 */
61250 duk_hthread *thr = comp_ctx->thr;
61251 duk_context *ctx = (duk_context *) thr;
61252 duk_token *tk;
61253 duk_small_int_t tok;
61254 duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
61255
61256 /*
61257 * ctx->prev_token token to process with duk__expr_led()
61258 * ctx->curr_token updated by caller
61259 */
61260
61261 comp_ctx->curr_func.led_count++;
61262
61263 /* The token in the switch has already been eaten here */
61264 tk = &comp_ctx->prev_token;
61265 tok = tk->t;
61266
61267 DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
61268 (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
61269
61270 /* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
61271
61272 switch (tok) {
61273
61274 /* PRIMARY EXPRESSIONS */
61275
61276 case DUK_TOK_PERIOD: {
61277 /* Property access expressions are critical for correct LHS ordering,
61278 * see comments in duk__expr()!
61279 *
61280 * A conservative approach would be to use duk__ivalue_totempconst()
61281 * for 'left'. However, allowing a reg-bound variable seems safe here
61282 * and is nice because "foo.bar" is a common expression. If the ivalue
61283 * is used in an expression a GETPROP will occur before any changes to
61284 * the base value can occur. If the ivalue is used as an assignment
61285 * LHS, the assignment code will ensure the base value is safe from
61286 * RHS mutation.
61287 */
61288
61289 /* XXX: This now coerces an identifier into a GETVAR to a temp, which
61290 * causes an extra LDREG in call setup. It's sufficient to coerce to a
61291 * unary ivalue?
61292 */
61293 duk__ivalue_toplain(comp_ctx, left);
61294
61295 /* NB: must accept reserved words as property name */
61296 if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
61298 }
61299
61300 res->t = DUK_IVAL_PROP;
61301 duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
61302 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
61303 duk_push_hstring(ctx, comp_ctx->curr_token.str1);
61304 duk_replace(ctx, res->x2.valstack_idx);
61305 res->x2.t = DUK_ISPEC_VALUE;
61306
61307 /* special RegExp literal handling after IdentifierName */
61308 comp_ctx->curr_func.reject_regexp_in_adv = 1;
61309
61310 duk__advance(comp_ctx);
61311 return;
61312 }
61313 case DUK_TOK_LBRACKET: {
61314 /* Property access expressions are critical for correct LHS ordering,
61315 * see comments in duk__expr()!
61316 */
61317
61318 /* XXX: optimize temp reg use */
61319 /* XXX: similar coercion issue as in DUK_TOK_PERIOD */
61320 /* XXX: coerce to regs? it might be better for enumeration use, where the
61321 * same PROP ivalue is used multiple times. Or perhaps coerce PROP further
61322 * there?
61323 */
61324 /* XXX: for simple cases like x['y'] an unnecessary LDREG is
61325 * emitted for the base value; could avoid it if we knew that
61326 * the key expression is safe (e.g. just a single literal).
61327 */
61328
61329 /* The 'left' value must not be a register bound variable
61330 * because it may be mutated during the rest of the expression
61331 * and E5.1 Section 11.2.1 specifies the order of evaluation
61332 * so that the base value is evaluated first.
61333 * See: test-bug-nested-prop-mutate.js.
61334 */
61335 duk__ivalue_totempconst(comp_ctx, left);
61336 duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, ']' terminates */
61338
61339 res->t = DUK_IVAL_PROP;
61340 duk__copy_ispec(comp_ctx, &res->x1, &res->x2); /* res.x1 -> res.x2 */
61341 duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
61342 return;
61343 }
61344 case DUK_TOK_LPAREN: {
61345 /* function call */
61346 duk_reg_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
61347 duk_int_t nargs;
61348 duk_small_uint_t call_flags = 0;
61349
61350 /*
61351 * XXX: attempt to get the call result to "next temp" whenever
61352 * possible to avoid unnecessary register shuffles.
61353 *
61354 * XXX: CSPROP (and CSREG) can overwrite the call target register, and save one temp,
61355 * if the call target is a temporary register and at the top of the temp reg "stack".
61356 */
61357
61358 /*
61359 * Setup call: target and 'this' binding. Three cases:
61360 *
61361 * 1. Identifier base (e.g. "foo()")
61362 * 2. Property base (e.g. "foo.bar()")
61363 * 3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
61364 */
61365
61366 if (left->t == DUK_IVAL_VAR) {
61367 duk_hstring *h_varname;
61368 duk_reg_t reg_varbind;
61369 duk_regconst_t rc_varname;
61370
61371 DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
61372
61373 h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
61374 DUK_ASSERT(h_varname != NULL);
61375 if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
61376 /* Potential direct eval call detected, flag the CALL
61377 * so that a run-time "direct eval" check is made and
61378 * special behavior may be triggered. Note that this
61379 * does not prevent 'eval' from being register bound.
61380 */
61381 DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
61382 "-> enabling EVALCALL flag, marking function "
61383 "as may_direct_eval"));
61384 call_flags |= DUK_BC_CALL_FLAG_EVALCALL;
61385
61386 comp_ctx->curr_func.may_direct_eval = 1;
61387 }
61388
61389 duk_dup(ctx, left->x1.valstack_idx);
61390 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61391 duk__emit_a_b(comp_ctx,
61393 (duk_regconst_t) (reg_cs + 0),
61394 (duk_regconst_t) reg_varbind);
61395 } else {
61396 duk__emit_a_b(comp_ctx,
61398 (duk_regconst_t) (reg_cs + 0),
61399 rc_varname);
61400 }
61401 } else if (left->t == DUK_IVAL_PROP) {
61402 DUK_DDD(DUK_DDDPRINT("function call with property base"));
61403
61404 duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 0); /* base */
61405 duk__ispec_toforcedreg(comp_ctx, &left->x2, reg_cs + 1); /* key */
61406 duk__emit_a_b_c(comp_ctx,
61408 (duk_regconst_t) (reg_cs + 0),
61409 (duk_regconst_t) (reg_cs + 0),
61410 (duk_regconst_t) (reg_cs + 1)); /* in-place setup */
61411 } else {
61412 DUK_DDD(DUK_DDDPRINT("function call with register base"));
61413
61414 duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
61415 duk__emit_a_b(comp_ctx,
61417 (duk_regconst_t) (reg_cs + 0),
61418 (duk_regconst_t) (reg_cs + 0)); /* in-place setup */
61419 }
61420
61421 DUK__SETTEMP(comp_ctx, reg_cs + 2);
61422 nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp" */
61423
61424 /* Tailcalls are handled by back-patching the TAILCALL flag to the
61425 * already emitted instruction later (in return statement parser).
61426 * Since A and C have a special meaning here, they cannot be "shuffled".
61427 */
61428
61429 duk__emit_a_b_c(comp_ctx,
61431 (duk_regconst_t) call_flags /*flags*/,
61432 (duk_regconst_t) reg_cs /*basereg*/,
61433 (duk_regconst_t) nargs /*numargs*/);
61434 DUK__SETTEMP(comp_ctx, reg_cs + 1); /* result in csreg */
61435
61436 res->t = DUK_IVAL_PLAIN;
61437 res->x1.t = DUK_ISPEC_REGCONST;
61438 res->x1.regconst = (duk_regconst_t) reg_cs;
61439 return;
61440 }
61441
61442 /* POSTFIX EXPRESSION */
61443
61444 case DUK_TOK_INCREMENT: {
61445 args = (DUK_OP_POSTINCR << 8) + 0;
61446 goto postincdec;
61447 }
61448 case DUK_TOK_DECREMENT: {
61449 args = (DUK_OP_POSTDECR << 8) + 0;
61450 goto postincdec;
61451 }
61452
61453 /* MULTIPLICATIVE EXPRESSION */
61454
61455 case DUK_TOK_MUL: {
61456 args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE; /* UnaryExpression */
61457 goto binary;
61458 }
61459 case DUK_TOK_DIV: {
61460 args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE; /* UnaryExpression */
61461 goto binary;
61462 }
61463 case DUK_TOK_MOD: {
61464 args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE; /* UnaryExpression */
61465 goto binary;
61466 }
61467
61468 /* ADDITIVE EXPRESSION */
61469
61470 case DUK_TOK_ADD: {
61471 args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
61472 goto binary;
61473 }
61474 case DUK_TOK_SUB: {
61475 args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
61476 goto binary;
61477 }
61478
61479 /* SHIFT EXPRESSION */
61480
61481 case DUK_TOK_ALSHIFT: {
61482 /* << */
61483 args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
61484 goto binary;
61485 }
61486 case DUK_TOK_ARSHIFT: {
61487 /* >> */
61488 args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
61489 goto binary;
61490 }
61491 case DUK_TOK_RSHIFT: {
61492 /* >>> */
61493 args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
61494 goto binary;
61495 }
61496
61497 /* RELATIONAL EXPRESSION */
61498
61499 case DUK_TOK_LT: {
61500 /* < */
61501 args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
61502 goto binary;
61503 }
61504 case DUK_TOK_GT: {
61505 args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
61506 goto binary;
61507 }
61508 case DUK_TOK_LE: {
61509 args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
61510 goto binary;
61511 }
61512 case DUK_TOK_GE: {
61513 args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
61514 goto binary;
61515 }
61516 case DUK_TOK_INSTANCEOF: {
61517 args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_INSTOF << 8) + DUK__BP_RELATIONAL;
61518 goto binary;
61519 }
61520 case DUK_TOK_IN: {
61521 args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_IN << 8) + DUK__BP_RELATIONAL;
61522 goto binary;
61523 }
61524
61525 /* EQUALITY EXPRESSION */
61526
61527 case DUK_TOK_EQ: {
61528 args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
61529 goto binary;
61530 }
61531 case DUK_TOK_NEQ: {
61532 args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
61533 goto binary;
61534 }
61535 case DUK_TOK_SEQ: {
61536 args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
61537 goto binary;
61538 }
61539 case DUK_TOK_SNEQ: {
61540 args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
61541 goto binary;
61542 }
61543
61544 /* BITWISE EXPRESSIONS */
61545
61546 case DUK_TOK_BAND: {
61547 args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
61548 goto binary;
61549 }
61550 case DUK_TOK_BXOR: {
61551 args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
61552 goto binary;
61553 }
61554 case DUK_TOK_BOR: {
61555 args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
61556 goto binary;
61557 }
61558
61559 /* LOGICAL EXPRESSIONS */
61560
61561 case DUK_TOK_LAND: {
61562 /* syntactically left-associative but parsed as right-associative */
61563 args = (1 << 8) + DUK__BP_LAND - 1;
61564 goto binary_logical;
61565 }
61566 case DUK_TOK_LOR: {
61567 /* syntactically left-associative but parsed as right-associative */
61568 args = (0 << 8) + DUK__BP_LOR - 1;
61569 goto binary_logical;
61570 }
61571
61572 /* CONDITIONAL EXPRESSION */
61573
61574 case DUK_TOK_QUESTION: {
61575 /* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
61576 * but only if it really is a temp. Nothing fancy here now.
61577 */
61578 duk_reg_t reg_temp;
61579 duk_int_t pc_jump1;
61580 duk_int_t pc_jump2;
61581
61582 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61583 duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
61584 duk__emit_if_true_skip(comp_ctx, reg_temp);
61585 pc_jump1 = duk__emit_jump_empty(comp_ctx); /* jump to false */
61586 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
61588 pc_jump2 = duk__emit_jump_empty(comp_ctx); /* jump to end */
61589 duk__patch_jump_here(comp_ctx, pc_jump1);
61590 duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
61591 duk__patch_jump_here(comp_ctx, pc_jump2);
61592
61593 DUK__SETTEMP(comp_ctx, reg_temp + 1);
61594 res->t = DUK_IVAL_PLAIN;
61595 res->x1.t = DUK_ISPEC_REGCONST;
61596 res->x1.regconst = (duk_regconst_t) reg_temp;
61597 return;
61598 }
61599
61600 /* ASSIGNMENT EXPRESSION */
61601
61602 case DUK_TOK_EQUALSIGN: {
61603 /*
61604 * Assignments are right associative, allows e.g.
61605 * a = 5;
61606 * a += b = 9; // same as a += (b = 9)
61607 * -> expression value 14, a = 14, b = 9
61608 *
61609 * Right associativiness is reflected in the BP for recursion,
61610 * "-1" ensures assignment operations are allowed.
61611 *
61612 * XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
61613 */
61614 args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1; /* DUK_OP_NONE marks a 'plain' assignment */
61615 goto assign;
61616 }
61617 case DUK_TOK_ADD_EQ: {
61618 /* right associative */
61619 args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
61620 goto assign;
61621 }
61622 case DUK_TOK_SUB_EQ: {
61623 /* right associative */
61624 args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
61625 goto assign;
61626 }
61627 case DUK_TOK_MUL_EQ: {
61628 /* right associative */
61629 args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
61630 goto assign;
61631 }
61632 case DUK_TOK_DIV_EQ: {
61633 /* right associative */
61634 args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
61635 goto assign;
61636 }
61637 case DUK_TOK_MOD_EQ: {
61638 /* right associative */
61639 args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
61640 goto assign;
61641 }
61642 case DUK_TOK_ALSHIFT_EQ: {
61643 /* right associative */
61644 args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
61645 goto assign;
61646 }
61647 case DUK_TOK_ARSHIFT_EQ: {
61648 /* right associative */
61649 args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
61650 goto assign;
61651 }
61652 case DUK_TOK_RSHIFT_EQ: {
61653 /* right associative */
61654 args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
61655 goto assign;
61656 }
61657 case DUK_TOK_BAND_EQ: {
61658 /* right associative */
61659 args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
61660 goto assign;
61661 }
61662 case DUK_TOK_BOR_EQ: {
61663 /* right associative */
61664 args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
61665 goto assign;
61666 }
61667 case DUK_TOK_BXOR_EQ: {
61668 /* right associative */
61669 args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
61670 goto assign;
61671 }
61672
61673 /* COMMA */
61674
61675 case DUK_TOK_COMMA: {
61676 /* right associative */
61677
61678 duk__ivalue_toplain_ignore(comp_ctx, left); /* need side effects, not value */
61679 duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
61680
61681 /* return 'res' (of right part) as our result */
61682 return;
61683 }
61684
61685 default: {
61686 break;
61687 }
61688 }
61689
61690 DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
61692 return;
61693
61694#if 0
61695 /* XXX: shared handling for 'duk__expr_lhs'? */
61696 if (comp_ctx->curr_func.paren_level == 0 && XXX) {
61697 comp_ctx->curr_func.duk__expr_lhs = 0;
61698 }
61699#endif
61700
61701 binary:
61702 /*
61703 * Shared handling of binary operations
61704 *
61705 * args = (is_extraop << 16) + (opcode << 8) + rbp
61706 */
61707 {
61708 duk__ivalue_toplain(comp_ctx, left);
61709 duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
61710
61711 /* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
61713 DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
61714
61715 res->t = (args >> 16) ? DUK_IVAL_ARITH_EXTRAOP : DUK_IVAL_ARITH;
61716 res->op = (args >> 8) & 0xff;
61717
61718 res->x2.t = res->x1.t;
61719 res->x2.regconst = res->x1.regconst;
61720 duk_copy(ctx, res->x1.valstack_idx, res->x2.valstack_idx);
61721
61722 res->x1.t = left->x1.t;
61723 res->x1.regconst = left->x1.regconst;
61724 duk_copy(ctx, left->x1.valstack_idx, res->x1.valstack_idx);
61725
61726 DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
61727 (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
61728 return;
61729 }
61730
61731 binary_logical:
61732 /*
61733 * Shared handling for logical AND and logical OR.
61734 *
61735 * args = (truthval << 8) + rbp
61736 *
61737 * Truthval determines when to skip right-hand-side.
61738 * For logical AND truthval=1, for logical OR truthval=0.
61739 *
61740 * See doc/compiler.rst for discussion on compiling logical
61741 * AND and OR expressions. The approach here is very simplistic,
61742 * generating extra jumps and multiple evaluations of truth values,
61743 * but generates code on-the-fly with only local back-patching.
61744 *
61745 * Both logical AND and OR are syntactically left-associated.
61746 * However, logical ANDs are compiled as right associative
61747 * expressions, i.e. "A && B && C" as "A && (B && C)", to allow
61748 * skip jumps to skip over the entire tail. Similarly for logical OR.
61749 */
61750
61751 {
61752 duk_reg_t reg_temp;
61753 duk_int_t pc_jump;
61754 duk_small_uint_t args_truthval = args >> 8;
61755 duk_small_uint_t args_rbp = args & 0xff;
61756
61757 /* XXX: unoptimal use of temps, resetting */
61758
61759 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61760
61761 duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
61762 duk__emit_a_b(comp_ctx,
61764 (duk_regconst_t) args_truthval,
61765 (duk_regconst_t) reg_temp); /* skip jump conditionally */
61766 pc_jump = duk__emit_jump_empty(comp_ctx);
61767 duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
61768 duk__patch_jump_here(comp_ctx, pc_jump);
61769
61770 res->t = DUK_IVAL_PLAIN;
61771 res->x1.t = DUK_ISPEC_REGCONST;
61772 res->x1.regconst = (duk_regconst_t) reg_temp;
61773 return;
61774 }
61775
61776 assign:
61777 /*
61778 * Shared assignment expression handling
61779 *
61780 * args = (opcode << 8) + rbp
61781 *
61782 * If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
61783 * Syntactically valid left-hand-side forms which are not accepted as
61784 * left-hand-side values (e.g. as in "f() = 1") must NOT cause a
61785 * SyntaxError, but rather a run-time ReferenceError.
61786 *
61787 * When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
61788 * to a temporary first. The RHS is then evaluated. Finally, the
61789 * <op> is applied to the initial value of RHS (not the value after
61790 * RHS evaluation), and written to X. Doing so concretely generates
61791 * inefficient code so we'd like to avoid the temporary when possible.
61792 * See: https://github.com/svaarala/duktape/pull/992.
61793 *
61794 * The expression value (final LHS value, written to RHS) is
61795 * conceptually copied into a fresh temporary so that it won't
61796 * change even if the LHS/RHS values change in outer expressions.
61797 * For example, it'd be generally incorrect for the expression value
61798 * to be the RHS register binding, unless there's a guarantee that it
61799 * won't change during further expression evaluation. Using the
61800 * temporary concretely produces inefficient bytecode, so we try to
61801 * avoid the extra temporary for some known-to-be-safe cases.
61802 * Currently the only safe case we detect is a "top level assignment",
61803 * for example "x = y + z;", where the assignment expression value is
61804 * ignored.
61805 * See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
61806 */
61807
61808 {
61809 duk_small_uint_t args_op = args >> 8;
61810 duk_small_uint_t args_rbp = args & 0xff;
61811 duk_bool_t toplevel_assign;
61812
61813 /* XXX: here we need to know if 'left' is left-hand-side compatible.
61814 * That information is no longer available from current expr parsing
61815 * state; it would need to be carried into the 'left' ivalue or by
61816 * some other means.
61817 */
61818
61819 /* A top-level assignment is e.g. "x = y;". For these it's safe
61820 * to use the RHS as-is as the expression value, even if the RHS
61821 * is a reg-bound identifier. The RHS ('res') is right associative
61822 * so it has consumed all other assignment level operations; the
61823 * only relevant lower binding power construct is comma operator
61824 * which will ignore the expression value provided here. Usually
61825 * the top level assignment expression value is ignored, but it
61826 * is relevant for e.g. eval code.
61827 */
61828 toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
61829 comp_ctx->curr_func.led_count == 1); /* one operator (= assign) */
61830 DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
61831 (long) comp_ctx->curr_func.nud_count,
61832 (long) comp_ctx->curr_func.led_count,
61833 (long) toplevel_assign));
61834
61835 if (left->t == DUK_IVAL_VAR) {
61836 duk_hstring *h_varname;
61837 duk_reg_t reg_varbind;
61838 duk_regconst_t rc_varname;
61839
61840 DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE); /* LHS is already side effect free */
61841
61842 h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
61843 DUK_ASSERT(h_varname != NULL);
61844 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
61845 /* E5 Section 11.13.1 (and others for other assignments), step 4. */
61846 goto syntax_error_lvalue;
61847 }
61848 duk_dup(ctx, left->x1.valstack_idx);
61849 (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
61850
61851 if (args_op == DUK_OP_NONE) {
61852 duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
61853 if (toplevel_assign) {
61854 /* Any 'res' will do. */
61855 DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
61856 } else {
61857 /* 'res' must be a plain ivalue, and not register-bound variable. */
61858 DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
61859 if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
61860 (res->x1.regconst & DUK__CONST_MARKER) == 0 &&
61861 !DUK__ISTEMP(comp_ctx, res->x1.regconst))) {
61862 duk__ivalue_totempconst(comp_ctx, res);
61863 }
61864 }
61865 } else {
61866 /* For X <op>= Y we need to evaluate the pre-op
61867 * value of X before evaluating the RHS: the RHS
61868 * can change X, but when we do <op> we must use
61869 * the pre-op value.
61870 */
61871 duk_reg_t reg_temp;
61872
61873 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61874
61875 if (reg_varbind >= 0) {
61876 duk_reg_t reg_res;
61877 duk_reg_t reg_src;
61878 duk_int_t pc_temp_load;
61879 duk_int_t pc_before_rhs;
61880 duk_int_t pc_after_rhs;
61881
61882 if (toplevel_assign) {
61883 /* 'reg_varbind' is the operation result and can also
61884 * become the expression value for top level assignments
61885 * such as: "var x; x += y;".
61886 */
61887 DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
61888 reg_res = reg_varbind;
61889 } else {
61890 /* Not safe to use 'reg_varbind' as assignment expression
61891 * value, so go through a temp.
61892 */
61893 DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
61894 reg_res = reg_temp; /* reg_res should be smallest possible */
61895 reg_temp = DUK__ALLOCTEMP(comp_ctx);
61896 }
61897
61898 /* Try to optimize X <op>= Y for reg-bound
61899 * variables. Detect side-effect free RHS
61900 * narrowly by seeing whether it emits code.
61901 * If not, rewind the code emitter and overwrite
61902 * the unnecessary temp reg load.
61903 */
61904
61905 pc_temp_load = duk__get_current_pc(comp_ctx);
61906 duk__emit_a_bc(comp_ctx,
61908 (duk_regconst_t) reg_temp,
61909 reg_varbind);
61910
61911 pc_before_rhs = duk__get_current_pc(comp_ctx);
61912 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
61913 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61914 pc_after_rhs = duk__get_current_pc(comp_ctx);
61915
61916 DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
61917 (long) pc_temp_load, (long) pc_before_rhs,
61918 (long) pc_after_rhs));
61919
61920 if (pc_after_rhs == pc_before_rhs) {
61921 /* Note: if the reg_temp load generated shuffling
61922 * instructions, we may need to rewind more than
61923 * one instruction, so use explicit PC computation.
61924 */
61925 DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
61926 DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (pc_temp_load - pc_before_rhs) * sizeof(duk_compiler_instr));
61927 reg_src = reg_varbind;
61928 } else {
61929 DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
61930 reg_src = reg_temp;
61931 }
61932
61933 duk__emit_a_b_c(comp_ctx,
61934 args_op,
61935 (duk_regconst_t) reg_res,
61936 (duk_regconst_t) reg_src,
61937 res->x1.regconst);
61938
61939 res->x1.regconst = (duk_regconst_t) reg_res;
61940
61941 /* Ensure compact use of temps. */
61942 if (DUK__ISTEMP(comp_ctx, reg_res)) {
61943 DUK__SETTEMP(comp_ctx, reg_res + 1);
61944 }
61945 } else {
61946 /* When LHS is not register bound, always go through a
61947 * temporary. No optimization for top level assignment.
61948 */
61949
61950 duk__emit_a_bc(comp_ctx,
61952 (duk_regconst_t) reg_temp,
61953 rc_varname);
61954
61955 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
61956 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61957
61958 duk__emit_a_b_c(comp_ctx,
61959 args_op,
61960 (duk_regconst_t) reg_temp,
61961 (duk_regconst_t) reg_temp,
61962 res->x1.regconst);
61963 res->x1.regconst = (duk_regconst_t) reg_temp;
61964 }
61965
61966 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
61967 }
61968
61969 /* At this point 'res' holds the potential expression value.
61970 * It can be basically any ivalue here, including a reg-bound
61971 * identifier (if code above deems it safe) or a unary/binary
61972 * operation. Operations must be resolved to a side effect free
61973 * plain value, and the side effects must happen exactly once.
61974 */
61975
61976 if (reg_varbind >= 0) {
61977 if (res->t != DUK_IVAL_PLAIN) {
61978 /* Resolve 'res' directly into the LHS binding, and use
61979 * that as the expression value if safe. If not safe,
61980 * resolve to a temp/const and copy to LHS.
61981 */
61982 if (toplevel_assign) {
61983 duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
61984 } else {
61985 duk__ivalue_totempconst(comp_ctx, res);
61986 duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
61987 duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
61988 }
61989 } else {
61990 /* Use 'res' as the expression value (it's side effect
61991 * free and may be a plain value, a register, or a
61992 * constant) and write it to the LHS binding too.
61993 */
61994 duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
61995 duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
61996 }
61997 } else {
61998 /* Only a reg fits into 'A' so coerce 'res' into a register
61999 * for PUTVAR.
62000 *
62001 * XXX: here the current A/B/C split is suboptimal: we could
62002 * just use 9 bits for reg_res (and support constants) and 17
62003 * instead of 18 bits for the varname const index.
62004 */
62005
62006 duk__ivalue_toreg(comp_ctx, res);
62007 duk__emit_a_bc(comp_ctx,
62009 res->x1.regconst,
62010 rc_varname);
62011 }
62012
62013 /* 'res' contains expression value */
62014 } else if (left->t == DUK_IVAL_PROP) {
62015 /* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
62016 duk_reg_t reg_obj;
62017 duk_regconst_t rc_key;
62018 duk_regconst_t rc_res;
62019 duk_reg_t reg_temp;
62020
62021 /* Property access expressions ('a[b]') are critical to correct
62022 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
62023 * We must make sure that the LHS target slot (base object and
62024 * key) don't change during RHS evaluation. The only concrete
62025 * problem is a register reference to a variable-bound register
62026 * (i.e., non-temp). Require temp regs for both key and base.
62027 *
62028 * Don't allow a constant for the object (even for a number
62029 * etc), as it goes into the 'A' field of the opcode.
62030 */
62031
62032 reg_obj = duk__ispec_toregconst_raw(comp_ctx,
62033 &left->x1,
62034 -1 /*forced_reg*/,
62035 DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
62036
62037 rc_key = duk__ispec_toregconst_raw(comp_ctx,
62038 &left->x2,
62039 -1 /*forced_reg*/,
62041
62042 /* Evaluate RHS only when LHS is safe. */
62043
62044 if (args_op == DUK_OP_NONE) {
62045 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62046 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
62047 rc_res = res->x1.regconst;
62048 } else {
62049 reg_temp = DUK__ALLOCTEMP(comp_ctx);
62050 duk__emit_a_b_c(comp_ctx,
62052 (duk_regconst_t) reg_temp,
62053 (duk_regconst_t) reg_obj,
62054 rc_key);
62055
62056 duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62057 DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
62058
62059 duk__emit_a_b_c(comp_ctx,
62060 args_op,
62061 (duk_regconst_t) reg_temp,
62062 (duk_regconst_t) reg_temp,
62063 res->x1.regconst);
62064 rc_res = (duk_regconst_t) reg_temp;
62065 }
62066
62067 duk__emit_a_b_c(comp_ctx,
62069 (duk_regconst_t) reg_obj,
62070 rc_key,
62071 rc_res);
62072
62073 res->t = DUK_IVAL_PLAIN;
62074 res->x1.t = DUK_ISPEC_REGCONST;
62075 res->x1.regconst = rc_res;
62076 } else {
62077 /* No support for lvalues returned from new or function call expressions.
62078 * However, these must NOT cause compile-time SyntaxErrors, but run-time
62079 * ReferenceErrors. Both left and right sides of the assignment must be
62080 * evaluated before throwing a ReferenceError. For instance:
62081 *
62082 * f() = g();
62083 *
62084 * must result in f() being evaluated, then g() being evaluated, and
62085 * finally, a ReferenceError being thrown. See E5 Section 11.13.1.
62086 */
62087
62088 duk_regconst_t rc_res;
62089
62090 /* First evaluate LHS fully to ensure all side effects are out. */
62092
62093 /* Then evaluate RHS fully (its value becomes the expression value too).
62094 * Technically we'd need the side effect safety check here too, but because
62095 * we always throw using INVLHS the result doesn't matter.
62096 */
62097 rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62098
62099 duk__emit_extraop_only(comp_ctx,
62101
62102 res->t = DUK_IVAL_PLAIN;
62103 res->x1.t = DUK_ISPEC_REGCONST;
62104 res->x1.regconst = rc_res;
62105 }
62106
62107 return;
62108 }
62109
62110 postincdec:
62111 {
62112 /*
62113 * Post-increment/decrement will return the original value as its
62114 * result value. However, even that value will be coerced using
62115 * ToNumber() which is quite awkward. Specific bytecode opcodes
62116 * are used to handle these semantics.
62117 *
62118 * Note that post increment/decrement has a "no LineTerminator here"
62119 * restriction. This is handled by duk__expr_lbp(), which forcibly terminates
62120 * the previous expression if a LineTerminator occurs before '++'/'--'.
62121 */
62122
62123 duk_reg_t reg_res;
62124 duk_small_uint_t args_op = args >> 8;
62125
62126 /* Specific assumptions for opcode numbering. */
62131
62132 reg_res = DUK__ALLOCTEMP(comp_ctx);
62133
62134 if (left->t == DUK_IVAL_VAR) {
62135 duk_hstring *h_varname;
62136 duk_reg_t reg_varbind;
62137 duk_regconst_t rc_varname;
62138
62139 h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
62140 DUK_ASSERT(h_varname != NULL);
62141
62142 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
62143 goto syntax_error;
62144 }
62145
62146 duk_dup(ctx, left->x1.valstack_idx);
62147 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
62148 duk__emit_a_bc(comp_ctx,
62149 args_op, /* e.g. DUK_OP_POSTINCR */
62150 (duk_regconst_t) reg_res,
62151 (duk_regconst_t) reg_varbind);
62152 } else {
62153 duk__emit_a_bc(comp_ctx,
62154 args_op + 4, /* e.g. DUK_OP_POSTINCV */
62155 (duk_regconst_t) reg_res,
62156 rc_varname);
62157 }
62158
62159 DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
62160 (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
62161 } else if (left->t == DUK_IVAL_PROP) {
62162 duk_reg_t reg_obj; /* allocate to reg only (not const) */
62163 duk_regconst_t rc_key;
62164
62165 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
62166 rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62167 duk__emit_a_b_c(comp_ctx,
62168 args_op + 8, /* e.g. DUK_OP_POSTINCP */
62169 (duk_regconst_t) reg_res,
62170 (duk_regconst_t) reg_obj,
62171 rc_key);
62172 } else {
62173 /* Technically return value is not needed because INVLHS will
62174 * unconditially throw a ReferenceError. Coercion is necessary
62175 * for proper semantics (consider ToNumber() called for an object).
62176 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
62177 */
62178 duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
62179 duk__emit_extraop_bc(comp_ctx,
62181 reg_res); /* for side effects, result ignored */
62182 duk__emit_extraop_only(comp_ctx,
62184 }
62186 res->t = DUK_IVAL_PLAIN;
62187 res->x1.t = DUK_ISPEC_REGCONST;
62188 res->x1.regconst = (duk_regconst_t) reg_res;
62189 DUK__SETTEMP(comp_ctx, reg_res + 1);
62190 return;
62191 }
62192
62193 syntax_error:
62195 return;
62196
62197 syntax_error_lvalue:
62199 return;
62200}
62201
62203 duk_small_int_t tok = comp_ctx->curr_token.t;
62204
62205 DUK_ASSERT(tok >= DUK_TOK_MINVAL && tok <= DUK_TOK_MAXVAL);
62207
62208 /* XXX: integrate support for this into led() instead?
62209 * Similar issue as post-increment/post-decrement.
62210 */
62211
62212 /* prevent duk__expr_led() by using a binding power less than anything valid */
62213 if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
62214 return 0;
62215 }
62216
62217 if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
62218 (comp_ctx->curr_token.lineterm)) {
62219 /* '++' or '--' in a post-increment/decrement position,
62220 * and a LineTerminator occurs between the operator and
62221 * the preceding expression. Force the previous expr
62222 * to terminate, in effect treating e.g. "a,b\n++" as
62223 * "a,b;++" (= SyntaxError).
62225 return 0;
62227
62228 return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]); /* format is bit packed */
62230
62231/*
62232 * Expression parsing.
62233 *
62234 * Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
62235 * first token of the expression. Upon exit, 'curr_tok' will be the first
62236 * token not part of the expression (e.g. semicolon terminating an expression
62237 * statement).
62238 */
62239
62240#define DUK__EXPR_RBP_MASK 0xff
62241#define DUK__EXPR_FLAG_REJECT_IN (1 << 8) /* reject 'in' token (used for for-in) */
62242#define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9) /* allow empty expression */
62243#define DUK__EXPR_FLAG_REQUIRE_INIT (1 << 10) /* require initializer for var/const */
62244
62245/* main expression parser function */
62246DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62247 duk_hthread *thr = comp_ctx->thr;
62248 duk_context *ctx = (duk_context *) thr;
62249 duk_ivalue tmp_alloc; /* 'res' is used for "left", and 'tmp' for "right" */
62250 duk_ivalue *tmp = &tmp_alloc;
62251 duk_small_uint_t rbp;
62252
62253 DUK__RECURSION_INCREASE(comp_ctx, thr);
62254
62256
62257 /* filter out flags from exprtop rbp_flags here to save space */
62258 rbp = rbp_flags & DUK__EXPR_RBP_MASK;
62259
62260 DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
62261 (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
62262 (long) comp_ctx->curr_func.paren_level));
62263
62264 DUK_MEMZERO(&tmp_alloc, sizeof(tmp_alloc));
62265 tmp->x1.valstack_idx = duk_get_top(ctx);
62266 tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
62267 duk_push_undefined(ctx);
62268 duk_push_undefined(ctx);
62269
62270 /* XXX: where to release temp regs in intermediate expressions?
62271 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
62272 * that particular expression temp regs can be forced here.
62273 */
62274
62275 /* XXX: increase ctx->expr_tokens here for every consumed token
62276 * (this would be a nice statistic)?
62277 */
62278
62279 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
62280 /* XXX: possibly incorrect handling of empty expression */
62281 DUK_DDD(DUK_DDDPRINT("empty expression"));
62282 if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
62284 }
62285 res->t = DUK_IVAL_PLAIN;
62286 res->x1.t = DUK_ISPEC_VALUE;
62287 duk_push_undefined(ctx);
62288 duk_replace(ctx, res->x1.valstack_idx);
62289 goto cleanup;
62290 }
62292 duk__advance(comp_ctx);
62293 duk__expr_nud(comp_ctx, res); /* reuse 'res' as 'left' */
62294 while (rbp < duk__expr_lbp(comp_ctx)) {
62295 duk__advance(comp_ctx);
62296 duk__expr_led(comp_ctx, res, tmp);
62297 duk__copy_ivalue(comp_ctx, tmp, res); /* tmp -> res */
62298 }
62299
62300 cleanup:
62301 /* final result is already in 'res' */
62302
62303 duk_pop_2(ctx);
62304
62305 DUK__RECURSION_DECREASE(comp_ctx, thr);
62306}
62307
62308DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62309 duk_hthread *thr = comp_ctx->thr;
62310
62311 /* Note: these variables must reside in 'curr_func' instead of the global
62312 * context: when parsing function expressions, expression parsing is nested.
62313 */
62314 comp_ctx->curr_func.nud_count = 0;
62315 comp_ctx->curr_func.led_count = 0;
62316 comp_ctx->curr_func.paren_level = 0;
62317 comp_ctx->curr_func.expr_lhs = 1;
62318 comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
62319
62320 duk__expr(comp_ctx, res, rbp_flags);
62321
62322 if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
62324 }
62325}
62326
62327/* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
62328 * and result conversions.
62329 *
62330 * Each helper needs at least 2-3 calls to make it worth while to wrap.
62331 */
62332
62333#if 0 /* unused */
62334DUK_LOCAL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62335 duk__expr(comp_ctx, res, rbp_flags);
62336 return duk__ivalue_toreg(comp_ctx, res);
62337}
62338#endif
62339
62340#if 0 /* unused */
62341DUK_LOCAL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62342 duk__expr(comp_ctx, res, rbp_flags);
62343 return duk__ivalue_totemp(comp_ctx, res);
62344}
62345#endif
62346
62347DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
62348 DUK_ASSERT(forced_reg >= 0);
62349 duk__expr(comp_ctx, res, rbp_flags);
62350 duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
62351}
62352
62354 duk__expr(comp_ctx, res, rbp_flags);
62355 return duk__ivalue_toregconst(comp_ctx, res);
62356}
62357
62358#if 0 /* unused */
62359DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62360 duk__expr(comp_ctx, res, rbp_flags);
62361 return duk__ivalue_totempconst(comp_ctx, res);
62362}
62363#endif
62364
62366 duk__expr(comp_ctx, res, rbp_flags);
62367 duk__ivalue_toplain(comp_ctx, res);
62368}
62369
62371 duk__expr(comp_ctx, res, rbp_flags);
62372 duk__ivalue_toplain_ignore(comp_ctx, res);
62373}
62374
62376 duk__exprtop(comp_ctx, res, rbp_flags);
62377 return duk__ivalue_toreg(comp_ctx, res);
62378}
62379
62380#if 0 /* unused */
62381DUK_LOCAL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62382 duk__exprtop(comp_ctx, res, rbp_flags);
62383 return duk__ivalue_totemp(comp_ctx, res);
62384}
62385#endif
62386
62387DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
62388 DUK_ASSERT(forced_reg >= 0);
62389 duk__exprtop(comp_ctx, res, rbp_flags);
62390 duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
62391}
62392
62394 duk__exprtop(comp_ctx, res, rbp_flags);
62395 return duk__ivalue_toregconst(comp_ctx, res);
62396}
62397
62398#if 0 /* unused */
62399DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
62400 duk__exprtop(comp_ctx, res, rbp_flags);
62401 duk__ivalue_toplain_ignore(comp_ctx, res);
62402}
62403#endif
62404
62405/*
62406 * Parse an individual source element (top level statement) or a statement.
62407 *
62408 * Handles labeled statements automatically (peeling away labels before
62409 * parsing an expression that follows the label(s)).
62410 *
62411 * Upon entry, 'curr_tok' contains the first token of the statement (parsed
62412 * in "allow regexp literal" mode). Upon exit, 'curr_tok' contains the first
62413 * token following the statement (if the statement has a terminator, this is
62414 * the token after the terminator).
62415 */
62417#ifdef DUK__HAS_VAL
62418#undef DUK__HAS_VAL
62419#endif
62420#ifdef DUK__HAS_TERM
62421#undef DUK__HAS_TERM
62422#endif
62423#ifdef DUK__ALLOW_AUTO_SEMI_ALWAYS
62424#undef DUK__ALLOW_AUTO_SEMI_ALWAYS
62425#endif
62426#ifdef DUK__STILL_PROLOGUE
62427#undef DUK__STILL_PROLOGUE
62428#endif
62429#ifdef DUK__IS_TERMINAL
62430#undef DUK__IS_TERMINAL
62431#endif
62432
62433#define DUK__HAS_VAL (1 << 0) /* stmt has non-empty value */
62434#define DUK__HAS_TERM (1 << 1) /* stmt has explicit/implicit semicolon terminator */
62435#define DUK__ALLOW_AUTO_SEMI_ALWAYS (1 << 2) /* allow automatic semicolon even without lineterm (compatibility) */
62436#define DUK__STILL_PROLOGUE (1 << 3) /* statement does not terminate directive prologue */
62437#define DUK__IS_TERMINAL (1 << 4) /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
62438
62439/* Parse a single variable declaration (e.g. "i" or "i=10"). A leading 'var'
62440 * has already been eaten. These is no return value in 'res', it is used only
62441 * as a temporary.
62442 *
62443 * When called from 'for-in' statement parser, the initializer expression must
62444 * not allow the 'in' token. The caller supply additional expression parsing
62445 * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
62446 *
62447 * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
62448 * the identifier is bound:
62449 *
62450 * If register bound: out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
62451 * If not register bound: out_reg_varbind < 0, out_rc_varname >= 0
62452 *
62453 * These allow the caller to use the variable for further assignment, e.g.
62454 * as is done in 'for-in' parsing.
62455 */
62456
62457DUK_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) {
62458 duk_hthread *thr = comp_ctx->thr;
62459 duk_context *ctx = (duk_context *) thr;
62460 duk_hstring *h_varname;
62461 duk_reg_t reg_varbind;
62462 duk_regconst_t rc_varname;
62463
62464 /* assume 'var' has been eaten */
62465
62466 /* Note: Identifier rejects reserved words */
62467 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
62468 goto syntax_error;
62469 }
62470 h_varname = comp_ctx->curr_token.str1;
62471
62472 DUK_ASSERT(h_varname != NULL);
62473
62474 /* strict mode restrictions (E5 Section 12.2.1) */
62475 if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
62476 goto syntax_error;
62477 }
62478
62479 /* register declarations in first pass */
62480 if (comp_ctx->curr_func.in_scanning) {
62481 duk_uarridx_t n;
62482 DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
62483 (duk_heaphdr *) h_varname));
62484 n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
62485 duk_push_hstring(ctx, h_varname);
62486 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
62487 duk_push_int(ctx, DUK_DECL_TYPE_VAR + (0 << 8));
62488 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
62489 }
62490
62491 duk_push_hstring(ctx, h_varname); /* push before advancing to keep reachable */
62492
62493 /* register binding lookup is based on varmap (even in first pass) */
62494 duk_dup_top(ctx);
62495 (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
62496
62497 duk__advance(comp_ctx); /* eat identifier */
62498
62499 if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
62500 duk__advance(comp_ctx);
62501
62502 DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
62503 (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
62504
62505 duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/); /* AssignmentExpression */
62506
62507 if (reg_varbind >= 0) {
62508 duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
62509 } else {
62510 duk_reg_t reg_val;
62511 reg_val = duk__ivalue_toreg(comp_ctx, res);
62512 duk__emit_a_bc(comp_ctx,
62514 (duk_regconst_t) reg_val,
62515 rc_varname);
62516 }
62517 } else {
62519 /* Used for minimal 'const': initializer required. */
62520 goto syntax_error;
62521 }
62522 }
62523
62524 duk_pop(ctx); /* pop varname */
62525
62526 *out_rc_varname = rc_varname;
62527 *out_reg_varbind = reg_varbind;
62528
62529 return;
62530
62531 syntax_error:
62533}
62534
62536 duk_reg_t reg_varbind;
62537 duk_regconst_t rc_varname;
62538
62539 duk__advance(comp_ctx); /* eat 'var' */
62540
62541 for (;;) {
62542 /* rc_varname and reg_varbind are ignored here */
62543 duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
62544
62545 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
62546 break;
62547 }
62548 duk__advance(comp_ctx);
62549 }
62550}
62551
62552DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
62553 duk_hthread *thr = comp_ctx->thr;
62554 duk_context *ctx = (duk_context *) thr;
62555 duk_int_t pc_v34_lhs; /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
62556 duk_reg_t temp_reset; /* knock back "next temp" to this whenever possible */
62557 duk_reg_t reg_temps; /* preallocated temporaries (2) for variants 3 and 4 */
62558
62559 DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
62560
62561 /* Two temporaries are preallocated here for variants 3 and 4 which need
62562 * registers which are never clobbered by expressions in the loop
62563 * (concretely: for the enumerator object and the next enumerated value).
62564 * Variants 1 and 2 "release" these temps.
62565 */
62566
62567 reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
62568
62569 temp_reset = DUK__GETTEMP(comp_ctx);
62570
62571 /*
62572 * For/for-in main variants are:
62573 *
62574 * 1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
62575 * 2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
62576 * 3. for (LeftHandSideExpression in Expression) Statement
62577 * 4. for (var VariableDeclarationNoIn in Expression) Statement
62578 *
62579 * Parsing these without arbitrary lookahead or backtracking is relatively
62580 * tricky but we manage to do so for now.
62581 *
62582 * See doc/compiler.rst for a detailed discussion of control flow
62583 * issues, evaluation order issues, etc.
62584 */
62585
62586 duk__advance(comp_ctx); /* eat 'for' */
62588
62589 DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
62590
62591 /* a label site has been emitted by duk__parse_stmt() automatically
62592 * (it will also emit the ENDLABEL).
62593 */
62594
62595 if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
62596 /*
62597 * Variant 2 or 4
62598 */
62599
62600 duk_reg_t reg_varbind; /* variable binding register if register-bound (otherwise < 0) */
62601 duk_regconst_t rc_varname; /* variable name reg/const, if variable not register-bound */
62602
62603 duk__advance(comp_ctx); /* eat 'var' */
62604 duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
62605 DUK__SETTEMP(comp_ctx, temp_reset);
62606
62607 if (comp_ctx->curr_token.t == DUK_TOK_IN) {
62608 /*
62609 * Variant 4
62610 */
62611
62612 DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
62613 pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here */
62614 if (reg_varbind >= 0) {
62615 duk__emit_a_bc(comp_ctx,
62617 (duk_regconst_t) reg_varbind,
62618 (duk_regconst_t) (reg_temps + 0));
62619 } else {
62620 duk__emit_a_bc(comp_ctx,
62622 (duk_regconst_t) (reg_temps + 0),
62623 rc_varname);
62624 }
62625 goto parse_3_or_4;
62626 } else {
62627 /*
62628 * Variant 2
62629 */
62630
62631 DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
62632 for (;;) {
62633 /* more initializers */
62634 if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
62635 break;
62636 }
62637 DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
62638
62639 duk__advance(comp_ctx); /* eat comma */
62640 duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
62641 }
62642 goto parse_1_or_2;
62643 }
62644 } else {
62645 /*
62646 * Variant 1 or 3
62647 */
62648
62649 pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here (variant 3) */
62650
62651 /* Note that duk__exprtop() here can clobber any reg above current temp_next,
62652 * so any loop variables (e.g. enumerator) must be "preallocated".
62653 */
62654
62655 /* don't coerce yet to a plain value (variant 3 needs special handling) */
62656 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression */
62657 if (comp_ctx->curr_token.t == DUK_TOK_IN) {
62658 /*
62659 * Variant 3
62660 */
62661
62662 /* XXX: need to determine LHS type, and check that it is LHS compatible */
62663 DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
62664 if (duk__expr_is_empty(comp_ctx)) {
62665 goto syntax_error; /* LeftHandSideExpression does not allow empty expression */
62666 }
62667
62668 if (res->t == DUK_IVAL_VAR) {
62669 duk_reg_t reg_varbind;
62670 duk_regconst_t rc_varname;
62671
62672 duk_dup(ctx, res->x1.valstack_idx);
62673 if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
62674 duk__emit_a_bc(comp_ctx,
62676 (duk_regconst_t) reg_varbind,
62677 (duk_regconst_t) (reg_temps + 0));
62678 } else {
62679 duk__emit_a_bc(comp_ctx,
62681 (duk_regconst_t) (reg_temps + 0),
62682 rc_varname);
62683 }
62684 } else if (res->t == DUK_IVAL_PROP) {
62685 /* Don't allow a constant for the object (even for a number etc), as
62686 * it goes into the 'A' field of the opcode.
62687 */
62688 duk_reg_t reg_obj;
62689 duk_regconst_t rc_key;
62690 reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
62691 rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62692 duk__emit_a_b_c(comp_ctx,
62694 (duk_regconst_t) reg_obj,
62695 rc_key,
62696 (duk_regconst_t) (reg_temps + 0));
62697 } else {
62698 duk__ivalue_toplain_ignore(comp_ctx, res); /* just in case */
62699 duk__emit_extraop_only(comp_ctx,
62701 }
62702 goto parse_3_or_4;
62703 } else {
62704 /*
62705 * Variant 1
62706 */
62707
62708 DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
62709 duk__ivalue_toplain_ignore(comp_ctx, res);
62710 goto parse_1_or_2;
62711 }
62712 }
62713
62714 parse_1_or_2:
62715 /*
62716 * Parse variant 1 or 2. The first part expression (which differs
62717 * in the variants) has already been parsed and its code emitted.
62718 *
62719 * reg_temps + 0: unused
62720 * reg_temps + 1: unused
62721 */
62722 {
62723 duk_regconst_t rc_cond;
62724 duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
62725 duk_int_t pc_jumpto_l3, pc_jumpto_l4;
62726 duk_bool_t expr_c_empty;
62727
62728 DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
62729
62730 /* "release" preallocated temps since we won't need them */
62731 temp_reset = reg_temps + 0;
62732 DUK__SETTEMP(comp_ctx, temp_reset);
62733
62735
62736 pc_l1 = duk__get_current_pc(comp_ctx);
62737 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
62738 if (duk__expr_is_empty(comp_ctx)) {
62739 /* no need to coerce */
62740 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
62741 pc_jumpto_l4 = -1; /* omitted */
62742 } else {
62743 rc_cond = duk__ivalue_toregconst(comp_ctx, res);
62744 duk__emit_if_false_skip(comp_ctx, rc_cond);
62745 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
62746 pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx); /* to exit */
62747 }
62748 DUK__SETTEMP(comp_ctx, temp_reset);
62749
62751
62752 pc_l2 = duk__get_current_pc(comp_ctx);
62753 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
62754 if (duk__expr_is_empty(comp_ctx)) {
62755 /* no need to coerce */
62756 expr_c_empty = 1;
62757 /* JUMP L1 omitted */
62758 } else {
62759 duk__ivalue_toplain_ignore(comp_ctx, res);
62760 expr_c_empty = 0;
62761 duk__emit_jump(comp_ctx, pc_l1);
62762 }
62763 DUK__SETTEMP(comp_ctx, temp_reset);
62764
62766
62767 pc_l3 = duk__get_current_pc(comp_ctx);
62768 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
62769 if (expr_c_empty) {
62770 duk__emit_jump(comp_ctx, pc_l1);
62771 } else {
62772 duk__emit_jump(comp_ctx, pc_l2);
62773 }
62774 /* temp reset is not necessary after duk__parse_stmt(), which already does it */
62775
62776 pc_l4 = duk__get_current_pc(comp_ctx);
62777
62778 DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
62779 "break: %ld->%ld, continue: %ld->%ld",
62780 (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
62781 (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
62782
62783 duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
62784 duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
62785 duk__patch_jump(comp_ctx,
62786 pc_label_site + 1,
62787 pc_l4); /* break jump */
62788 duk__patch_jump(comp_ctx,
62789 pc_label_site + 2,
62790 expr_c_empty ? pc_l1 : pc_l2); /* continue jump */
62791 }
62792 goto finished;
62793
62794 parse_3_or_4:
62795 /*
62796 * Parse variant 3 or 4.
62797 *
62798 * For variant 3 (e.g. "for (A in C) D;") the code for A (except the
62799 * final property/variable write) has already been emitted. The first
62800 * instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
62801 * there to satisfy control flow needs.
62802 *
62803 * For variant 4, if the variable declaration had an initializer
62804 * (e.g. "for (var A = B in C) D;") the code for the assignment
62805 * (B) has already been emitted.
62806 *
62807 * Variables set before entering here:
62808 *
62809 * pc_v34_lhs: insert a "JUMP L2" here (see doc/compiler.rst example).
62810 * reg_temps + 0: iteration target value (written to LHS)
62811 * reg_temps + 1: enumerator object
62812 */
62813 {
62814 duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
62815 duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
62816 duk_reg_t reg_target;
62817
62818 DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
62819
62820 DUK__SETTEMP(comp_ctx, temp_reset);
62821
62822 /* First we need to insert a jump in the middle of previously
62823 * emitted code to get the control flow right. No jumps can
62824 * cross the position where the jump is inserted. See doc/compiler.rst
62825 * for discussion on the intricacies of control flow and side effects
62826 * for variants 3 and 4.
62827 */
62828
62829 duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
62830 pc_jumpto_l2 = pc_v34_lhs; /* inserted jump */
62831 pc_l1 = pc_v34_lhs + 1; /* +1, right after inserted jump */
62832
62833 /* The code for writing reg_temps + 0 to the left hand side has already
62834 * been emitted.
62835 */
62836
62837 pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* -> loop body */
62838
62839 duk__advance(comp_ctx); /* eat 'in' */
62840
62841 /* Parse enumeration target and initialize enumerator. For 'null' and 'undefined',
62842 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
62843 * (E5 Section 12.6.4, step 3). Note that INITENUM requires the value to be in a
62844 * register (constant not allowed).
62845 */
62846
62847 pc_l2 = duk__get_current_pc(comp_ctx);
62848 reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression */
62849 duk__emit_extraop_b_c(comp_ctx,
62851 (duk_regconst_t) (reg_temps + 1),
62852 (duk_regconst_t) reg_target);
62853 pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
62854 DUK__SETTEMP(comp_ctx, temp_reset);
62855
62857
62858 pc_l3 = duk__get_current_pc(comp_ctx);
62859 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
62860 /* temp reset is not necessary after duk__parse_stmt(), which already does it */
62861
62862 /* NEXTENUM needs a jump slot right after the main opcode.
62863 * We need the code emitter to reserve the slot: if there's
62864 * target shuffling, the target shuffle opcodes must happen
62865 * after the jump slot (for NEXTENUM the shuffle opcodes are
62866 * not needed if the enum is finished).
62867 */
62868 pc_l4 = duk__get_current_pc(comp_ctx);
62869 duk__emit_extraop_b_c(comp_ctx,
62871 (duk_regconst_t) (reg_temps + 0),
62872 (duk_regconst_t) (reg_temps + 1));
62873 pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc; /* NEXTENUM jump slot: executed when enum finished */
62874 duk__emit_jump(comp_ctx, pc_l1); /* jump to next loop, using reg_v34_iter as iterated value */
62875
62876 pc_l5 = duk__get_current_pc(comp_ctx);
62877
62878 /* XXX: since the enumerator may be a memory expensive object,
62879 * perhaps clear it explicitly here? If so, break jump must
62880 * go through this clearing operation.
62881 */
62882
62883 DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
62884 "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
62885 "break: %ld->%ld, continue: %ld->%ld",
62886 (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
62887 (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
62888 (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
62889
62890 duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
62891 duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
62892 duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
62893 duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
62894 duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5); /* break jump */
62895 duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4); /* continue jump */
62896 }
62897 goto finished;
62898
62899 finished:
62900 DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
62901 return;
62902
62903 syntax_error:
62905}
62906
62907DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
62908 duk_hthread *thr = comp_ctx->thr;
62909 duk_reg_t temp_at_loop;
62910 duk_regconst_t rc_switch; /* reg/const for switch value */
62911 duk_regconst_t rc_case; /* reg/const for case value */
62912 duk_reg_t reg_temp; /* general temp register */
62913 duk_int_t pc_prevcase = -1;
62914 duk_int_t pc_prevstmt = -1;
62915 duk_int_t pc_default = -1; /* -1 == not set, -2 == pending (next statement list) */
62916
62917 /* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
62918
62919 /*
62920 * Switch is pretty complicated because of several conflicting concerns:
62921 *
62922 * - Want to generate code without an intermediate representation,
62923 * i.e., in one go
62924 *
62925 * - Case selectors are expressions, not values, and may thus e.g. throw
62926 * exceptions (which causes evaluation order concerns)
62927 *
62928 * - Evaluation semantics of case selectors and default clause need to be
62929 * carefully implemented to provide correct behavior even with case value
62930 * side effects
62931 *
62932 * - Fall through case and default clauses; avoiding dead JUMPs if case
62933 * ends with an unconditional jump (a break or a continue)
62934 *
62935 * - The same case value may occur multiple times, but evaluation rules
62936 * only process the first match before switching to a "propagation" mode
62937 * where case values are no longer evaluated
62938 *
62939 * See E5 Section 12.11. Also see doc/compiler.rst for compilation
62940 * discussion.
62941 */
62942
62943 duk__advance(comp_ctx);
62945 rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
62948
62949 DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
62950
62951 temp_at_loop = DUK__GETTEMP(comp_ctx);
62952
62953 for (;;) {
62954 duk_int_t num_stmts;
62955 duk_small_int_t tok;
62956
62957 /* sufficient for keeping temp reg numbers in check */
62958 DUK__SETTEMP(comp_ctx, temp_at_loop);
62959
62960 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
62961 break;
62962 }
62963
62964 /*
62965 * Parse a case or default clause.
62966 */
62967
62968 if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
62969 /*
62970 * Case clause.
62971 *
62972 * Note: cannot use reg_case as a temp register (for SEQ target)
62973 * because it may be a constant.
62974 */
62975
62976 duk__patch_jump_here(comp_ctx, pc_prevcase); /* chain jumps for case
62977 * evaluation and checking
62978 */
62979
62980 duk__advance(comp_ctx);
62981 rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
62983
62984 reg_temp = DUK__ALLOCTEMP(comp_ctx);
62985 duk__emit_a_b_c(comp_ctx,
62986 DUK_OP_SEQ,
62987 (duk_regconst_t) reg_temp,
62988 rc_switch,
62989 rc_case);
62990 duk__emit_if_true_skip(comp_ctx, (duk_regconst_t) reg_temp);
62991
62992 /* jump to next case clause */
62993 pc_prevcase = duk__emit_jump_empty(comp_ctx); /* no match, next case */
62994
62995 /* statements go here (if any) on next loop */
62996 } else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
62997 /*
62998 * Default clause.
62999 */
63000
63001 if (pc_default >= 0) {
63002 goto syntax_error;
63003 }
63004 duk__advance(comp_ctx);
63006
63007 /* Fix for https://github.com/svaarala/duktape/issues/155:
63008 * If 'default' is first clause (detected by pc_prevcase < 0)
63009 * we need to ensure we stay in the matching chain.
63010 */
63011 if (pc_prevcase < 0) {
63012 DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
63013 pc_prevcase = duk__emit_jump_empty(comp_ctx);
63014 }
63015
63016 /* default clause matches next statement list (if any) */
63017 pc_default = -2;
63018 } else {
63019 /* Code is not accepted before the first case/default clause */
63020 goto syntax_error;
63021 }
63022
63023 /*
63024 * Parse code after the clause. Possible terminators are
63025 * 'case', 'default', and '}'.
63026 *
63027 * Note that there may be no code at all, not even an empty statement,
63028 * between case clauses. This must be handled just like an empty statement
63029 * (omitting seemingly pointless JUMPs), to avoid situations like
63030 * test-bug-case-fallthrough.js.
63031 */
63032
63033 num_stmts = 0;
63034 if (pc_default == -2) {
63035 pc_default = duk__get_current_pc(comp_ctx);
63036 }
63037
63038 /* Note: this is correct even for default clause statements:
63039 * they participate in 'fall-through' behavior even if the
63040 * default clause is in the middle.
63041 */
63042 duk__patch_jump_here(comp_ctx, pc_prevstmt); /* chain jumps for 'fall-through'
63043 * after a case matches.
63044 */
63045
63046 for (;;) {
63047 tok = comp_ctx->curr_token.t;
63048 if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
63049 tok == DUK_TOK_RCURLY) {
63050 break;
63051 }
63052 num_stmts++;
63053 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63054 }
63055
63056 /* fall-through jump to next code of next case (backpatched) */
63057 pc_prevstmt = duk__emit_jump_empty(comp_ctx);
63058
63059 /* XXX: would be nice to omit this jump when the jump is not
63060 * reachable, at least in the obvious cases (such as the case
63061 * ending with a 'break'.
63062 *
63063 * Perhaps duk__parse_stmt() could provide some info on whether
63064 * the statement is a "dead end"?
63065 *
63066 * If implemented, just set pc_prevstmt to -1 when not needed.
63067 */
63068 }
63069
63070 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
63071 duk__advance(comp_ctx);
63072
63073 /* default case control flow patchup; note that if pc_prevcase < 0
63074 * (i.e. no case clauses), control enters default case automatically.
63075 */
63076 if (pc_default >= 0) {
63077 /* default case exists: go there if no case matches */
63078 duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
63079 } else {
63080 /* default case does not exist, or no statements present
63081 * after default case: finish case evaluation
63082 */
63083 duk__patch_jump_here(comp_ctx, pc_prevcase);
63084 }
63085
63086 /* fall-through control flow patchup; note that pc_prevstmt may be
63087 * < 0 (i.e. no case clauses), in which case this is a no-op.
63088 */
63089 duk__patch_jump_here(comp_ctx, pc_prevstmt);
63090
63091 /* continue jump not patched, an INVALID opcode remains there */
63092 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
63093
63094 /* Note: 'fast' breaks will jump to pc_label_site + 1, which will
63095 * then jump here. The double jump will be eliminated by a
63096 * peephole pass, resulting in an optimal jump here. The label
63097 * site jumps will remain in bytecode and will waste code size.
63098 */
63099
63100 return;
63101
63102 syntax_error:
63104}
63105
63107 duk_reg_t temp_reset;
63108 duk_regconst_t rc_cond;
63109 duk_int_t pc_jump_false;
63110
63111 DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
63112
63113 temp_reset = DUK__GETTEMP(comp_ctx);
63114
63115 duk__advance(comp_ctx); /* eat 'if' */
63117
63118 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63119 duk__emit_if_true_skip(comp_ctx, rc_cond);
63120 pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */
63121 DUK__SETTEMP(comp_ctx, temp_reset);
63122
63124
63125 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63126
63127 /* The 'else' ambiguity is resolved by 'else' binding to the innermost
63128 * construct, so greedy matching is correct here.
63129 */
63130
63131 if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
63132 duk_int_t pc_jump_end;
63133
63134 DUK_DDD(DUK_DDDPRINT("if has else part"));
63135
63136 duk__advance(comp_ctx);
63137
63138 pc_jump_end = duk__emit_jump_empty(comp_ctx); /* jump from true part to end */
63139 duk__patch_jump_here(comp_ctx, pc_jump_false);
63140
63141 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63142
63143 duk__patch_jump_here(comp_ctx, pc_jump_end);
63144 } else {
63145 DUK_DDD(DUK_DDDPRINT("if does not have else part"));
63146
63147 duk__patch_jump_here(comp_ctx, pc_jump_false);
63148 }
63149
63150 DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
63151}
63152
63153DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
63154 duk_regconst_t rc_cond;
63155 duk_int_t pc_start;
63156
63157 DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
63158
63159 duk__advance(comp_ctx); /* eat 'do' */
63160
63161 pc_start = duk__get_current_pc(comp_ctx);
63162 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63163 duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
63164
63167
63168 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63169 duk__emit_if_false_skip(comp_ctx, rc_cond);
63170 duk__emit_jump(comp_ctx, pc_start);
63171 /* no need to reset temps, as we're finished emitting code */
63172
63174
63175 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
63176
63177 DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
63178}
63179
63180DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
63181 duk_reg_t temp_reset;
63182 duk_regconst_t rc_cond;
63183 duk_int_t pc_start;
63184 duk_int_t pc_jump_false;
63185
63186 DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
63187
63188 temp_reset = DUK__GETTEMP(comp_ctx);
63189
63190 duk__advance(comp_ctx); /* eat 'while' */
63191
63193
63194 pc_start = duk__get_current_pc(comp_ctx);
63195 duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
63197 rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63198 duk__emit_if_true_skip(comp_ctx, rc_cond);
63199 pc_jump_false = duk__emit_jump_empty(comp_ctx);
63200 DUK__SETTEMP(comp_ctx, temp_reset);
63201
63203
63204 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63205 duk__emit_jump(comp_ctx, pc_start);
63206
63207 duk__patch_jump_here(comp_ctx, pc_jump_false);
63208 duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
63209
63210 DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
63211}
63212
63214 duk_hthread *thr = comp_ctx->thr;
63215 duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
63216 duk_int_t label_id;
63217 duk_int_t label_catch_depth;
63218 duk_int_t label_pc; /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
63219 duk_bool_t label_is_closest;
63220
63221 DUK_UNREF(res);
63222
63223 duk__advance(comp_ctx); /* eat 'break' or 'continue' */
63224
63225 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
63226 comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
63227 comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
63228 /* break/continue without label */
63229
63230 duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
63231 } else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
63232 /* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
63233 DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
63234 duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
63235 duk__advance(comp_ctx);
63236 } else {
63238 }
63239
63240 /* Use a fast break/continue when possible. A fast break/continue is
63241 * just a jump to the LABEL break/continue jump slot, which then jumps
63242 * to an appropriate place (for break, going through ENDLABEL correctly).
63243 * The peephole optimizer will optimize the jump to a direct one.
63244 */
63245
63246 if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
63247 label_is_closest) {
63248 DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
63249 "label_catch_depth=%ld, catch_depth=%ld "
63250 "-> use fast variant (direct jump)",
63251 (long) is_break, (long) label_id, (long) label_is_closest,
63252 (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
63253
63254 duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
63255 } else {
63256 DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
63257 "label_catch_depth=%ld, catch_depth=%ld "
63258 "-> use slow variant (longjmp)",
63259 (long) is_break, (long) label_id, (long) label_is_closest,
63260 (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
63261
63262 duk__emit_extraop_bc(comp_ctx,
63264 (duk_regconst_t) label_id);
63265 }
63266}
63267
63269 duk_hthread *thr = comp_ctx->thr;
63270 duk_regconst_t rc_val;
63271 duk_small_uint_t ret_flags;
63272
63273 duk__advance(comp_ctx); /* eat 'return' */
63274
63275 /* A 'return' statement is only allowed inside an actual function body,
63276 * not as part of eval or global code.
63277 */
63278 if (!comp_ctx->curr_func.is_function) {
63280 }
63281
63282 ret_flags = 0;
63283
63284 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
63285 comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
63286 comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
63287 DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
63288 rc_val = 0;
63289 } else {
63290 duk_int_t pc_before_expr;
63291 duk_int_t pc_after_expr;
63292
63293 DUK_DDD(DUK_DDDPRINT("return with a value"));
63294
63295 DUK_UNREF(pc_before_expr);
63296 DUK_UNREF(pc_after_expr);
63297
63298 pc_before_expr = duk__get_current_pc(comp_ctx);
63299 rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63300 pc_after_expr = duk__get_current_pc(comp_ctx);
63301
63302 /* Tail call check: if last opcode emitted was CALL(I), and
63303 * the context allows it, change the CALL(I) to a tail call.
63304 * This doesn't guarantee that a tail call will be allowed at
63305 * runtime, so the RETURN must still be emitted. (Duktape
63306 * 0.10.0 avoided this and simulated a RETURN if a tail call
63307 * couldn't be used at runtime; but this didn't work
63308 * correctly with a thread yield/resume, see
63309 * test-bug-tailcall-thread-yield-resume.js for discussion.)
63310 *
63311 * In addition to the last opcode being CALL, we also need to
63312 * be sure that 'rc_val' is the result register of the CALL(I).
63313 * For instance, for the expression 'return 0, (function ()
63314 * { return 1; }), 2' the last opcode emitted is CALL (no
63315 * bytecode is emitted for '2') but 'rc_val' indicates
63316 * constant '2'. Similarly if '2' is replaced by a register
63317 * bound variable, no opcodes are emitted but tail call would
63318 * be incorrect.
63319 *
63320 * This is tricky and easy to get wrong. It would be best to
63321 * track enough expression metadata to check that 'rc_val' came
63322 * from that last CALL instruction. We don't have that metadata
63323 * now, so we check that 'rc_val' is a temporary register result
63324 * (not a constant or a register bound variable). There should
63325 * be no way currently for 'rc_val' to be a temporary for an
63326 * expression following the CALL instruction without emitting
63327 * some opcodes following the CALL. This proxy check is used
63328 * below.
63329 *
63330 * See: test-bug-comma-expr-gh131.js.
63331 *
63332 * The non-standard 'caller' property disables tail calls
63333 * because they pose some special cases which haven't been
63334 * fixed yet.
63335 */
63336
63337#if defined(DUK_USE_TAILCALL)
63338 if (comp_ctx->curr_func.catch_depth == 0 && /* no catchers */
63339 pc_after_expr > pc_before_expr) { /* at least one opcode emitted */
63340 duk_compiler_instr *instr;
63342
63343 instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
63344 DUK_ASSERT(instr != NULL);
63345
63346 op = (duk_small_uint_t) DUK_DEC_OP(instr->ins);
63347 if ((op == DUK_OP_CALL || op == DUK_OP_CALLI) &&
63348 DUK__ISTEMP(comp_ctx, rc_val) /* see above */) {
63349 DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
63350 "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
63351 "and last instruction is a CALL "
63352 "-> set TAILCALL flag"));
63353 /* Just flip the single bit. */
63355 }
63356 }
63357#endif /* DUK_USE_TAILCALL */
63358
63360 }
63361
63362 duk__emit_a_b(comp_ctx,
63364 (duk_regconst_t) ret_flags /*flags*/,
63365 rc_val /*reg*/);
63366}
63367
63369 duk_reg_t reg_val;
63370
63371 duk__advance(comp_ctx); /* eat 'throw' */
63372
63373 /* Unlike break/continue, throw statement does not allow an empty value. */
63374
63375 if (comp_ctx->curr_token.lineterm) {
63377 }
63378
63379 reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63380 duk__emit_extraop_bc(comp_ctx,
63382 (duk_regconst_t) reg_val);
63383}
63384
63386 duk_hthread *thr = comp_ctx->thr;
63387 duk_context *ctx = (duk_context *) thr;
63388 duk_reg_t reg_catch; /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
63389 duk_regconst_t rc_varname = 0;
63390 duk_small_uint_t trycatch_flags = 0;
63391 duk_int_t pc_ldconst = -1;
63392 duk_int_t pc_trycatch = -1;
63393 duk_int_t pc_catch = -1;
63394 duk_int_t pc_finally = -1;
63395
63396 DUK_UNREF(res);
63397
63398 /*
63399 * See the following documentation for discussion:
63400 *
63401 * doc/execution.rst: control flow details
63402 *
63403 * Try, catch, and finally "parts" are Blocks, not Statements, so
63404 * they must always be delimited by curly braces. This is unlike e.g.
63405 * the if statement, which accepts any Statement. This eliminates any
63406 * questions of matching parts of nested try statements. The Block
63407 * parsing is implemented inline here (instead of calling out).
63408 *
63409 * Finally part has a 'let scoped' variable, which requires a few kinks
63410 * here.
63411 */
63412
63413 comp_ctx->curr_func.catch_depth++;
63414
63415 duk__advance(comp_ctx); /* eat 'try' */
63416
63417 reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
63418
63419 /* The target for this LDCONST may need output shuffling, but we assume
63420 * that 'pc_ldconst' will be the LDCONST that we can patch later. This
63421 * should be the case because there's no input shuffling. (If there's
63422 * no catch clause, this LDCONST will be replaced with a NOP.)
63423 */
63424 pc_ldconst = duk__get_current_pc(comp_ctx);
63425 duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
63426
63427 pc_trycatch = duk__get_current_pc(comp_ctx);
63428 duk__emit_invalid(comp_ctx); /* TRYCATCH, cannot emit now (not enough info) */
63429 duk__emit_invalid(comp_ctx); /* jump for 'catch' case */
63430 duk__emit_invalid(comp_ctx); /* jump for 'finally' case or end (if no finally) */
63431
63432 /* try part */
63434 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63435 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63436 duk__emit_extraop_only(comp_ctx,
63438
63439 if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
63440 /*
63441 * The catch variable must be updated to reflect the new allocated
63442 * register for the duration of the catch clause. We need to store
63443 * and restore the original value for the varmap entry (if any).
63444 */
63445
63446 /*
63447 * Note: currently register bindings must be fixed for the entire
63448 * function. So, even though the catch variable is in a register
63449 * we know, we must use an explicit environment record and slow path
63450 * accesses to read/write the catch binding to make closures created
63451 * within the catch clause work correctly. This restriction should
63452 * be fixable (at least in common cases) later.
63453 *
63454 * See: test-bug-catch-binding-2.js.
63455 *
63456 * XXX: improve to get fast path access to most catch clauses.
63457 */
63458
63459 duk_hstring *h_var;
63460 duk_int_t varmap_value; /* for storing/restoring the varmap binding for catch variable */
63461
63462 DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(ctx)));
63463
63464 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
63465
63466 pc_catch = duk__get_current_pc(comp_ctx);
63467
63468 duk__advance(comp_ctx);
63470
63471 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
63472 /* Identifier, i.e. don't allow reserved words */
63473 goto syntax_error;
63474 }
63475 h_var = comp_ctx->curr_token.str1;
63476 DUK_ASSERT(h_var != NULL);
63477
63478 duk_push_hstring(ctx, h_var); /* keep in on valstack, use borrowed ref below */
63479
63480 if (comp_ctx->curr_func.is_strict &&
63481 ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
63482 (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
63483 DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
63484 goto syntax_error;
63485 }
63486
63487 duk_dup_top(ctx);
63488 rc_varname = duk__getconst(comp_ctx);
63489 DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
63490 (unsigned long) rc_varname, (long) rc_varname));
63491
63492 duk__advance(comp_ctx);
63494
63496
63497 DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
63498 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63499
63500 duk_dup_top(ctx);
63501 duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
63502 if (duk_is_undefined(ctx, -1)) {
63503 varmap_value = -2;
63504 } else if (duk_is_null(ctx, -1)) {
63505 varmap_value = -1;
63506 } else {
63507 DUK_ASSERT(duk_is_number(ctx, -1));
63508 varmap_value = duk_get_int(ctx, -1);
63509 DUK_ASSERT(varmap_value >= 0);
63510 }
63511 duk_pop(ctx);
63512
63513#if 0
63514 /* It'd be nice to do something like this - but it doesn't
63515 * work for closures created inside the catch clause.
63516 */
63517 duk_dup_top(ctx);
63518 duk_push_int(ctx, (duk_int_t) (reg_catch + 0));
63519 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63520#endif
63521 duk_dup_top(ctx);
63522 duk_push_null(ctx);
63523 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63524
63525 duk__emit_a_bc(comp_ctx,
63527 (duk_regconst_t) (reg_catch + 0) /*value*/,
63528 rc_varname /*varname*/);
63529
63530 DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
63531 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63532
63533 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63534 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63535
63536 if (varmap_value == -2) {
63537 /* not present */
63538 duk_del_prop(ctx, comp_ctx->curr_func.varmap_idx);
63539 } else {
63540 if (varmap_value == -1) {
63541 duk_push_null(ctx);
63542 } else {
63543 DUK_ASSERT(varmap_value >= 0);
63544 duk_push_int(ctx, varmap_value);
63545 }
63546 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63547 }
63548 /* varname is popped by above code */
63549
63550 DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
63551 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63552
63553 duk__emit_extraop_only(comp_ctx,
63555
63556 /*
63557 * XXX: for now, indicate that an expensive catch binding
63558 * declarative environment is always needed. If we don't
63559 * need it, we don't need the const_varname either.
63560 */
63561
63562 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
63563
63564 DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(ctx)));
63565 }
63566
63567 if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
63568 trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
63569
63570 pc_finally = duk__get_current_pc(comp_ctx);
63571
63572 duk__advance(comp_ctx);
63573
63575 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63576 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63577 duk__emit_extraop_b(comp_ctx,
63579 reg_catch); /* rethrow */
63580 }
63581
63582 if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
63583 !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
63584 /* must have catch and/or finally */
63585 goto syntax_error;
63586 }
63587
63588 /* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
63589 * will replace the LDCONST with a NOP. For any actual constant (including
63590 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
63591 */
63592
63593 duk__patch_trycatch(comp_ctx,
63594 pc_ldconst,
63595 pc_trycatch,
63596 reg_catch,
63597 rc_varname,
63598 trycatch_flags);
63599
63600 if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
63601 DUK_ASSERT(pc_catch >= 0);
63602 duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
63604
63605 if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
63606 DUK_ASSERT(pc_finally >= 0);
63607 duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
63608 } else {
63609 /* without finally, the second jump slot is used to jump to end of stmt */
63610 duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
63611 }
63612
63613 comp_ctx->curr_func.catch_depth--;
63614 return;
63615
63616 syntax_error:
63618}
63619
63621 duk_int_t pc_trycatch;
63622 duk_int_t pc_finished;
63623 duk_reg_t reg_catch;
63624 duk_small_uint_t trycatch_flags;
63625
63626 if (comp_ctx->curr_func.is_strict) {
63628 }
63629
63630 comp_ctx->curr_func.catch_depth++;
63631
63632 duk__advance(comp_ctx); /* eat 'with' */
63633
63634 reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
63635
63637 duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
63639
63640 pc_trycatch = duk__get_current_pc(comp_ctx);
63641 trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
63642 duk__emit_a_bc(comp_ctx,
63644 (duk_regconst_t) trycatch_flags /*a*/,
63645 (duk_regconst_t) reg_catch /*bc*/);
63646 duk__emit_invalid(comp_ctx); /* catch jump */
63647 duk__emit_invalid(comp_ctx); /* finished jump */
63648
63649 duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63650 duk__emit_extraop_only(comp_ctx,
63652
63653 pc_finished = duk__get_current_pc(comp_ctx);
63654
63655 duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
63656
63657 comp_ctx->curr_func.catch_depth--;
63658}
63659
63661 /* if a site already exists, nop: max one label site per statement */
63662 if (label_id >= 0) {
63663 return label_id;
63664 }
63665
63666 label_id = comp_ctx->curr_func.label_next++;
63667 DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
63668
63669 duk__emit_extraop_bc(comp_ctx,
63671 (duk_regconst_t) label_id);
63672 duk__emit_invalid(comp_ctx);
63673 duk__emit_invalid(comp_ctx);
63674
63675 return label_id;
63676}
63677
63678/* Parse a single statement.
63679 *
63680 * Creates a label site (with an empty label) automatically for iteration
63681 * statements. Also "peels off" any label statements for explicit labels.
63682 */
63683DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
63684 duk_hthread *thr = comp_ctx->thr;
63685 duk_context *ctx = (duk_context *) thr;
63686 duk_bool_t dir_prol_at_entry; /* directive prologue status at entry */
63687 duk_reg_t temp_at_entry;
63688 duk_uarridx_t labels_len_at_entry;
63689 duk_int_t pc_at_entry; /* assumed to also be PC of "LABEL" */
63690 duk_int_t stmt_id;
63691 duk_small_uint_t stmt_flags = 0;
63692 duk_int_t label_id = -1;
63693 duk_small_uint_t tok;
63694
63695 DUK__RECURSION_INCREASE(comp_ctx, thr);
63696
63697 temp_at_entry = DUK__GETTEMP(comp_ctx);
63698 pc_at_entry = duk__get_current_pc(comp_ctx);
63699 labels_len_at_entry = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.labelnames_idx);
63700 stmt_id = comp_ctx->curr_func.stmt_next++;
63701 dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
63702
63703 DUK_UNREF(stmt_id);
63704
63705 DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
63706 "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
63707 (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
63708 (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
63709 (long) comp_ctx->curr_func.catch_depth));
63710
63711 /* The directive prologue flag is cleared by default so that it is
63712 * unset for any recursive statement parsing. It is only "revived"
63713 * if a directive is detected. (We could also make directives only
63714 * allowed if 'allow_source_elem' was true.)
63715 */
63716 comp_ctx->curr_func.in_directive_prologue = 0;
63717
63718 retry_parse:
63719
63720 DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
63721 (long) stmt_id, (long) label_id, (long) allow_source_elem,
63722 (long) comp_ctx->curr_func.catch_depth));
63723
63724 /*
63725 * Detect iteration statements; if encountered, establish an
63726 * empty label.
63727 */
63728
63729 tok = comp_ctx->curr_token.t;
63730 if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
63731 tok == DUK_TOK_SWITCH) {
63732 DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
63733
63734 label_id = duk__stmt_label_site(comp_ctx, label_id);
63735 duk__add_label(comp_ctx,
63737 pc_at_entry /*pc_label*/,
63738 label_id);
63739 }
63740
63741 /*
63742 * Main switch for statement / source element type.
63743 */
63744
63745 switch (comp_ctx->curr_token.t) {
63746 case DUK_TOK_FUNCTION: {
63747 /*
63748 * Function declaration, function expression, or (non-standard)
63749 * function statement.
63750 *
63751 * The E5 specification only allows function declarations at
63752 * the top level (in "source elements"). An ExpressionStatement
63753 * is explicitly not allowed to begin with a "function" keyword
63754 * (E5 Section 12.4). Hence any non-error semantics for such
63755 * non-top-level statements are non-standard. Duktape semantics
63756 * for function statements are modelled after V8, see
63757 * test-dev-func-decl-outside-top.js.
63758 */
63759
63760#if defined(DUK_USE_NONSTD_FUNC_STMT)
63761 /* Lenient: allow function declarations outside top level in
63762 * non-strict mode but reject them in strict mode.
63763 */
63764 if (allow_source_elem || !comp_ctx->curr_func.is_strict)
63765#else /* DUK_USE_NONSTD_FUNC_STMT */
63766 /* Strict: never allow function declarations outside top level. */
63767 if (allow_source_elem)
63768#endif /* DUK_USE_NONSTD_FUNC_STMT */
63769 {
63770 /* FunctionDeclaration: not strictly a statement but handled as such.
63771 *
63772 * O(depth^2) parse count for inner functions is handled by recording a
63773 * lexer offset on the first compilation pass, so that the function can
63774 * be efficiently skipped on the second pass. This is encapsulated into
63775 * duk__parse_func_like_fnum().
63776 */
63777
63778 duk_int_t fnum;
63779
63780 DUK_DDD(DUK_DDDPRINT("function declaration statement"));
63781
63782 duk__advance(comp_ctx); /* eat 'function' */
63783 fnum = duk__parse_func_like_fnum(comp_ctx, 1 /*is_decl*/, 0 /*is_setget*/);
63784
63785 if (comp_ctx->curr_func.in_scanning) {
63786 duk_uarridx_t n;
63787 duk_hstring *h_funcname;
63788
63789 duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, fnum * 3);
63790 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME); /* -> [ ... func name ] */
63791 h_funcname = duk_get_hstring(ctx, -1);
63792 DUK_ASSERT(h_funcname != NULL);
63793
63794 DUK_DDD(DUK_DDDPRINT("register function declaration %!O in pass 1, fnum %ld",
63795 (duk_heaphdr *) h_funcname, (long) fnum));
63796 n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
63797 duk_push_hstring(ctx, h_funcname);
63798 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
63799 duk_push_int(ctx, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
63800 duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
63801
63802 duk_pop_n(ctx, 2);
63803 }
63804
63805 /* no statement value (unlike function expression) */
63806 stmt_flags = 0;
63807 break;
63808 } else {
63810 }
63811 break;
63812 }
63813 case DUK_TOK_LCURLY: {
63814 DUK_DDD(DUK_DDDPRINT("block statement"));
63815 duk__advance(comp_ctx);
63816 duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63817 /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63818 if (label_id >= 0) {
63819 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
63820 }
63821 stmt_flags = 0;
63822 break;
63823 }
63824 case DUK_TOK_CONST: {
63825 DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
63826 duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
63827 stmt_flags = DUK__HAS_TERM;
63828 break;
63829 }
63830 case DUK_TOK_VAR: {
63831 DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
63832 duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
63833 stmt_flags = DUK__HAS_TERM;
63834 break;
63835 }
63836 case DUK_TOK_SEMICOLON: {
63837 /* empty statement with an explicit semicolon */
63838 DUK_DDD(DUK_DDDPRINT("empty statement"));
63839 stmt_flags = DUK__HAS_TERM;
63840 break;
63841 }
63842 case DUK_TOK_IF: {
63843 DUK_DDD(DUK_DDDPRINT("if statement"));
63844 duk__parse_if_stmt(comp_ctx, res);
63845 if (label_id >= 0) {
63846 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
63847 }
63848 stmt_flags = 0;
63849 break;
63850 }
63851 case DUK_TOK_DO: {
63852 /*
63853 * Do-while statement is mostly trivial, but there is special
63854 * handling for automatic semicolon handling (triggered by the
63855 * DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
63856 *
63857 * https://bugs.ecmascript.org/show_bug.cgi?id=8
63858 *
63859 * See doc/compiler.rst for details.
63860 */
63861 DUK_DDD(DUK_DDDPRINT("do statement"));
63862 DUK_ASSERT(label_id >= 0);
63863 duk__update_label_flags(comp_ctx,
63864 label_id,
63866 duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
63867 stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS; /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
63868 break;
63869 }
63870 case DUK_TOK_WHILE: {
63871 DUK_DDD(DUK_DDDPRINT("while statement"));
63872 DUK_ASSERT(label_id >= 0);
63873 duk__update_label_flags(comp_ctx,
63874 label_id,
63876 duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
63877 stmt_flags = 0;
63878 break;
63879 }
63880 case DUK_TOK_FOR: {
63881 /*
63882 * For/for-in statement is complicated to parse because
63883 * determining the statement type (three-part for vs. a
63884 * for-in) requires potential backtracking.
63885 *
63886 * See the helper for the messy stuff.
63887 */
63888 DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
63889 DUK_ASSERT(label_id >= 0);
63890 duk__update_label_flags(comp_ctx,
63891 label_id,
63893 duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
63894 stmt_flags = 0;
63895 break;
63896 }
63897 case DUK_TOK_CONTINUE:
63898 case DUK_TOK_BREAK: {
63899 DUK_DDD(DUK_DDDPRINT("break/continue statement"));
63900 duk__parse_break_or_continue_stmt(comp_ctx, res);
63901 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
63902 break;
63903 }
63904 case DUK_TOK_RETURN: {
63905 DUK_DDD(DUK_DDDPRINT("return statement"));
63906 duk__parse_return_stmt(comp_ctx, res);
63907 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
63908 break;
63909 }
63910 case DUK_TOK_WITH: {
63911 DUK_DDD(DUK_DDDPRINT("with statement"));
63912 comp_ctx->curr_func.with_depth++;
63913 duk__parse_with_stmt(comp_ctx, res);
63914 if (label_id >= 0) {
63915 duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
63916 }
63917 comp_ctx->curr_func.with_depth--;
63918 stmt_flags = 0;
63919 break;
63920 }
63921 case DUK_TOK_SWITCH: {
63922 /*
63923 * The switch statement is pretty messy to compile.
63924 * See the helper for details.
63925 */
63926 DUK_DDD(DUK_DDDPRINT("switch statement"));
63927 DUK_ASSERT(label_id >= 0);
63928 duk__update_label_flags(comp_ctx,
63929 label_id,
63930 DUK_LABEL_FLAG_ALLOW_BREAK); /* don't allow continue */
63931 duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
63932 stmt_flags = 0;
63933 break;
63934 }
63935 case DUK_TOK_THROW: {
63936 DUK_DDD(DUK_DDDPRINT("throw statement"));
63937 duk__parse_throw_stmt(comp_ctx, res);
63938 stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
63939 break;
63940 }
63941 case DUK_TOK_TRY: {
63942 DUK_DDD(DUK_DDDPRINT("try statement"));
63943 duk__parse_try_stmt(comp_ctx, res);
63944 stmt_flags = 0;
63945 break;
63946 }
63947 case DUK_TOK_DEBUGGER: {
63948 duk__advance(comp_ctx);
63949#if defined(DUK_USE_DEBUGGER_SUPPORT)
63950 DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
63952#else
63953 DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
63954#endif
63955 stmt_flags = DUK__HAS_TERM;
63956 break;
63957 }
63958 default: {
63959 /*
63960 * Else, must be one of:
63961 * - ExpressionStatement, possibly a directive (String)
63962 * - LabelledStatement (Identifier followed by ':')
63963 *
63964 * Expressions beginning with 'function' keyword are covered by a case
63965 * above (such expressions are not allowed in standard E5 anyway).
63966 * Also expressions starting with '{' are interpreted as block
63967 * statements. See E5 Section 12.4.
63968 *
63969 * Directive detection is tricky; see E5 Section 14.1 on directive
63970 * prologue. A directive is an expression statement with a single
63971 * string literal and an explicit or automatic semicolon. Escape
63972 * characters are significant and no parens etc are allowed:
63973 *
63974 * 'use strict'; // valid 'use strict' directive
63975 * 'use\u0020strict'; // valid directive, not a 'use strict' directive
63976 * ('use strict'); // not a valid directive
63977 *
63978 * The expression is determined to consist of a single string literal
63979 * based on duk__expr_nud() and duk__expr_led() call counts. The string literal
63980 * of a 'use strict' directive is determined to lack any escapes based
63981 * num_escapes count from the lexer. Note that other directives may be
63982 * allowed to contain escapes, so a directive with escapes does not
63983 * terminate a directive prologue.
63984 *
63985 * We rely on the fact that the expression parser will not emit any
63986 * code for a single token expression. However, it will generate an
63987 * intermediate value which we will then successfully ignore.
63988 *
63989 * A similar approach is used for labels.
63990 */
63991
63992 duk_bool_t single_token;
63993
63994 DUK_DDD(DUK_DDDPRINT("expression statement"));
63995 duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63996
63997 single_token = (comp_ctx->curr_func.nud_count == 1 && /* one token */
63998 comp_ctx->curr_func.led_count == 0); /* no operators */
63999
64000 if (single_token &&
64001 comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
64002 comp_ctx->curr_token.t == DUK_TOK_COLON) {
64003 /*
64004 * Detected label
64005 */
64006
64007 duk_hstring *h_lab;
64008
64009 /* expected ival */
64010 DUK_ASSERT(res->t == DUK_IVAL_VAR);
64011 DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
64013 h_lab = comp_ctx->prev_token.str1;
64014 DUK_ASSERT(h_lab != NULL);
64015
64016 DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
64017 (duk_heaphdr *) h_lab));
64018
64019 duk__advance(comp_ctx); /* eat colon */
64020
64021 label_id = duk__stmt_label_site(comp_ctx, label_id);
64022
64023 duk__add_label(comp_ctx,
64024 h_lab,
64025 pc_at_entry /*pc_label*/,
64026 label_id);
64027
64028 /* a statement following a label cannot be a source element
64029 * (a function declaration).
64030 */
64031 allow_source_elem = 0;
64032
64033 DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
64034 goto retry_parse;
64035 }
64036
64037 stmt_flags = 0;
64038
64039 if (dir_prol_at_entry && /* still in prologue */
64040 single_token && /* single string token */
64041 comp_ctx->prev_token.t == DUK_TOK_STRING) {
64042 /*
64043 * Detected a directive
64044 */
64045 duk_hstring *h_dir;
64046
64047 /* expected ival */
64048 DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
64049 DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
64051 h_dir = comp_ctx->prev_token.str1;
64052 DUK_ASSERT(h_dir != NULL);
64053
64054 DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
64055
64056 stmt_flags |= DUK__STILL_PROLOGUE;
64057
64058 /* Note: escaped characters differentiate directives */
64059
64060 if (comp_ctx->prev_token.num_escapes > 0) {
64061 DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
64062 "but we ignore such directives"));
64063 } else {
64064 /*
64065 * The length comparisons are present to handle
64066 * strings like "use strict\u0000foo" as required.
64067 */
64068
64069 if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
64070 DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict", 10) == 0) {
64071#if defined(DUK_USE_STRICT_DECL)
64072 DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
64073 (long) comp_ctx->curr_func.is_strict, (long) 1));
64074 comp_ctx->curr_func.is_strict = 1;
64075#else
64076 DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
64077#endif
64078 } else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
64079 DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail", 14) == 0) {
64080 DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
64081 (long) comp_ctx->curr_func.is_notail, (long) 1));
64082 comp_ctx->curr_func.is_notail = 1;
64083 } else {
64084 DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
64085 "directive prologue", (duk_hobject *) h_dir));
64086 }
64087 }
64088 } else {
64089 DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
64090 "prologue terminated if still active"));
64091 }
64092
64093 stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
64094 }
64095 } /* end switch (tok) */
64096
64097 /*
64098 * Statement value handling.
64099 *
64100 * Global code and eval code has an implicit return value
64101 * which comes from the last statement with a value
64102 * (technically a non-"empty" continuation, which is
64103 * different from an empty statement).
64104 *
64105 * Since we don't know whether a later statement will
64106 * override the value of the current statement, we need
64107 * to coerce the statement value to a register allocated
64108 * for implicit return values. In other cases we need
64109 * to coerce the statement value to a plain value to get
64110 * any side effects out (consider e.g. "foo.bar;").
64111 */
64112
64113 /* XXX: what about statements which leave a half-cooked value in 'res'
64114 * but have no stmt value? Any such statements?
64115 */
64116
64117 if (stmt_flags & DUK__HAS_VAL) {
64118 duk_reg_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
64119 if (reg_stmt_value >= 0) {
64120 duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
64121 } else {
64122 duk__ivalue_toplain_ignore(comp_ctx, res);
64123 }
64124 } else {
64125 ;
64126 }
64127
64128 /*
64129 * Statement terminator check, including automatic semicolon
64130 * handling. After this step, 'curr_tok' should be the first
64131 * token after a possible statement terminator.
64132 */
64133
64134 if (stmt_flags & DUK__HAS_TERM) {
64135 if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
64136 DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
64137 duk__advance(comp_ctx);
64138 } else {
64139 if (comp_ctx->curr_token.allow_auto_semi) {
64140 DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
64141 } else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
64142 /* XXX: make this lenience dependent on flags or strictness? */
64143 DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
64144 "even though no lineterm present before next token)"));
64145 } else {
64147 }
64148 }
64149 } else {
64150 DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
64151 }
64152
64153 /*
64154 * Directive prologue tracking.
64155 */
64156
64157 if (stmt_flags & DUK__STILL_PROLOGUE) {
64158 DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
64159 comp_ctx->curr_func.in_directive_prologue = 1;
64160 }
64161
64162 /*
64163 * Cleanups (all statement parsing flows through here).
64164 *
64165 * Pop label site and reset labels. Reset 'next temp' to value at
64166 * entry to reuse temps.
64167 */
64168
64169 if (label_id >= 0) {
64170 duk__emit_extraop_bc(comp_ctx,
64172 (duk_regconst_t) label_id);
64173 }
64174
64175 DUK__SETTEMP(comp_ctx, temp_at_entry);
64176
64177 duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
64178
64179 /* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
64180
64181 DUK__RECURSION_DECREASE(comp_ctx, thr);
64183
64184#undef DUK__HAS_VAL
64185#undef DUK__HAS_TERM
64186#undef DUK__ALLOW_AUTO_SEMI_ALWAYS
64187
64188/*
64189 * Parse a statement list.
64190 *
64191 * Handles automatic semicolon insertion and implicit return value.
64192 *
64193 * Upon entry, 'curr_tok' should contain the first token of the first
64194 * statement (parsed in the "allow regexp literal" mode). Upon exit,
64195 * 'curr_tok' contains the token following the statement list terminator
64196 * (EOF or closing brace).
64197 */
64198
64199DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
64200 duk_hthread *thr = comp_ctx->thr;
64201 duk_context *ctx = (duk_context *) thr;
64202 duk_ivalue res_alloc;
64203 duk_ivalue *res = &res_alloc;
64204
64205 /* Setup state. Initial ivalue is 'undefined'. */
64206
64208
64209 /* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
64210 * intermediate values suffice for parsing of each function. Nesting is needed
64211 * for nested functions (which may occur inside expressions).
64212 */
64213
64214 DUK_MEMZERO(&res_alloc, sizeof(res_alloc));
64215 res->t = DUK_IVAL_PLAIN;
64216 res->x1.t = DUK_ISPEC_VALUE;
64217 res->x1.valstack_idx = duk_get_top(ctx);
64218 res->x2.valstack_idx = res->x1.valstack_idx + 1;
64219 duk_push_undefined(ctx);
64220 duk_push_undefined(ctx);
64221
64222 /* Parse statements until a closing token (EOF or '}') is found. */
64223
64224 for (;;) {
64225 /* Check whether statement list ends. */
64226
64227 if (expect_eof) {
64228 if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
64229 break;
64230 }
64231 } else {
64232 if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
64233 break;
64234 }
64235 }
64236
64237 /* Check statement type based on the first token type.
64238 *
64239 * Note: expression parsing helpers expect 'curr_tok' to
64240 * contain the first token of the expression upon entry.
64241 */
64242
64243 DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
64244
64245 duk__parse_stmt(comp_ctx, res, allow_source_elem);
64246 }
64247
64248 duk__advance(comp_ctx);
64249
64250 /* Tear down state. */
64251
64252 duk_pop_2(ctx);
64253}
64254
64255/*
64256 * Declaration binding instantiation conceptually happens when calling a
64257 * function; for us it essentially means that function prologue. The
64258 * conceptual process is described in E5 Section 10.5.
64259 *
64260 * We need to keep track of all encountered identifiers to (1) create an
64261 * identifier-to-register map ("varmap"); and (2) detect duplicate
64262 * declarations. Identifiers which are not bound to registers still need
64263 * to be tracked for detecting duplicates. Currently such identifiers
64264 * are put into the varmap with a 'null' value, which is later cleaned up.
64265 *
64266 * To support functions with a large number of variable and function
64267 * declarations, registers are not allocated beyond a certain limit;
64268 * after that limit, variables and functions need slow path access.
64269 * Arguments are currently always register bound, which imposes a hard
64270 * (and relatively small) argument count limit.
64271 *
64272 * Some bindings in E5 are not configurable (= deletable) and almost all
64273 * are mutable (writable). Exceptions are:
64274 *
64275 * - The 'arguments' binding, established only if no shadowing argument
64276 * or function declaration exists. We handle 'arguments' creation
64277 * and binding through an explicit slow path environment record.
64278 *
64279 * - The "name" binding for a named function expression. This is also
64280 * handled through an explicit slow path environment record.
64281 */
64282
64283/* XXX: add support for variables to not be register bound always, to
64284 * handle cases with a very large number of variables?
64285 */
64286
64288 duk_hthread *thr = comp_ctx->thr;
64289 duk_context *ctx = (duk_context *) thr;
64290 duk_hstring *h_name;
64291 duk_bool_t configurable_bindings;
64292 duk_uarridx_t num_args;
64293 duk_uarridx_t num_decls;
64294 duk_regconst_t rc_name;
64295 duk_small_uint_t declvar_flags;
64296 duk_uarridx_t i;
64297#ifdef DUK_USE_ASSERTIONS
64298 duk_idx_t entry_top;
64299#endif
64300
64301#ifdef DUK_USE_ASSERTIONS
64302 entry_top = duk_get_top(ctx);
64303#endif
64304
64305 /*
64306 * Preliminaries
64307 */
64308
64309 configurable_bindings = comp_ctx->curr_func.is_eval;
64310 DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
64311
64312 /* varmap is already in comp_ctx->curr_func.varmap_idx */
64313
64314 /*
64315 * Function formal arguments, always bound to registers
64316 * (there's no support for shuffling them now).
64317 */
64318
64319 num_args = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
64320 DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
64321 /* XXX: check num_args */
64322
64323 for (i = 0; i < num_args; i++) {
64324 duk_get_prop_index(ctx, comp_ctx->curr_func.argnames_idx, i);
64325 h_name = duk_get_hstring(ctx, -1);
64326 DUK_ASSERT(h_name != NULL);
64327
64328 if (comp_ctx->curr_func.is_strict) {
64329 if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
64330 DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
64331 goto error_argname;
64332 }
64333 duk_dup_top(ctx);
64334 if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64335 DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
64336 goto error_argname;
64337 }
64338
64339 /* Ensure argument name is not a reserved word in current
64340 * (final) strictness. Formal argument parsing may not
64341 * catch reserved names if strictness changes during
64342 * parsing.
64343 *
64344 * We only need to do this in strict mode because non-strict
64345 * keyword are always detected in formal argument parsing.
64346 */
64347
64349 goto error_argname;
64350 }
64351 }
64352
64353 /* overwrite any previous binding of the same name; the effect is
64354 * that last argument of a certain name wins.
64355 */
64356
64357 /* only functions can have arguments */
64358 DUK_ASSERT(comp_ctx->curr_func.is_function);
64359 duk_push_uarridx(ctx, i); /* -> [ ... name index ] */
64360 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
64361
64362 /* no code needs to be emitted, the regs already have values */
64363 }
64364
64365 /* use temp_next for tracking register allocations */
64366 DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_reg_t) num_args);
64367
64368 /*
64369 * After arguments, allocate special registers (like shuffling temps)
64370 */
64371
64372 if (out_stmt_value_reg) {
64373 *out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
64374 }
64375 if (comp_ctx->curr_func.needs_shuffle) {
64376 duk_reg_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
64377 comp_ctx->curr_func.shuffle1 = shuffle_base;
64378 comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
64379 comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
64380 DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
64381 (long) comp_ctx->curr_func.shuffle1,
64382 (long) comp_ctx->curr_func.shuffle2,
64383 (long) comp_ctx->curr_func.shuffle3));
64384 }
64385 if (comp_ctx->curr_func.temp_next > 0x100) {
64386 DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
64387 goto error_outofregs;
64388 }
64389
64390 /*
64391 * Function declarations
64392 */
64393
64394 num_decls = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
64395 DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
64396 (long) num_decls,
64397 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.decls_idx)));
64398 for (i = 0; i < num_decls; i += 2) {
64399 duk_int_t decl_type;
64400 duk_int_t fnum;
64401
64402 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
64403 decl_type = duk_to_int(ctx, -1);
64404 fnum = decl_type >> 8; /* XXX: macros */
64405 decl_type = decl_type & 0xff;
64406 duk_pop(ctx);
64407
64408 if (decl_type != DUK_DECL_TYPE_FUNC) {
64409 continue;
64410 }
64411
64412 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
64413
64414 /* XXX: spilling */
64415 if (comp_ctx->curr_func.is_function) {
64416 duk_reg_t reg_bind;
64417 duk_dup_top(ctx);
64418 if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64419 /* shadowed; update value */
64420 duk_dup_top(ctx);
64421 duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
64422 reg_bind = duk_to_int(ctx, -1); /* [ ... name reg_bind ] */
64423 duk__emit_a_bc(comp_ctx,
64425 (duk_regconst_t) reg_bind,
64426 (duk_regconst_t) fnum);
64427 } else {
64428 /* function: always register bound */
64429 reg_bind = DUK__ALLOCTEMP(comp_ctx);
64430 duk__emit_a_bc(comp_ctx,
64432 (duk_regconst_t) reg_bind,
64433 (duk_regconst_t) fnum);
64434 duk_push_int(ctx, (duk_int_t) reg_bind);
64435 }
64436 } else {
64437 /* Function declaration for global/eval code is emitted even
64438 * for duplicates, because of E5 Section 10.5, step 5.e of
64439 * E5.1 (special behavior for variable bound to global object).
64440 *
64441 * DECLVAR will not re-declare a variable as such, but will
64442 * update the binding value.
64443 */
64444
64445 duk_reg_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
64446 duk_dup_top(ctx);
64447 rc_name = duk__getconst(comp_ctx);
64448 duk_push_null(ctx);
64449
64450 duk__emit_a_bc(comp_ctx,
64452 (duk_regconst_t) reg_temp,
64453 (duk_regconst_t) fnum);
64454
64455 declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
64458
64459 if (configurable_bindings) {
64460 declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
64461 }
64462
64463 duk__emit_a_b_c(comp_ctx,
64465 (duk_regconst_t) declvar_flags /*flags*/,
64466 rc_name /*name*/,
64467 (duk_regconst_t) reg_temp /*value*/);
64468
64469 DUK__SETTEMP(comp_ctx, reg_temp); /* forget temp */
64470 }
64471
64472 DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
64473 (duk_tval *) duk_get_tval(ctx, -2),
64474 (duk_tval *) duk_get_tval(ctx, -1)));
64475
64476 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
64477 }
64478
64479 /*
64480 * 'arguments' binding is special; if a shadowing argument or
64481 * function declaration exists, an arguments object will
64482 * definitely not be needed, regardless of whether the identifier
64483 * 'arguments' is referenced inside the function body.
64484 */
64485
64487 DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
64488 "-> arguments object creation can be skipped"));
64489 comp_ctx->curr_func.is_arguments_shadowed = 1;
64490 }
64491
64492 /*
64493 * Variable declarations.
64494 *
64495 * Unlike function declarations, variable declaration values don't get
64496 * assigned on entry. If a binding of the same name already exists, just
64497 * ignore it silently.
64498 */
64499
64500 for (i = 0; i < num_decls; i += 2) {
64501 duk_int_t decl_type;
64502
64503 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
64504 decl_type = duk_to_int(ctx, -1);
64505 decl_type = decl_type & 0xff;
64506 duk_pop(ctx);
64507
64508 if (decl_type != DUK_DECL_TYPE_VAR) {
64509 continue;
64510 }
64511
64512 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
64513
64514 if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64515 /* shadowed, ignore */
64516 } else {
64517 duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
64518 h_name = duk_get_hstring(ctx, -1);
64519 DUK_ASSERT(h_name != NULL);
64520
64521 if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
64522 !comp_ctx->curr_func.is_arguments_shadowed) {
64523 /* E5 Section steps 7-8 */
64524 DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
64525 "but appears as a variable declaration -> treat as "
64526 "a no-op for variable declaration purposes"));
64527 duk_pop(ctx);
64528 continue;
64529 }
64530
64531 /* XXX: spilling */
64532 if (comp_ctx->curr_func.is_function) {
64533 duk_reg_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
64534 /* no need to init reg, it will be undefined on entry */
64535 duk_push_int(ctx, (duk_int_t) reg_bind);
64536 } else {
64537 duk_dup_top(ctx);
64538 rc_name = duk__getconst(comp_ctx);
64539 duk_push_null(ctx);
64540
64541 declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
64544 if (configurable_bindings) {
64545 declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
64546 }
64547
64548 duk__emit_a_b_c(comp_ctx,
64550 (duk_regconst_t) declvar_flags /*flags*/,
64551 rc_name /*name*/,
64552 (duk_regconst_t) 0 /*value*/);
64553 }
64554
64555 duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
64556 }
64557 }
64558
64559 /*
64560 * Wrap up
64561 */
64562
64563 DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
64564 (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx),
64565 (long) comp_ctx->curr_func.is_arguments_shadowed));
64566
64567 DUK_ASSERT_TOP(ctx, entry_top);
64568 return;
64569
64570 error_outofregs:
64573 return;
64574
64575 error_argname:
64578 return;
64579}
64580
64581/*
64582 * Parse a function-body-like expression (FunctionBody or Program
64583 * in E5 grammar) using a two-pass parse. The productions appear
64584 * in the following contexts:
64585 *
64586 * - function expression
64587 * - function statement
64588 * - function declaration
64589 * - getter in object literal
64590 * - setter in object literal
64591 * - global code
64592 * - eval code
64593 * - Function constructor body
64594 *
64595 * This function only parses the statement list of the body; the argument
64596 * list and possible function name must be initialized by the caller.
64597 * For instance, for Function constructor, the argument names are originally
64598 * on the value stack. The parsing of statements ends either at an EOF or
64599 * a closing brace; this is controlled by an input flag.
64600 *
64601 * Note that there are many differences affecting parsing and even code
64602 * generation:
64603 *
64604 * - Global and eval code have an implicit return value generated
64605 * by the last statement; function code does not
64606 *
64607 * - Global code, eval code, and Function constructor body end in
64608 * an EOF, other bodies in a closing brace ('}')
64609 *
64610 * Upon entry, 'curr_tok' is ignored and the function will pull in the
64611 * first token on its own. Upon exit, 'curr_tok' is the terminating
64612 * token (EOF or closing brace).
64613 */
64614
64615DUK_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) {
64616 duk_compiler_func *func;
64617 duk_hthread *thr;
64618 duk_context *ctx;
64619 duk_reg_t reg_stmt_value = -1;
64620 duk_lexer_point lex_pt;
64621 duk_reg_t temp_first;
64622 duk_small_int_t compile_round = 1;
64623
64624 DUK_ASSERT(comp_ctx != NULL);
64625
64626 thr = comp_ctx->thr;
64627 ctx = (duk_context *) thr;
64628 DUK_ASSERT(thr != NULL);
64629
64630 func = &comp_ctx->curr_func;
64631 DUK_ASSERT(func != NULL);
64632
64633 DUK__RECURSION_INCREASE(comp_ctx, thr);
64634
64636
64637 /*
64638 * Store lexer position for a later rewind
64639 */
64640
64641 DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
64642
64643 /*
64644 * Program code (global and eval code) has an implicit return value
64645 * from the last statement value (e.g. eval("1; 2+3;") returns 3).
64646 * This is not the case with functions. If implicit statement return
64647 * value is requested, all statements are coerced to a register
64648 * allocated here, and used in the implicit return statement below.
64649 */
64650
64651 /* XXX: this is pointless here because pass 1 is throw-away */
64652 if (implicit_return_value) {
64653 reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
64654
64655 /* If an implicit return value is needed by caller, it must be
64656 * initialized to 'undefined' because we don't know whether any
64657 * non-empty (where "empty" is a continuation type, and different
64658 * from an empty statement) statements will be executed.
64659 *
64660 * However, since 1st pass is a throwaway one, no need to emit
64661 * it here.
64662 */
64663#if 0
64664 duk__emit_extraop_bc(comp_ctx,
64666 0);
64667#endif
64668 }
64669
64670 /*
64671 * First pass.
64672 *
64673 * Gather variable/function declarations needed for second pass.
64674 * Code generated is dummy and discarded.
64675 */
64676
64677 func->in_directive_prologue = 1;
64678 func->in_scanning = 1;
64679 func->may_direct_eval = 0;
64680 func->id_access_arguments = 0;
64681 func->id_access_slow = 0;
64682 func->reg_stmt_value = reg_stmt_value;
64683#if defined(DUK_USE_DEBUGGER_SUPPORT)
64684 func->min_line = DUK_INT_MAX;
64685 func->max_line = 0;
64686#endif
64687
64688 /* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
64689 if (expect_token >= 0) {
64690 /* Eating a left curly; regexp mode is allowed by left curly
64691 * based on duk__token_lbp[] automatically.
64692 */
64693 DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
64695 duk__advance_expect(comp_ctx, expect_token);
64696 } else {
64697 /* Need to set curr_token.t because lexing regexp mode depends on current
64698 * token type. Zero value causes "allow regexp" mode.
64699 */
64700 comp_ctx->curr_token.t = 0;
64701 duk__advance(comp_ctx);
64702 }
64703
64704 DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
64705 duk__parse_stmts(comp_ctx,
64706 1, /* allow source elements */
64707 expect_eof); /* expect EOF instead of } */
64708 DUK_DDD(DUK_DDDPRINT("end 1st pass"));
64709
64710 /*
64711 * Second (and possibly third) pass.
64712 *
64713 * Generate actual code. In most cases the need for shuffle
64714 * registers is detected during pass 1, but in some corner cases
64715 * we'll only detect it during pass 2 and a third pass is then
64716 * needed (see GH-115).
64717 */
64718
64719 for (;;) {
64720 duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
64721 compile_round++;
64722
64723 /*
64724 * Rewind lexer.
64725 *
64726 * duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
64727 * literal" mode with current strictness.
64728 *
64729 * curr_token line number info should be initialized for pass 2 before
64730 * generating prologue, to ensure prologue bytecode gets nice line numbers.
64731 */
64732
64733 DUK_DDD(DUK_DDDPRINT("rewind lexer"));
64734 DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
64735 comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
64736 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
64737 duk__advance(comp_ctx);
64738
64739 /*
64740 * Reset function state and perform register allocation, which creates
64741 * 'varmap' for second pass. Function prologue for variable declarations,
64742 * binding value initializations etc is emitted as a by-product.
64743 *
64744 * Strict mode restrictions for duplicate and invalid argument
64745 * names are checked here now that we know whether the function
64746 * is actually strict. See: test-dev-strict-mode-boundary.js.
64747 *
64748 * Inner functions are compiled during pass 1 and are not reset.
64749 */
64750
64751 duk__reset_func_for_pass2(comp_ctx);
64752 func->in_directive_prologue = 1;
64753 func->in_scanning = 0;
64754
64755 /* must be able to emit code, alloc consts, etc. */
64756
64758 (implicit_return_value ? &reg_stmt_value : NULL));
64759 func->reg_stmt_value = reg_stmt_value;
64760
64761 temp_first = DUK__GETTEMP(comp_ctx);
64762
64763 func->temp_first = temp_first;
64764 func->temp_next = temp_first;
64765 func->stmt_next = 0;
64766 func->label_next = 0;
64767
64768 /* XXX: init or assert catch depth etc -- all values */
64769 func->id_access_arguments = 0;
64770 func->id_access_slow = 0;
64771
64772 /*
64773 * Check function name validity now that we know strictness.
64774 * This only applies to function declarations and expressions,
64775 * not setter/getter name.
64776 *
64777 * See: test-dev-strict-mode-boundary.js
64778 */
64779
64780 if (func->is_function && !func->is_setget && func->h_name != NULL) {
64781 if (func->is_strict) {
64782 if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
64783 DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
64784 goto error_funcname;
64785 }
64787 DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
64788 goto error_funcname;
64789 }
64790 } else {
64793 DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
64794 goto error_funcname;
64795 }
64796 }
64797 }
64798
64799 /*
64800 * Second pass parsing.
64801 */
64802
64803 if (implicit_return_value) {
64804 /* Default implicit return value. */
64805 duk__emit_extraop_bc(comp_ctx,
64807 0);
64808 }
64809
64810 DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
64811 duk__parse_stmts(comp_ctx,
64812 1, /* allow source elements */
64813 expect_eof); /* expect EOF instead of } */
64814 DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
64815
64817
64818 if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
64819 /* Shuffle decision not changed. */
64820 break;
64821 }
64822 if (compile_round >= 3) {
64823 /* Should never happen but avoid infinite loop just in case. */
64824 DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
64826 }
64827 DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
64828 }
64829
64830 /*
64831 * Emit a final RETURN.
64832 *
64833 * It would be nice to avoid emitting an unnecessary "return" opcode
64834 * if the current PC is not reachable. However, this cannot be reliably
64835 * detected; even if the previous instruction is an unconditional jump,
64836 * there may be a previous jump which jumps to current PC (which is the
64837 * case for iteration and conditional statements, for instance).
64838 */
64839
64840 /* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
64841 * we could avoid the last RETURN if we could ensure there is no way to get here
64842 * (directly or via a jump)
64843 */
64844
64845 DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
64846 if (reg_stmt_value >= 0) {
64847 duk__emit_a_b(comp_ctx,
64850 (duk_regconst_t) reg_stmt_value /*reg*/);
64851 } else {
64852 duk__emit_a_b(comp_ctx,
64854 (duk_regconst_t) 0 /*flags*/,
64855 (duk_regconst_t) 0 /*reg(ignored)*/);
64856 }
64857
64858 /*
64859 * Peephole optimize JUMP chains.
64860 */
64861
64863
64864 /*
64865 * comp_ctx->curr_func is now ready to be converted into an actual
64866 * function template.
64867 */
64868
64869 DUK__RECURSION_DECREASE(comp_ctx, thr);
64870 return;
64871
64872 error_funcname:
64874}
64875
64876/*
64877 * Parse a function-like expression:
64878 *
64879 * - function expression
64880 * - function declaration
64881 * - function statement (non-standard)
64882 * - setter/getter
64883 *
64884 * Adds the function to comp_ctx->curr_func function table and returns the
64885 * function number.
64886 *
64887 * On entry, curr_token points to:
64888 *
64889 * - the token after 'function' for function expression/declaration/statement
64890 * - the token after 'set' or 'get' for setter/getter
64891 */
64892
64893/* Parse formals. */
64895 duk_hthread *thr = comp_ctx->thr;
64896 duk_context *ctx = (duk_context *) thr;
64897 duk_bool_t first = 1;
64898 duk_uarridx_t n;
64899
64900 for (;;) {
64901 if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
64902 break;
64903 }
64904
64905 if (first) {
64906 /* no comma */
64907 first = 0;
64908 } else {
64910 }
64911
64912 /* Note: when parsing a formal list in non-strict context, e.g.
64913 * "implements" is parsed as an identifier. When the function is
64914 * later detected to be strict, the argument list must be rechecked
64915 * against a larger set of reserved words (that of strict mode).
64916 * This is handled by duk__parse_func_body(). Here we recognize
64917 * whatever tokens are considered reserved in current strictness
64918 * (which is not always enough).
64919 */
64920
64921 if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
64922 DUK_ERROR_SYNTAX(thr, "expected identifier");
64923 }
64926 DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
64927 (duk_heaphdr *) comp_ctx->curr_token.str1));
64928
64929 /* XXX: append primitive */
64930 duk_push_hstring(ctx, comp_ctx->curr_token.str1);
64931 n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
64932 duk_put_prop_index(ctx, comp_ctx->curr_func.argnames_idx, n);
64933
64934 duk__advance(comp_ctx); /* eat identifier */
64935 }
64936}
64937
64938/* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
64939 * correctly set up. Assumes that curr_token is just after 'function' (or
64940 * 'set'/'get' etc).
64941 */
64942DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
64943 duk_hthread *thr = comp_ctx->thr;
64944 duk_context *ctx = (duk_context *) thr;
64945
64946 DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
64947 DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
64948 DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
64949 DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
64950 DUK_ASSERT(comp_ctx->curr_func.is_setget == is_setget);
64951 DUK_ASSERT(comp_ctx->curr_func.is_decl == is_decl);
64952
64954
64955 /*
64956 * Function name (if any)
64957 *
64958 * We don't check for prohibited names here, because we don't
64959 * yet know whether the function will be strict. Function body
64960 * parsing handles this retroactively.
64961 *
64962 * For function expressions and declarations function name must
64963 * be an Identifer (excludes reserved words). For setter/getter
64964 * it is a PropertyName which allows reserved words and also
64965 * strings and numbers (e.g. "{ get 1() { ... } }").
64966 */
64967
64968 if (is_setget) {
64969 /* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
64970 if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER ||
64971 comp_ctx->curr_token.t == DUK_TOK_STRING) {
64972 duk_push_hstring(ctx, comp_ctx->curr_token.str1); /* keep in valstack */
64973 } else if (comp_ctx->curr_token.t == DUK_TOK_NUMBER) {
64974 duk_push_number(ctx, comp_ctx->curr_token.num);
64975 duk_to_string(ctx, -1);
64976 } else {
64978 }
64979 comp_ctx->curr_func.h_name = duk_get_hstring(ctx, -1); /* borrowed reference */
64980 DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
64981 duk__advance(comp_ctx);
64982 } else {
64983 /* Function name is an Identifier (not IdentifierName), but we get
64984 * the raw name (not recognizing keywords) here and perform the name
64985 * checks only after pass 1.
64986 */
64987 if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER) {
64988 duk_push_hstring(ctx, comp_ctx->curr_token.str1); /* keep in valstack */
64989 comp_ctx->curr_func.h_name = duk_get_hstring(ctx, -1); /* borrowed reference */
64990 DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
64991 duk__advance(comp_ctx);
64992 } else {
64993 /* valstack will be unbalanced, which is OK */
64994 DUK_ASSERT(!is_setget);
64995 if (is_decl) {
64997 }
64998 }
64999 }
65000
65001 DUK_DDD(DUK_DDDPRINT("function name: %!O",
65002 (duk_heaphdr *) comp_ctx->curr_func.h_name));
65003
65004 /*
65005 * Formal argument list
65006 *
65007 * We don't check for prohibited names or for duplicate argument
65008 * names here, becase we don't yet know whether the function will
65009 * be strict. Function body parsing handles this retroactively.
65010 */
65011
65013
65014 duk__parse_func_formals(comp_ctx);
65015
65016 DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
65017 duk__advance(comp_ctx);
65018
65019 /*
65020 * Parse function body
65021 */
65022
65023 duk__parse_func_body(comp_ctx,
65024 0, /* expect_eof */
65025 0, /* implicit_return_value */
65026 DUK_TOK_LCURLY); /* expect_token */
65027
65028 /*
65029 * Convert duk_compiler_func to a function template and add it
65030 * to the parent function table.
65031 */
65032
65033 duk__convert_to_func_template(comp_ctx, is_setget /*force_no_namebind*/); /* -> [ ... func ] */
65034}
65035
65036/* Parse an inner function, adding the function template to the current function's
65037 * function table. Return a function number to be used by the outer function.
65038 *
65039 * Avoiding O(depth^2) inner function parsing is handled here. On the first pass,
65040 * compile and register the function normally into the 'funcs' array, also recording
65041 * a lexer point (offset/line) to the closing brace of the function. On the second
65042 * pass, skip the function and return the same 'fnum' as on the first pass by using
65043 * a running counter.
65044 *
65045 * An unfortunate side effect of this is that when parsing the inner function, almost
65046 * nothing is known of the outer function, i.e. the inner function's scope. We don't
65047 * need that information at the moment, but it would allow some optimizations if it
65048 * were used.
65049 */
65051 duk_hthread *thr = comp_ctx->thr;
65052 duk_context *ctx = (duk_context *) thr;
65053 duk_compiler_func old_func;
65054 duk_idx_t entry_top;
65055 duk_int_t fnum;
65056
65057 /*
65058 * On second pass, skip the function.
65059 */
65060
65061 if (!comp_ctx->curr_func.in_scanning) {
65062 duk_lexer_point lex_pt;
65063
65064 fnum = comp_ctx->curr_func.fnum_next++;
65065 duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
65066 lex_pt.offset = duk_to_int(ctx, -1);
65067 duk_pop(ctx);
65068 duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
65069 lex_pt.line = duk_to_int(ctx, -1);
65070 duk_pop(ctx);
65071
65072 DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
65073 (long) lex_pt.offset, (long) lex_pt.line));
65074
65075 DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
65076 comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
65077 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
65078 duk__advance(comp_ctx);
65080
65081 return fnum;
65082 }
65083
65084 /*
65085 * On first pass, perform actual parsing. Remember valstack top on entry
65086 * to restore it later, and switch to using a new function in comp_ctx.
65087 */
65088
65089 entry_top = duk_get_top(ctx);
65090 DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
65091 (long) entry_top, (long) comp_ctx->curr_token.start_offset));
65092
65093 DUK_MEMCPY(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
65094
65095 DUK_MEMZERO(&comp_ctx->curr_func, sizeof(duk_compiler_func));
65097 DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
65098
65099 /* inherit initial strictness from parent */
65100 comp_ctx->curr_func.is_strict = old_func.is_strict;
65101
65102 DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
65103 comp_ctx->curr_func.is_function = 1;
65104 DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
65105 DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
65106 comp_ctx->curr_func.is_setget = is_setget;
65107 comp_ctx->curr_func.is_decl = is_decl;
65108
65109 /*
65110 * Parse inner function
65111 */
65112
65113 duk__parse_func_like_raw(comp_ctx, is_decl, is_setget); /* pushes function template */
65114
65115 /* prev_token.start_offset points to the closing brace here; when skipping
65116 * we're going to reparse the closing brace to ensure semicolon insertion
65117 * etc work as expected.
65118 */
65119 DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
65120 (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
65121 DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
65122
65123 /* XXX: append primitive */
65124 DUK_ASSERT(duk_get_length(ctx, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
65125 fnum = old_func.fnum_next++;
65126
65127 if (fnum > DUK__MAX_FUNCS) {
65129 }
65130
65131 /* array writes autoincrement length */
65132 (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
65133 duk_push_size_t(ctx, comp_ctx->prev_token.start_offset);
65134 (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
65135 duk_push_int(ctx, comp_ctx->prev_token.start_line);
65136 (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
65137
65138 /*
65139 * Cleanup: restore original function, restore valstack state.
65140 */
65141
65142 DUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
65143 duk_set_top(ctx, entry_top);
65144
65145 DUK_ASSERT_TOP(ctx, entry_top);
65146
65147 return fnum;
65148}
65149
65150/*
65151 * Compile input string into an executable function template without
65152 * arguments.
65153 *
65154 * The string is parsed as the "Program" production of Ecmascript E5.
65155 * Compilation context can be either global code or eval code (see E5
65156 * Sections 14 and 15.1.2.1).
65157 *
65158 * Input stack: [ ... filename ]
65159 * Output stack: [ ... func_template ]
65160 */
65161
65162/* XXX: source code property */
65163
65165 duk_hthread *thr = (duk_hthread *) ctx;
65166 duk_hstring *h_filename;
65167 duk__compiler_stkstate *comp_stk;
65168 duk_compiler_ctx *comp_ctx;
65169 duk_lexer_point *lex_pt;
65170 duk_compiler_func *func;
65171 duk_idx_t entry_top;
65172 duk_bool_t is_strict;
65173 duk_bool_t is_eval;
65174 duk_bool_t is_funcexpr;
65175 duk_small_uint_t flags;
65176
65177 DUK_ASSERT(thr != NULL);
65178
65179 /*
65180 * Arguments check
65181 */
65182
65183 entry_top = duk_get_top(ctx);
65184 DUK_ASSERT(entry_top >= 2);
65185
65186 comp_stk = (duk__compiler_stkstate *) duk_require_pointer(ctx, -1);
65187 comp_ctx = &comp_stk->comp_ctx_alloc;
65188 lex_pt = &comp_stk->lex_pt_alloc;
65189 DUK_ASSERT(comp_ctx != NULL);
65190 DUK_ASSERT(lex_pt != NULL);
65191
65192 flags = comp_stk->flags;
65193 is_eval = (flags & DUK_JS_COMPILE_FLAG_EVAL ? 1 : 0);
65194 is_strict = (flags & DUK_JS_COMPILE_FLAG_STRICT ? 1 : 0);
65195 is_funcexpr = (flags & DUK_JS_COMPILE_FLAG_FUNCEXPR ? 1 : 0);
65196
65197 h_filename = duk_get_hstring(ctx, -2); /* may be undefined */
65198
65199 /*
65200 * Init compiler and lexer contexts
65201 */
65202
65203 func = &comp_ctx->curr_func;
65204#ifdef DUK_USE_EXPLICIT_NULL_INIT
65205 comp_ctx->thr = NULL;
65206 comp_ctx->h_filename = NULL;
65207 comp_ctx->prev_token.str1 = NULL;
65208 comp_ctx->prev_token.str2 = NULL;
65209 comp_ctx->curr_token.str1 = NULL;
65210 comp_ctx->curr_token.str2 = NULL;
65211#endif
65212
65214
65215 duk_push_dynamic_buffer(ctx, 0); /* entry_top + 0 */
65216 duk_push_undefined(ctx); /* entry_top + 1 */
65217 duk_push_undefined(ctx); /* entry_top + 2 */
65218 duk_push_undefined(ctx); /* entry_top + 3 */
65219 duk_push_undefined(ctx); /* entry_top + 4 */
65220
65221 comp_ctx->thr = thr;
65222 comp_ctx->h_filename = h_filename;
65223 comp_ctx->tok11_idx = entry_top + 1;
65224 comp_ctx->tok12_idx = entry_top + 2;
65225 comp_ctx->tok21_idx = entry_top + 3;
65226 comp_ctx->tok22_idx = entry_top + 4;
65228
65229 /* comp_ctx->lex has been pre-initialized by caller: it has been
65230 * zeroed and input/input_length has been set.
65231 */
65232 comp_ctx->lex.thr = thr;
65233 /* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
65234 comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
65235 comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
65236 comp_ctx->lex.buf_idx = entry_top + 0;
65237 comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 0);
65238 DUK_ASSERT(comp_ctx->lex.buf != NULL);
65241
65242 lex_pt->offset = 0;
65243 lex_pt->line = 1;
65244 DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt); /* fills window */
65245 comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
65246
65247 /*
65248 * Initialize function state for a zero-argument function
65249 */
65250
65252 DUK_ASSERT(func->num_formals == 0);
65253
65254 if (is_funcexpr) {
65255 /* Name will be filled from function expression, not by caller.
65256 * This case is used by Function constructor and duk_compile()
65257 * API with the DUK_COMPILE_FUNCTION option.
65258 */
65259 DUK_ASSERT(func->h_name == NULL);
65260 } else {
65263 func->h_name = duk_get_hstring(ctx, -1);
65264 }
65265
65266 /*
65267 * Parse a function body or a function-like expression, depending
65268 * on flags.
65269 */
65270
65271 func->is_strict = is_strict;
65272 func->is_setget = 0;
65273 func->is_decl = 0;
65274
65275 if (is_funcexpr) {
65276 func->is_function = 1;
65277 func->is_eval = 0;
65278 func->is_global = 0;
65279
65280 duk__advance(comp_ctx); /* init 'curr_token' */
65282 (void) duk__parse_func_like_raw(comp_ctx,
65283 0, /* is_decl */
65284 0); /* is_setget */
65285 } else {
65286 func->is_function = 0;
65287 func->is_eval = is_eval;
65288 func->is_global = !is_eval;
65289
65290 duk__parse_func_body(comp_ctx,
65291 1, /* expect_eof */
65292 1, /* implicit_return_value */
65293 -1); /* expect_token */
65295
65296 /*
65297 * Convert duk_compiler_func to a function template
65298 */
65299
65300 duk__convert_to_func_template(comp_ctx, 0 /*force_no_namebind*/);
65301
65302 /*
65303 * Wrapping duk_safe_call() will mangle the stack, just return stack top
65304 */
65305
65306 /* [ ... filename (temps) func ] */
65307
65308 return 1;
65309}
65310
65311DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {
65312 duk_context *ctx = (duk_context *) thr;
65313 duk__compiler_stkstate comp_stk;
65314 duk_compiler_ctx *prev_ctx;
65315 duk_ret_t safe_rc;
65316
65317 /* XXX: this illustrates that a C catchpoint implemented using duk_safe_call()
65318 * is a bit heavy at the moment. The wrapper compiles to ~180 bytes on x64.
65319 * Alternatives would be nice.
65320 */
65321
65322 DUK_ASSERT(thr != NULL);
65323 DUK_ASSERT(src_buffer != NULL);
65324
65325 /* preinitialize lexer state partially */
65326 DUK_MEMZERO(&comp_stk, sizeof(comp_stk));
65327 comp_stk.flags = flags;
65329 comp_stk.comp_ctx_alloc.lex.input = src_buffer;
65330 comp_stk.comp_ctx_alloc.lex.input_length = src_length;
65331
65332 duk_push_pointer(ctx, (void *) &comp_stk);
65333
65334 /* [ ... filename &comp_stk ] */
65335
65336 prev_ctx = thr->compile_ctx;
65337 thr->compile_ctx = &comp_stk.comp_ctx_alloc; /* for duk_error_augment.c */
65338 safe_rc = duk_safe_call(ctx, duk__js_compile_raw, 2 /*nargs*/, 1 /*nret*/);
65339 thr->compile_ctx = prev_ctx; /* must restore reliably before returning */
65340
65341 if (safe_rc != DUK_EXEC_SUCCESS) {
65342 duk_throw(ctx);
65343 }
65344
65345 /* [ ... template ] */
65346}
65347#line 1 "duk_js_executor.c"
65348/*
65349 * Ecmascript bytecode executor.
65350 */
65351
65352/* include removed: duk_internal.h */
65353
65354/*
65355 * Local declarations.
65356 */
65357
65359
65360/*
65361 * Arithmetic, binary, and logical helpers.
65362 *
65363 * Note: there is no opcode for logical AND or logical OR; this is on
65364 * purpose, because the evalution order semantics for them make such
65365 * opcodes pretty pointless: short circuiting means they are most
65366 * comfortably implemented as jumps. However, a logical NOT opcode
65367 * is useful.
65368 *
65369 * Note: careful with duk_tval pointers here: they are potentially
65370 * invalidated by any DECREF and almost any API call. It's still
65371 * preferable to work without making a copy but that's not always
65372 * possible.
65373 */
65374
65376 /*
65377 * Ecmascript modulus ('%') does not match IEEE 754 "remainder"
65378 * operation (implemented by remainder() in C99) but does seem
65379 * to match ANSI C fmod().
65380 *
65381 * Compare E5 Section 11.5.3 and "man fmod".
65382 */
65383
65384 return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
65385}
65386
65388 /*
65389 * Addition operator is different from other arithmetic
65390 * operations in that it also provides string concatenation.
65391 * Hence it is implemented separately.
65392 *
65393 * There is a fast path for number addition. Other cases go
65394 * through potentially multiple coercions as described in the
65395 * E5 specification. It may be possible to reduce the number
65396 * of coercions, but this must be done carefully to preserve
65397 * the exact semantics.
65398 *
65399 * E5 Section 11.6.1.
65400 *
65401 * Custom types also have special behavior implemented here.
65402 */
65403
65404 duk_context *ctx = (duk_context *) thr;
65406
65407 DUK_ASSERT(thr != NULL);
65408 DUK_ASSERT(ctx != NULL);
65409 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65410 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
65411 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
65412 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65413
65414 /*
65415 * Fast paths
65416 */
65417
65418#if defined(DUK_USE_FASTINT)
65419 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65420 duk_int64_t v1, v2, v3;
65421 duk_int32_t v3_hi;
65422 duk_tval *tv_z;
65423
65424 /* Input values are signed 48-bit so we can detect overflow
65425 * reliably from high bits or just a comparison.
65426 */
65427
65428 v1 = DUK_TVAL_GET_FASTINT(tv_x);
65429 v2 = DUK_TVAL_GET_FASTINT(tv_y);
65430 v3 = v1 + v2;
65431 v3_hi = (duk_int32_t) (v3 >> 32);
65432 if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
65433 tv_z = thr->valstack_bottom + idx_z;
65434 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
65435 return;
65436 } else {
65437 /* overflow, fall through */
65438 ;
65439 }
65440 }
65441#endif /* DUK_USE_FASTINT */
65442
65443 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
65444 duk_tval *tv_z;
65445
65446 du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
65449
65450 tv_z = thr->valstack_bottom + idx_z;
65451 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
65452 return;
65453 }
65454
65455 /*
65456 * Slow path: potentially requires function calls for coercion
65457 */
65458
65459 duk_push_tval(ctx, tv_x);
65460 duk_push_tval(ctx, tv_y);
65461 duk_to_primitive(ctx, -2, DUK_HINT_NONE); /* side effects -> don't use tv_x, tv_y after */
65463
65464 /* As a first approximation, buffer values are coerced to strings
65465 * for addition. This means that adding two buffers currently
65466 * results in a string.
65467 */
65470 duk_to_string(ctx, -2);
65471 duk_to_string(ctx, -1);
65472 duk_concat(ctx, 2); /* [... s1 s2] -> [... s1+s2] */
65473 duk_replace(ctx, (duk_idx_t) idx_z); /* side effects */
65474 } else {
65475 duk_double_t d1, d2;
65476
65477 d1 = duk_to_number(ctx, -2);
65478 d2 = duk_to_number(ctx, -1);
65479 DUK_ASSERT(duk_is_number(ctx, -2));
65480 DUK_ASSERT(duk_is_number(ctx, -1));
65483
65484 du.d = d1 + d2;
65487
65488 duk_pop_2(ctx);
65489 duk_push_number(ctx, du.d);
65490 duk_replace(ctx, (duk_idx_t) idx_z); /* side effects */
65491 }
65492}
65493
65495 /*
65496 * Arithmetic operations other than '+' have number-only semantics
65497 * and are implemented here. The separate switch-case here means a
65498 * "double dispatch" of the arithmetic opcode, but saves code space.
65499 *
65500 * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
65501 */
65502
65503 duk_context *ctx = (duk_context *) thr;
65504 duk_tval *tv_z;
65505 duk_double_t d1, d2;
65507
65508 DUK_ASSERT(thr != NULL);
65509 DUK_ASSERT(ctx != NULL);
65510 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65511 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
65512 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
65513 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65514
65515#if defined(DUK_USE_FASTINT)
65516 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65517 duk_int64_t v1, v2, v3;
65518 duk_int32_t v3_hi;
65519
65520 v1 = DUK_TVAL_GET_FASTINT(tv_x);
65521 v2 = DUK_TVAL_GET_FASTINT(tv_y);
65522
65523 switch (opcode) {
65524 case DUK_OP_SUB: {
65525 v3 = v1 - v2;
65526 break;
65527 }
65528 case DUK_OP_MUL: {
65529 /* Must ensure result is 64-bit (no overflow); a
65530 * simple and sufficient fast path is to allow only
65531 * 32-bit inputs. Avoid zero inputs to avoid
65532 * negative zero issues (-1 * 0 = -0, for instance).
65533 */
65534 if (v1 >= -0x80000000LL && v1 <= 0x7fffffffLL && v1 != 0 &&
65535 v2 >= -0x80000000LL && v2 <= 0x7fffffffLL && v2 != 0) {
65536 v3 = v1 * v2;
65537 } else {
65538 goto skip_fastint;
65539 }
65540 break;
65541 }
65542 case DUK_OP_DIV: {
65543 /* Don't allow a zero divisor. Fast path check by
65544 * "verifying" with multiplication. Also avoid zero
65545 * dividend to avoid negative zero issues (0 / -1 = -0
65546 * for instance).
65547 */
65548 if (v1 == 0 || v2 == 0) {
65549 goto skip_fastint;
65550 }
65551 v3 = v1 / v2;
65552 if (v3 * v2 != v1) {
65553 goto skip_fastint;
65554 }
65555 break;
65556 }
65557 case DUK_OP_MOD: {
65558 /* Don't allow a zero divisor. Restrict both v1 and
65559 * v2 to positive values to avoid compiler specific
65560 * behavior.
65561 */
65562 if (v1 < 1 || v2 < 1) {
65563 goto skip_fastint;
65564 }
65565 v3 = v1 % v2;
65566 DUK_ASSERT(v3 >= 0);
65567 DUK_ASSERT(v3 < v2);
65568 DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
65569 break;
65570 }
65571 default: {
65573 goto skip_fastint;
65574 }
65575 }
65576
65577 v3_hi = (duk_int32_t) (v3 >> 32);
65578 if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
65579 tv_z = thr->valstack_bottom + idx_z;
65580 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
65581 return;
65582 }
65583 /* fall through if overflow etc */
65584 }
65585 skip_fastint:
65586#endif /* DUK_USE_FASTINT */
65587
65588 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
65589 /* fast path */
65590 d1 = DUK_TVAL_GET_NUMBER(tv_x);
65591 d2 = DUK_TVAL_GET_NUMBER(tv_y);
65592 } else {
65593 duk_push_tval(ctx, tv_x);
65594 duk_push_tval(ctx, tv_y);
65595 d1 = duk_to_number(ctx, -2); /* side effects */
65596 d2 = duk_to_number(ctx, -1);
65597 DUK_ASSERT(duk_is_number(ctx, -2));
65598 DUK_ASSERT(duk_is_number(ctx, -1));
65601 duk_pop_2(ctx);
65602 }
65603
65604 switch (opcode) {
65605 case DUK_OP_SUB: {
65606 du.d = d1 - d2;
65607 break;
65608 }
65609 case DUK_OP_MUL: {
65610 du.d = d1 * d2;
65611 break;
65612 }
65613 case DUK_OP_DIV: {
65614 du.d = d1 / d2;
65615 break;
65616 }
65617 case DUK_OP_MOD: {
65618 du.d = duk__compute_mod(d1, d2);
65619 break;
65620 }
65621 default: {
65623 du.d = DUK_DOUBLE_NAN; /* should not happen */
65624 break;
65625 }
65626 }
65627
65628 /* important to use normalized NaN with 8-byte tagged types */
65631
65632 tv_z = thr->valstack_bottom + idx_z;
65633 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
65634}
65635
65637 /*
65638 * Binary bitwise operations use different coercions (ToInt32, ToUint32)
65639 * depending on the operation. We coerce the arguments first using
65640 * ToInt32(), and then cast to an 32-bit value if necessary. Note that
65641 * such casts must be correct even if there is no native 32-bit type
65642 * (e.g., duk_int32_t and duk_uint32_t are 64-bit).
65643 *
65644 * E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
65645 */
65646
65647 duk_context *ctx = (duk_context *) thr;
65648 duk_tval *tv_z;
65649 duk_int32_t i1, i2, i3;
65650 duk_uint32_t u1, u2, u3;
65651#if defined(DUK_USE_FASTINT)
65652 duk_int64_t fi3;
65653#else
65654 duk_double_t d3;
65655#endif
65656
65657 DUK_ASSERT(thr != NULL);
65658 DUK_ASSERT(ctx != NULL);
65659 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65660 DUK_ASSERT(tv_y != NULL); /* may be reg or const */
65661 DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
65662 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65663
65664#if defined(DUK_USE_FASTINT)
65665 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65666 i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
65667 i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
65668 }
65669 else
65670#endif /* DUK_USE_FASTINT */
65671 {
65672 duk_push_tval(ctx, tv_x);
65673 duk_push_tval(ctx, tv_y);
65674 i1 = duk_to_int32(ctx, -2);
65675 i2 = duk_to_int32(ctx, -1);
65676 duk_pop_2(ctx);
65677 }
65678
65679 switch (opcode) {
65680 case DUK_OP_BAND: {
65681 i3 = i1 & i2;
65682 break;
65683 }
65684 case DUK_OP_BOR: {
65685 i3 = i1 | i2;
65686 break;
65687 }
65688 case DUK_OP_BXOR: {
65689 i3 = i1 ^ i2;
65690 break;
65691 }
65692 case DUK_OP_BASL: {
65693 /* Signed shift, named "arithmetic" (asl) because the result
65694 * is signed, e.g. 4294967295 << 1 -> -2. Note that result
65695 * must be masked.
65696 */
65697
65698 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65699 i3 = i1 << (u2 & 0x1f); /* E5 Section 11.7.1, steps 7 and 8 */
65700 i3 = i3 & ((duk_int32_t) 0xffffffffUL); /* Note: left shift, should mask */
65701 break;
65702 }
65703 case DUK_OP_BASR: {
65704 /* signed shift */
65705
65706 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65707 i3 = i1 >> (u2 & 0x1f); /* E5 Section 11.7.2, steps 7 and 8 */
65708 break;
65709 }
65710 case DUK_OP_BLSR: {
65711 /* unsigned shift */
65712
65713 u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
65714 u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65715
65716 /* special result value handling */
65717 u3 = u1 >> (u2 & 0x1f); /* E5 Section 11.7.2, steps 7 and 8 */
65718#if defined(DUK_USE_FASTINT)
65719 fi3 = (duk_int64_t) u3;
65720 goto fastint_result_set;
65721#else
65722 d3 = (duk_double_t) u3;
65723 goto result_set;
65724#endif
65725 }
65726 default: {
65728 i3 = 0; /* should not happen */
65729 break;
65730 }
65731 }
65732
65733#if defined(DUK_USE_FASTINT)
65734 /* Result is always fastint compatible. */
65735 /* XXX: Set 32-bit result (but must then handle signed and
65736 * unsigned results separately).
65737 */
65738 fi3 = (duk_int64_t) i3;
65740 fastint_result_set:
65741 tv_z = thr->valstack_bottom + idx_z;
65742 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3); /* side effects */
65743#else
65744 d3 = (duk_double_t) i3;
65745
65746 result_set:
65747 DUK_ASSERT(!DUK_ISNAN(d3)); /* 'd3' is never NaN, so no need to normalize */
65748 DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3); /* always normalized */
65749
65750 tv_z = thr->valstack_bottom + idx_z;
65751 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3); /* side effects */
65752#endif
65753}
65754
65755/* In-place unary operation. */
65757 /*
65758 * Arithmetic operations other than '+' have number-only semantics
65759 * and are implemented here. The separate switch-case here means a
65760 * "double dispatch" of the arithmetic opcode, but saves code space.
65761 *
65762 * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
65763 */
65764
65765 duk_context *ctx = (duk_context *) thr;
65766 duk_double_t d1;
65768
65769 DUK_ASSERT(thr != NULL);
65770 DUK_ASSERT(ctx != NULL);
65771 DUK_ASSERT(opcode == DUK_EXTRAOP_UNM || opcode == DUK_EXTRAOP_UNP);
65772 DUK_ASSERT(tv_x != NULL);
65773 DUK_ASSERT(idx_x >= 0);
65774
65775#if defined(DUK_USE_FASTINT)
65776 if (DUK_TVAL_IS_FASTINT(tv_x)) {
65777 duk_int64_t v1, v2;
65778
65779 v1 = DUK_TVAL_GET_FASTINT(tv_x);
65780 if (opcode == DUK_EXTRAOP_UNM) {
65781 /* The smallest fastint is no longer 48-bit when
65782 * negated. Positive zero becames negative zero
65783 * (cannot be represented) when negated.
65784 */
65785 if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
65786 v2 = -v1;
65787 DUK_TVAL_SET_FASTINT(tv_x, v2); /* no refcount changes */
65788 return;
65789 }
65790 } else {
65791 /* ToNumber() for a fastint is a no-op. */
65792 DUK_ASSERT(opcode == DUK_EXTRAOP_UNP);
65793 return;
65794 }
65795 /* fall through if overflow etc */
65796 }
65797#endif /* DUK_USE_FASTINT */
65798
65799 if (!DUK_TVAL_IS_NUMBER(tv_x)) {
65800 duk_to_number(ctx, idx_x); /* side effects, perform in-place */
65801 tv_x = DUK_GET_TVAL_POSIDX(ctx, idx_x);
65802 DUK_ASSERT(tv_x != NULL);
65804 }
65805
65806 d1 = DUK_TVAL_GET_NUMBER(tv_x);
65807 if (opcode == DUK_EXTRAOP_UNM) {
65808 du.d = -d1;
65809 } else {
65810 /* ToNumber() for a double is a no-op. */
65812 du.d = d1;
65813 }
65814 DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du); /* mandatory if du.d is a NaN */
65815
65817
65818#if defined(DUK_USE_FASTINT)
65819 /* Unary plus is used to force a fastint check, so must include
65820 * downgrade check.
65821 */
65822 DUK_TVAL_SET_NUMBER_CHKFAST(tv_x, du.d); /* no refcount changes */
65823#else
65824 DUK_TVAL_SET_NUMBER(tv_x, du.d); /* no refcount changes */
65825#endif
65826}
65827
65829 /*
65830 * E5 Section 11.4.8
65831 */
65832
65833 duk_context *ctx = (duk_context *) thr;
65834 duk_tval *tv_z;
65835 duk_int32_t i1, i2;
65836#if !defined(DUK_USE_FASTINT)
65837 duk_double_t d2;
65838#endif
65839
65840 DUK_ASSERT(thr != NULL);
65841 DUK_ASSERT(ctx != NULL);
65842 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65843 DUK_ASSERT_DISABLE(idx_z >= 0);
65844 DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65845
65846#if defined(DUK_USE_FASTINT)
65847 if (DUK_TVAL_IS_FASTINT(tv_x)) {
65848 i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
65849 }
65850 else
65851#endif /* DUK_USE_FASTINT */
65852 {
65853 duk_push_tval(ctx, tv_x);
65854 i1 = duk_to_int32(ctx, -1);
65855 duk_pop(ctx);
65856 }
65857
65858 i2 = ~i1;
65859
65860#if defined(DUK_USE_FASTINT)
65861 /* Result is always fastint compatible. */
65862 tv_z = thr->valstack_bottom + idx_z;
65863 DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv_z, i2); /* side effects */
65864#else
65865 d2 = (duk_double_t) i2;
65866
65867 DUK_ASSERT(!DUK_ISNAN(d2)); /* 'val' is never NaN, so no need to normalize */
65868 DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2); /* always normalized */
65869
65870 tv_z = thr->valstack_bottom + idx_z;
65871 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d2); /* side effects */
65872#endif
65873}
65874
65876 /*
65877 * E5 Section 11.4.9
65878 */
65879
65880 duk_bool_t res;
65881
65882 DUK_ASSERT(thr != NULL);
65883 DUK_ASSERT(tv_x != NULL); /* may be reg or const */
65884 DUK_ASSERT(tv_z != NULL); /* reg */
65885
65886 DUK_UNREF(thr); /* w/o refcounts */
65887
65888 /* ToBoolean() does not require any operations with side effects so
65889 * we can do it efficiently. For footprint it would be better to use
65890 * duk_js_toboolean() and then push+replace to the result slot.
65891 */
65892 res = duk_js_toboolean(tv_x); /* does not modify tv_x */
65893 DUK_ASSERT(res == 0 || res == 1);
65894 res ^= 1;
65895 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv_z, res); /* side effects */
65897
65898/*
65899 * Longjmp and other control flow transfer for the bytecode executor.
65900 *
65901 * The longjmp handler can handle all longjmp types: error, yield, and
65902 * resume (pseudotypes are never actually thrown).
65904 * Error policy for longjmp: should not ordinarily throw errors; if errors
65905 * occur (e.g. due to out-of-memory) they bubble outwards rather than being
65906 * handled recursively.
65907 */
65908
65909#define DUK__LONGJMP_RESTART 0 /* state updated, restart bytecode execution */
65910#define DUK__LONGJMP_RETHROW 1 /* exit bytecode executor by rethrowing an error to caller */
65911
65912#define DUK__RETHAND_RESTART 0 /* state updated, restart bytecode execution */
65913#define DUK__RETHAND_FINISHED 1 /* exit bytecode execution with return value */
65914
65915/* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
65916 * top are combined into one pass.
65917 */
65918
65919/* Reconfigure value stack for return to an Ecmascript function at 'act_idx'. */
65921 duk_activation *act;
65922 duk_hcompiledfunction *h_func;
65923 duk_idx_t clamp_top;
65924
65925 DUK_ASSERT(thr != NULL);
65926 DUK_ASSERT_DISABLE(act_idx >= 0); /* unsigned */
65927 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
65929 DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0); /* unsigned */
65930
65931 /* Clamp so that values at 'clamp_top' and above are wiped and won't
65932 * retain reachable garbage. Then extend to 'nregs' because we're
65933 * returning to an Ecmascript function.
65934 */
65935
65936 act = thr->callstack + act_idx;
65937 h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
65938
65940 DUK_ASSERT(act->idx_retval >= act->idx_bottom);
65941 clamp_top = (duk_idx_t) (act->idx_retval - act->idx_bottom + 1); /* +1 = one retval */
65942 duk_set_top((duk_context *) thr, clamp_top);
65943 act = NULL;
65944
65945 (void) duk_valstack_resize_raw((duk_context *) thr,
65946 (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
65947 h_func->nregs + /* reg count */
65948 DUK_VALSTACK_INTERNAL_EXTRA, /* + spare */
65949 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
65950 0 /* no compact */ |
65952
65953 duk_set_top((duk_context *) thr, h_func->nregs);
65954}
65955
65957 duk_activation *act;
65958 duk_catcher *cat;
65959 duk_hcompiledfunction *h_func;
65960 duk_idx_t clamp_top;
65961
65962 DUK_ASSERT(thr != NULL);
65963 DUK_ASSERT_DISABLE(act_idx >= 0); /* unsigned */
65964 DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
65966 DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0); /* unsigned */
65967
65968 act = thr->callstack + act_idx;
65969 cat = thr->catchstack + cat_idx;
65970 h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
65971
65972 thr->valstack_bottom = thr->valstack + act->idx_bottom;
65973 DUK_ASSERT(cat->idx_base >= act->idx_bottom);
65974 clamp_top = (duk_idx_t) (cat->idx_base - act->idx_bottom + 2); /* +2 = catcher value, catcher lj_type */
65975 duk_set_top((duk_context *) thr, clamp_top);
65976 act = NULL;
65977 cat = NULL;
65978
65979 (void) duk_valstack_resize_raw((duk_context *) thr,
65980 (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
65981 h_func->nregs + /* reg count */
65982 DUK_VALSTACK_INTERNAL_EXTRA, /* + spare */
65983 DUK_VSRESIZE_FLAG_SHRINK | /* flags */
65984 0 /* no compact */ |
65986
65987 duk_set_top((duk_context *) thr, h_func->nregs);
65988}
65989
65990/* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type. */
65991DUK_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) {
65992 duk_tval *tv1;
65993
65994 DUK_ASSERT(thr != NULL);
65995 DUK_ASSERT(tv_val_unstable != NULL);
65996
65997 tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base;
65998 DUK_ASSERT(tv1 < thr->valstack_top);
65999 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */
66000
66001 tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base + 1;
66002 DUK_ASSERT(tv1 < thr->valstack_top);
66003
66004 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) lj_type); /* side effects */
66005}
66006
66007DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
66008 duk_context *ctx;
66009 duk_activation *act;
66010
66011 DUK_ASSERT(thr != NULL);
66012 DUK_ASSERT(tv_val_unstable != NULL);
66013 ctx = (duk_context *) thr;
66014
66015 duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
66016
66017 duk_hthread_catchstack_unwind(thr, cat_idx + 1);
66019
66020 DUK_ASSERT(thr->callstack_top >= 1);
66023
66024 duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
66025
66026 DUK_ASSERT(thr->callstack_top >= 1);
66027 act = thr->callstack + thr->callstack_top - 1;
66028 act->curr_pc = thr->catchstack[cat_idx].pc_base + 0; /* +0 = catch */
66029 act = NULL;
66030
66031 /*
66032 * If entering a 'catch' block which requires an automatic
66033 * catch variable binding, create the lexical environment.
66034 *
66035 * The binding is mutable (= writable) but not deletable.
66036 * Step 4 for the catch production in E5 Section 12.14;
66037 * no value is given for CreateMutableBinding 'D' argument,
66038 * which implies the binding is not deletable.
66039 */
66040
66041 if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(&thr->catchstack[cat_idx])) {
66042 duk_hobject *new_env;
66043 duk_hobject *act_lex_env;
66044
66045 DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding"));
66046
66047 /* Note: 'act' is dangerous here because it may get invalidate at many
66048 * points, so we re-lookup it multiple times.
66049 */
66050 DUK_ASSERT(thr->callstack_top >= 1);
66051 act = thr->callstack + thr->callstack_top - 1;
66052
66053 if (act->lex_env == NULL) {
66054 DUK_ASSERT(act->var_env == NULL);
66055 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
66056
66057 /* this may have side effects, so re-lookup act */
66059 act = thr->callstack + thr->callstack_top - 1;
66060 }
66061 DUK_ASSERT(act->lex_env != NULL);
66062 DUK_ASSERT(act->var_env != NULL);
66064 DUK_UNREF(act); /* unreferenced without assertions */
66065
66066 act = thr->callstack + thr->callstack_top - 1;
66067 act_lex_env = act->lex_env;
66068 act = NULL; /* invalidated */
66069
66073 act_lex_env);
66074 new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
66075 DUK_ASSERT(new_env != NULL);
66076 DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
66077
66078 /* Note: currently the catch binding is handled without a register
66079 * binding because we don't support dynamic register bindings (they
66080 * must be fixed for an entire function). So, there is no need to
66081 * record regbases etc.
66082 */
66083
66084 DUK_ASSERT(thr->catchstack[cat_idx].h_varname != NULL);
66085 duk_push_hstring(ctx, thr->catchstack[cat_idx].h_varname);
66086 duk_push_tval(ctx, thr->valstack + thr->catchstack[cat_idx].idx_base);
66087 duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_W); /* writable, not configurable */
66088
66089 act = thr->callstack + thr->callstack_top - 1;
66090 act->lex_env = new_env;
66091 DUK_HOBJECT_INCREF(thr, new_env); /* reachable through activation */
66092
66093 DUK_CAT_SET_LEXENV_ACTIVE(&thr->catchstack[cat_idx]);
66094
66095 duk_pop(ctx);
66096
66097 DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
66098 }
66099
66101}
66102
66103DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
66104 duk_activation *act;
66105
66106 DUK_ASSERT(thr != NULL);
66107 DUK_ASSERT(tv_val_unstable != NULL);
66108
66109 duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
66110
66111 duk_hthread_catchstack_unwind(thr, cat_idx + 1); /* cat_idx catcher is kept, even for finally */
66113
66114 DUK_ASSERT(thr->callstack_top >= 1);
66117
66118 duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
66119
66120 DUK_ASSERT(thr->callstack_top >= 1);
66121 act = thr->callstack + thr->callstack_top - 1;
66122 act->curr_pc = thr->catchstack[cat_idx].pc_base + 1; /* +1 = finally */
66123 act = NULL;
66124
66126}
66127
66129 duk_activation *act;
66130
66131 DUK_ASSERT(thr != NULL);
66132
66133 DUK_ASSERT(thr->callstack_top >= 1);
66134 act = thr->callstack + thr->callstack_top - 1;
66135
66138
66139 /* +0 = break, +1 = continue */
66140 act->curr_pc = thr->catchstack[cat_idx].pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
66141 act = NULL; /* invalidated */
66142
66143 duk_hthread_catchstack_unwind(thr, cat_idx + 1); /* keep label catcher */
66144 /* no need to unwind callstack */
66145
66146 /* valstack should not need changes */
66147#if defined(DUK_USE_ASSERTIONS)
66148 DUK_ASSERT(thr->callstack_top >= 1);
66149 act = thr->callstack + thr->callstack_top - 1;
66152#endif
66153}
66154
66155/* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
66156 * when a RETURN opcode terminates a thread and yields to the resumer.
66157 */
66158DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_size_t act_idx, duk_tval *tv_val_unstable) {
66159 duk_tval *tv1;
66160
66161 DUK_ASSERT(thr != NULL);
66162 DUK_ASSERT(resumer != NULL);
66163 DUK_ASSERT(tv_val_unstable != NULL);
66164 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + act_idx) != NULL);
66165 DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + act_idx))); /* resume caller must be an ecmascript func */
66166
66167 tv1 = resumer->valstack + resumer->callstack[act_idx].idx_retval; /* return value from Duktape.Thread.resume() */
66168 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */
66169
66170 duk_hthread_callstack_unwind(resumer, act_idx + 1); /* unwind to 'resume' caller */
66171
66172 /* no need to unwind catchstack */
66173 duk__reconfig_valstack_ecma_return(resumer, act_idx);
66174
66175 /* caller must change active thread, and set thr->resumer to NULL */
66176}
66177
66180 duk_hthread *entry_thread,
66181 duk_size_t entry_callstack_top) {
66182 duk_size_t entry_callstack_index;
66184
66185 DUK_ASSERT(thr != NULL);
66186 DUK_ASSERT(entry_thread != NULL);
66187 DUK_ASSERT(entry_callstack_top > 0); /* guarantees entry_callstack_top - 1 >= 0 */
66188
66189 entry_callstack_index = entry_callstack_top - 1;
66190
66191 /* 'thr' is the current thread, as no-one resumes except us and we
66192 * switch 'thr' in that case.
66193 */
66194 DUK_ASSERT(thr == thr->heap->curr_thread);
66195
66196 /*
66197 * (Re)try handling the longjmp.
66198 *
66199 * A longjmp handler may convert the longjmp to a different type and
66200 * "virtually" rethrow by goto'ing to 'check_longjmp'. Before the goto,
66201 * the following must be updated:
66202 * - the heap 'lj' state
66203 * - 'thr' must reflect the "throwing" thread
66204 */
66205
66206 check_longjmp:
66207
66208 DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld",
66209 (long) thr->heap->lj.type,
66210 (duk_tval *) &thr->heap->lj.value1,
66211 (duk_tval *) &thr->heap->lj.value2,
66212 (long) thr->heap->lj.iserror));
66213
66214 switch (thr->heap->lj.type) {
66215
66216 case DUK_LJ_TYPE_RESUME: {
66217 /*
66218 * Note: lj.value1 is 'value', lj.value2 is 'resumee'.
66219 * This differs from YIELD.
66220 */
66221
66222 duk_tval *tv;
66223 duk_tval *tv2;
66224 duk_size_t act_idx;
66225 duk_hthread *resumee;
66226
66227 /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
66228
66229 DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged by Duktape.Thread.resume() */
66230 DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66235 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* an Ecmascript function */
66236 DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66237
66238 tv = &thr->heap->lj.value2; /* resumee */
66242 resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
66243
66244 DUK_ASSERT(resumee != NULL);
66245 DUK_ASSERT(resumee->resumer == NULL);
66247 resumee->state == DUK_HTHREAD_STATE_YIELDED); /* checked by Duktape.Thread.resume() */
66249 resumee->callstack_top >= 2); /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */
66251 (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1) != NULL &&
66253 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1))->func == duk_bi_thread_yield));
66255 (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2) != NULL &&
66256 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2)))); /* an Ecmascript function */
66258 (resumee->callstack + resumee->callstack_top - 2)->idx_retval >= 0); /* idx_retval unsigned */
66260 resumee->callstack_top == 0); /* INACTIVE: no activation, single function value on valstack */
66262 (resumee->valstack_top == resumee->valstack + 1 &&
66263 DUK_TVAL_IS_OBJECT(resumee->valstack_top - 1) &&
66265
66266 if (thr->heap->lj.iserror) {
66267 /*
66268 * Throw the error in the resumed thread's context; the
66269 * error value is pushed onto the resumee valstack.
66270 *
66271 * Note: the callstack of the target may empty in this case
66272 * too (i.e. the target thread has never been resumed). The
66273 * value stack will contain the initial function in that case,
66274 * which we simply ignore.
66275 */
66276
66277 resumee->resumer = thr;
66280 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66281 thr = resumee;
66282
66283 thr->heap->lj.type = DUK_LJ_TYPE_THROW;
66284
66285 /* thr->heap->lj.value1 is already the value to throw */
66286 /* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
66287
66288 DUK_ASSERT(thr->heap->lj.iserror); /* already set */
66289
66290 DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
66291 goto check_longjmp;
66292 } else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
66293 act_idx = resumee->callstack_top - 2; /* Ecmascript function */
66294 DUK_ASSERT_DISABLE(resumee->callstack[act_idx].idx_retval >= 0); /* unsigned */
66295
66296 tv = resumee->valstack + resumee->callstack[act_idx].idx_retval; /* return value from Duktape.Thread.yield() */
66297 DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
66298 tv2 = &thr->heap->lj.value1;
66299 DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2); /* side effects */
66300
66301 duk_hthread_callstack_unwind(resumee, act_idx + 1); /* unwind to 'yield' caller */
66302
66303 /* no need to unwind catchstack */
66304
66305 duk__reconfig_valstack_ecma_return(resumee, act_idx);
66306
66307 resumee->resumer = thr;
66310 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66311#if 0
66312 thr = resumee; /* not needed, as we exit right away */
66313#endif
66314 DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
66315 retval = DUK__LONGJMP_RESTART;
66316 goto wipe_and_return;
66317 } else {
66318 duk_small_uint_t call_flags;
66319 duk_bool_t setup_rc;
66320
66321 /* resumee: [... initial_func] (currently actually: [initial_func]) */
66322
66323 duk_push_undefined((duk_context *) resumee);
66324 tv = &thr->heap->lj.value1;
66325 duk_push_tval((duk_context *) resumee, tv);
66326
66327 /* resumee: [... initial_func undefined(= this) resume_value ] */
66328
66329 call_flags = DUK_CALL_FLAG_IS_RESUME; /* is resume, not a tail call */
66330
66331 setup_rc = duk_handle_ecma_call_setup(resumee,
66332 1, /* num_stack_args */
66333 call_flags); /* call_flags */
66334 if (setup_rc == 0) {
66335 /* Shouldn't happen but check anyway. */
66337 }
66338
66339 resumee->resumer = thr;
66342 DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66343#if 0
66344 thr = resumee; /* not needed, as we exit right away */
66345#endif
66346 DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
66347 retval = DUK__LONGJMP_RESTART;
66348 goto wipe_and_return;
66349 }
66351 break; /* never here */
66352 }
66353
66354 case DUK_LJ_TYPE_YIELD: {
66355 /*
66356 * Currently only allowed only if yielding thread has only
66357 * Ecmascript activations (except for the Duktape.Thread.yield()
66358 * call at the callstack top) and none of them constructor
66359 * calls.
66360 *
66361 * This excludes the 'entry' thread which will always have
66362 * a preventcount > 0.
66363 */
66364
66365 duk_hthread *resumer;
66366
66367 /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
66368
66369 DUK_ASSERT(thr != entry_thread); /* Duktape.Thread.yield() should prevent */
66370 DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged from Duktape.Thread.yield() */
66371 DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.yield() activation */
66376 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* an Ecmascript function */
66377 DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66378
66379 resumer = thr->resumer;
66380
66381 DUK_ASSERT(resumer != NULL);
66382 DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED); /* written by a previous RESUME handling */
66383 DUK_ASSERT(resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66384 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1) != NULL &&
66386 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1))->func == duk_bi_thread_resume);
66387 DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2) != NULL &&
66388 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2))); /* an Ecmascript function */
66389 DUK_ASSERT_DISABLE((resumer->callstack + resumer->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66390
66391 if (thr->heap->lj.iserror) {
66393 thr->resumer = NULL;
66395 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66396 thr = resumer;
66397
66398 thr->heap->lj.type = DUK_LJ_TYPE_THROW;
66399 /* lj.value1 is already set */
66400 DUK_ASSERT(thr->heap->lj.iserror); /* already set */
66401
66402 DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
66403 goto check_longjmp;
66404 } else {
66405 duk__handle_yield(thr, resumer, resumer->callstack_top - 2, &thr->heap->lj.value1);
66406
66408 thr->resumer = NULL;
66410 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66411#if 0
66412 thr = resumer; /* not needed, as we exit right away */
66413#endif
66414
66415 DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
66416 retval = DUK__LONGJMP_RESTART;
66417 goto wipe_and_return;
66418 }
66420 break; /* never here */
66421 }
66422
66423 case DUK_LJ_TYPE_THROW: {
66424 /*
66425 * Three possible outcomes:
66426 * * A try or finally catcher is found => resume there.
66427 * (or)
66428 * * The error propagates to the bytecode executor entry
66429 * level (and we're in the entry thread) => rethrow
66430 * with a new longjmp(), after restoring the previous
66431 * catchpoint.
66432 * * The error is not caught in the current thread, so
66433 * the thread finishes with an error. This works like
66434 * a yielded error, except that the thread is finished
66435 * and can no longer be resumed. (There is always a
66436 * resumer in this case.)
66437 *
66438 * Note: until we hit the entry level, there can only be
66439 * Ecmascript activations.
66440 */
66441
66442 duk_catcher *cat;
66443 duk_hthread *resumer;
66444
66445 cat = thr->catchstack + thr->catchstack_top - 1;
66446 while (cat >= thr->catchstack) {
66447 if (thr == entry_thread &&
66448 cat->callstack_index < entry_callstack_index) {
66449 /* entry level reached */
66450 break;
66451 }
66452
66453 if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
66455
66457 cat - thr->catchstack,
66458 &thr->heap->lj.value1,
66460
66461 DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
66462 retval = DUK__LONGJMP_RESTART;
66463 goto wipe_and_return;
66464 }
66465
66466 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
66469
66471 cat - thr->catchstack,
66472 &thr->heap->lj.value1,
66474
66475 DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
66476 retval = DUK__LONGJMP_RESTART;
66477 goto wipe_and_return;
66478 }
66479
66480 cat--;
66481 }
66482
66483 if (thr == entry_thread) {
66484 /* not caught by anything before entry level; rethrow and let the
66485 * final catcher unwind everything
66486 */
66487#if 0
66488 duk_hthread_catchstack_unwind(thr, (cat - thr->catchstack) + 1); /* leave 'cat' as top catcher (also works if catchstack exhausted) */
66489 duk_hthread_callstack_unwind(thr, entry_callstack_index + 1);
66490
66491#endif
66492 DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
66493 retval = DUK__LONGJMP_RETHROW;
66494 goto just_return;
66495 /* Note: MUST NOT wipe_and_return here, as heap->lj must remain intact */
66496 }
66497
66498 DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
66499
66500 /* not caught by current thread, thread terminates (yield error to resumer);
66501 * note that this may cause a cascade if the resumer terminates with an uncaught
66502 * exception etc (this is OK, but needs careful testing)
66503 */
66504
66505 DUK_ASSERT(thr->resumer != NULL);
66506 DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66509 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */
66511 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2))); /* an Ecmascript function */
66512
66513 resumer = thr->resumer;
66514
66515 /* reset longjmp */
66516
66517 DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW); /* already set */
66518 /* lj.value1 already set */
66519
66520 duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
66522
66523 thr->resumer = NULL;
66525 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66526 thr = resumer;
66527 goto check_longjmp;
66528 }
66529
66530 case DUK_LJ_TYPE_BREAK: /* pseudotypes, not used in actual longjmps */
66532 case DUK_LJ_TYPE_RETURN:
66533 case DUK_LJ_TYPE_NORMAL:
66534 default: {
66535 /* should never happen, but be robust */
66536 DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
66537 goto convert_to_internal_error;
66538 }
66539
66540 } /* end switch */
66541
66543
66544 wipe_and_return:
66545 /* this is not strictly necessary, but helps debugging */
66547 thr->heap->lj.iserror = 0;
66548
66549 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
66550 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
66551
66552 just_return:
66553 return retval;
66554
66555 convert_to_internal_error:
66556 /* This could also be thrown internally (set the error, goto check_longjmp),
66557 * but it's better for internal errors to bubble outwards so that we won't
66558 * infinite loop in this catchpoint.
66559 */
66562 return retval;
66563}
66564
66565/* Handle a BREAK/CONTINUE opcode. Avoid using longjmp() for BREAK/CONTINUE
66566 * handling because it has a measurable performance impact in ordinary
66567 * environments and an extreme impact in Emscripten (GH-342).
66568 */
66570 duk_uint_t label_id,
66571 duk_small_uint_t lj_type) {
66572 duk_catcher *cat;
66573 duk_size_t orig_callstack_index;
66574
66575 DUK_ASSERT(thr != NULL);
66576
66577 /*
66578 * Find a matching label catcher or 'finally' catcher in
66579 * the same function.
66580 *
66581 * A label catcher must always exist and will match unless
66582 * a 'finally' captures the break/continue first. It is the
66583 * compiler's responsibility to ensure that labels are used
66584 * correctly.
66585 */
66586
66587 /* Note: thr->catchstack_top may be 0, so that cat < thr->catchstack
66588 * initially. This is OK and intended.
66589 */
66590 cat = thr->catchstack + thr->catchstack_top - 1;
66591 DUK_ASSERT(thr->callstack_top > 0);
66592 orig_callstack_index = thr->callstack_top - 1;
66593
66594 DUK_DDD(DUK_DDDPRINT("handling break/continue with label=%ld, callstack index=%ld",
66595 (long) label_id, (long) cat->callstack_index));
66596
66597 while (cat >= thr->catchstack) {
66598 if (cat->callstack_index != orig_callstack_index) {
66599 break;
66600 }
66601 DUK_DDD(DUK_DDDPRINT("considering catcher %ld: type=%ld label=%ld",
66602 (long) (cat - thr->catchstack),
66603 (long) DUK_CAT_GET_TYPE(cat),
66604 (long) DUK_CAT_GET_LABEL(cat)));
66605
66606 if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
66608 duk_size_t cat_idx;
66609 duk_tval tv_tmp;
66610
66611 cat_idx = (duk_size_t) (cat - thr->catchstack); /* get before side effects */
66612
66613 DUK_TVAL_SET_FASTINT_U32(&tv_tmp, (duk_uint32_t) label_id);
66614 duk__handle_finally(thr, cat_idx, &tv_tmp, lj_type);
66615
66616 DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
66617 return;
66618 }
66620 (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
66621 duk_size_t cat_idx;
66622
66623 cat_idx = (duk_size_t) (cat - thr->catchstack);
66624 duk__handle_label(thr, cat_idx, lj_type);
66626 DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
66627 return;
66628 }
66629 cat--;
66630 }
66631
66632 /* should never happen, but be robust */
66633 DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
66635 return;
66636}
66637
66638/* Handle a RETURN opcode. Avoid using longjmp() for return handling because
66639 * it has a measurable performance impact in ordinary environments and an extreme
66640 * impact in Emscripten (GH-342). Return value is on value stack top.
66641 */
66643 duk_hthread *entry_thread,
66644 duk_size_t entry_callstack_top) {
66645 duk_tval *tv1;
66646 duk_tval *tv2;
66647 duk_hthread *resumer;
66648 duk_catcher *cat;
66649 duk_size_t new_cat_top;
66650 duk_size_t orig_callstack_index;
66651
66652 /* We can directly access value stack here. */
66653
66654 DUK_ASSERT(thr != NULL);
66655 DUK_ASSERT(entry_thread != NULL);
66656 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66657 tv1 = thr->valstack_top - 1;
66658 DUK_TVAL_CHKFAST_INPLACE(tv1); /* fastint downgrade check for return values */
66659
66660 /*
66661 * Four possible outcomes:
66662 *
66663 * 1. A 'finally' in the same function catches the 'return'.
66664 * It may continue to propagate when 'finally' is finished,
66665 * or it may be neutralized by 'finally' (both handled by
66666 * ENDFIN).
66667 *
66668 * 2. The return happens at the entry level of the bytecode
66669 * executor, so return from the executor (in C stack).
66670 *
66671 * 3. There is a calling (Ecmascript) activation in the call
66672 * stack => return to it, in the same executor instance.
66673 *
66674 * 4. There is no calling activation, and the thread is
66675 * terminated. There is always a resumer in this case,
66676 * which gets the return value similarly to a 'yield'
66677 * (except that the current thread can no longer be
66678 * resumed).
66679 */
66680
66681 DUK_ASSERT(thr != NULL);
66682 DUK_ASSERT(thr->callstack_top >= 1);
66683 DUK_ASSERT(thr->catchstack != NULL);
66684
66685 /* XXX: does not work if thr->catchstack is NULL */
66686 /* XXX: does not work if thr->catchstack is allocated but lowest pointer */
66687
66688 cat = thr->catchstack + thr->catchstack_top - 1; /* may be < thr->catchstack initially */
66689 DUK_ASSERT(thr->callstack_top > 0); /* ensures callstack_top - 1 >= 0 */
66690 orig_callstack_index = thr->callstack_top - 1;
66691
66692 while (cat >= thr->catchstack) {
66693 if (cat->callstack_index != orig_callstack_index) {
66694 break;
66695 }
66696 if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
66698 duk_size_t cat_idx;
66699
66700 cat_idx = (duk_size_t) (cat - thr->catchstack); /* get before side effects */
66701
66702 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66703 duk__handle_finally(thr, cat_idx, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
66704
66705 DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
66706 return DUK__RETHAND_RESTART;
66707 }
66708 cat--;
66709 }
66710 /* If out of catchstack, cat = thr->catchstack - 1;
66711 * new_cat_top will be 0 in that case.
66712 */
66713 new_cat_top = (duk_size_t) ((cat + 1) - thr->catchstack);
66714 cat = NULL; /* avoid referencing, invalidated */
66715
66716 DUK_DDD(DUK_DDDPRINT("no catcher in catch stack, return to calling activation / yield"));
66717
66718 if (thr == entry_thread &&
66719 thr->callstack_top == entry_callstack_top) {
66720 /* Return to the bytecode executor caller which will unwind stacks.
66721 * Return value is already on the stack top: [ ... retval ].
66722 */
66723
66724 /* XXX: could unwind catchstack here, so that call handling
66725 * didn't need to do that?
66726 */
66727 DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
66728 return DUK__RETHAND_FINISHED;
66729 }
66730
66731 if (thr->callstack_top >= 2) {
66732 /* There is a caller; it MUST be an Ecmascript caller (otherwise it would
66733 * match entry level check)
66734 */
66735
66736 DUK_DDD(DUK_DDDPRINT("return to Ecmascript caller, idx_retval=%ld, lj_value1=%!T",
66737 (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
66738 (duk_tval *) &thr->heap->lj.value1));
66739
66740 DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* must be ecmascript */
66741
66742 tv1 = thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval;
66743 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66744 tv2 = thr->valstack_top - 1;
66745 DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
66746
66747 DUK_DDD(DUK_DDDPRINT("return value at idx_retval=%ld is %!T",
66748 (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
66749 (duk_tval *) (thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval)));
66750
66751 duk_hthread_catchstack_unwind(thr, new_cat_top); /* leave 'cat' as top catcher (also works if catchstack exhausted) */
66754
66755 DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
66756 return DUK__RETHAND_RESTART;
66757 }
66758
66759 DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
66760
66761 DUK_ASSERT(thr->resumer != NULL);
66762 DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
66765 ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */
66767 DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2))); /* an Ecmascript function */
66768 DUK_ASSERT_DISABLE((thr->resumer->callstack + thr->resumer->callstack_top - 2)->idx_retval >= 0); /* unsigned */
66771
66772 resumer = thr->resumer;
66773
66774 /* Share yield longjmp handler. */
66775 DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66776 duk__handle_yield(thr, resumer, resumer->callstack_top - 2, thr->valstack_top - 1);
66777
66778 duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
66780
66781 thr->resumer = NULL;
66783 DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66784#if 0
66785 thr = resumer; /* not needed */
66786#endif
66787
66788 DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
66789 return DUK__RETHAND_RESTART;
66790}
66791
66792/*
66793 * Executor interrupt handling
66794 *
66795 * The handler is called whenever the interrupt countdown reaches zero
66796 * (or below). The handler must perform whatever checks are activated,
66797 * e.g. check for cumulative step count to impose an execution step
66798 * limit or check for breakpoints or other debugger interaction.
66799 *
66800 * When the actions are done, the handler must reinit the interrupt
66801 * init and counter values. The 'init' value must indicate how many
66802 * bytecode instructions are executed before the next interrupt. The
66803 * counter must interface with the bytecode executor loop. Concretely,
66804 * the new init value is normally one higher than the new counter value.
66805 * For instance, to execute exactly one bytecode instruction the init
66806 * value is set to 1 and the counter to 0. If an error is thrown by the
66807 * interrupt handler, the counters are set to the same value (e.g. both
66808 * to 0 to cause an interrupt when the next bytecode instruction is about
66809 * to be executed after error handling).
66810 *
66811 * Maintaining the init/counter value properly is important for accurate
66812 * behavior. For instance, executor step limit needs a cumulative step
66813 * count which is simply computed as a sum of 'init' values. This must
66814 * work accurately even when single stepping.
66815 */
66816
66817#if defined(DUK_USE_INTERRUPT_COUNTER)
66818
66819#define DUK__INT_NOACTION 0 /* no specific action, resume normal execution */
66820#define DUK__INT_RESTART 1 /* must "goto restart_execution", e.g. breakpoints changed */
66821
66822#if defined(DUK_USE_DEBUGGER_SUPPORT)
66823DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
66824 duk_context *ctx;
66825 duk_activation *act;
66826 duk_breakpoint *bp;
66827 duk_breakpoint **bp_active;
66828 duk_uint_fast32_t line = 0;
66829 duk_bool_t process_messages;
66830 duk_bool_t processed_messages = 0;
66831
66832 DUK_ASSERT(thr->heap->dbg_processing == 0); /* don't re-enter e.g. during Eval */
66833
66834 ctx = (duk_context *) thr;
66835 act = thr->callstack + thr->callstack_top - 1;
66836
66837 /* It might seem that replacing 'thr->heap' with just 'heap' below
66838 * might be a good idea, but it increases code size slightly
66839 * (probably due to unnecessary spilling) at least on x64.
66840 */
66841
66842 /*
66843 * Breakpoint and step state checks
66844 */
66845
66847 (thr->heap->dbg_step_thread == thr &&
66848 thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
66849 line = duk_debug_curr_line(thr);
66850
66851 if (act->prev_line != line) {
66852 /* Stepped? Step out is handled by callstack unwind. */
66853 if ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
66854 thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
66855 (thr->heap->dbg_step_thread == thr) &&
66856 (thr->heap->dbg_step_csindex == thr->callstack_top - 1) &&
66857 (line != thr->heap->dbg_step_startline)) {
66858 DUK_D(DUK_DPRINT("STEP STATE TRIGGERED PAUSE at line %ld",
66859 (long) line));
66860
66861 DUK_HEAP_SET_PAUSED(thr->heap);
66862 }
66863
66864 /* Check for breakpoints only on line transition.
66865 * Breakpoint is triggered when we enter the target
66866 * line from a different line, and the previous line
66867 * was within the same function.
66868 *
66869 * This condition is tricky: the condition used to be
66870 * that transition to -or across- the breakpoint line
66871 * triggered the breakpoint. This seems intuitively
66872 * better because it handles breakpoints on lines with
66873 * no emitted opcodes; but this leads to the issue
66874 * described in: https://github.com/svaarala/duktape/issues/263.
66875 */
66876 bp_active = thr->heap->dbg_breakpoints_active;
66877 for (;;) {
66878 bp = *bp_active++;
66879 if (bp == NULL) {
66880 break;
66881 }
66882
66883 DUK_ASSERT(bp->filename != NULL);
66884 if (act->prev_line != bp->line && line == bp->line) {
66885 DUK_D(DUK_DPRINT("BREAKPOINT TRIGGERED at %!O:%ld",
66886 (duk_heaphdr *) bp->filename, (long) bp->line));
66887
66888 DUK_HEAP_SET_PAUSED(thr->heap);
66889 }
66890 }
66891 } else {
66892 ;
66893 }
66894
66895 act->prev_line = line;
66896 }
66897
66898 /*
66899 * Rate limit check for sending status update or peeking into
66900 * the debug transport. Both can be expensive operations that
66901 * we don't want to do on every opcode.
66902 *
66903 * Making sure the interval remains reasonable on a wide variety
66904 * of targets and bytecode is difficult without a timestamp, so
66905 * we use a Date-provided timestamp for the rate limit check.
66906 * But since it's also expensive to get a timestamp, a bytecode
66907 * counter is used to rate limit getting timestamps.
66908 */
66909
66910 process_messages = 0;
66911 if (thr->heap->dbg_state_dirty || thr->heap->dbg_paused || thr->heap->dbg_detaching) {
66912 /* Enter message processing loop for sending Status notifys and
66913 * to finish a pending detach.
66914 */
66915 process_messages = 1;
66916 }
66917
66918 /* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
66919 thr->heap->dbg_exec_counter += thr->interrupt_init;
66920 if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
66921 /* Overflow of the execution counter is fine and doesn't break
66922 * anything here.
66923 */
66924
66925 duk_double_t now, diff_last;
66926
66927 thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
66928 now = DUK_USE_DATE_GET_NOW(ctx);
66929
66930 diff_last = now - thr->heap->dbg_last_time;
66931 if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
66932 /* Negative value checked so that a "time jump" works
66933 * reasonably.
66934 *
66935 * Same interval is now used for status sending and
66936 * peeking.
66937 */
66938
66939 thr->heap->dbg_last_time = now;
66940 thr->heap->dbg_state_dirty = 1;
66941 process_messages = 1;
66942 }
66943 }
66944
66945 /*
66946 * Process messages and send status if necessary.
66947 *
66948 * If we're paused, we'll block for new messages. If we're not
66949 * paused, we'll process anything we can peek but won't block
66950 * for more. Detach (and re-attach) handling is all localized
66951 * to duk_debug_process_messages() too.
66952 *
66953 * Debugger writes outside the message loop may cause debugger
66954 * detach1 phase to run, after which dbg_read_cb == NULL and
66955 * dbg_detaching != 0. The message loop will finish the detach
66956 * by running detach2 phase, so enter the message loop also when
66957 * detaching.
66958 */
66959
66960 act = NULL; /* may be changed */
66961 if (process_messages) {
66962 DUK_ASSERT(thr->heap->dbg_processing == 0);
66963 processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
66964 DUK_ASSERT(thr->heap->dbg_processing == 0);
66965 }
66966
66967 /* Continue checked execution if there are breakpoints or we're stepping.
66968 * Also use checked execution if paused flag is active - it shouldn't be
66969 * because the debug message loop shouldn't terminate if it was. Step out
66970 * is handled by callstack unwind and doesn't need checked execution.
66971 * Note that debugger may have detached due to error or explicit request
66972 * above, so we must recheck attach status.
66973 */
66974
66975 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
66976 act = thr->callstack + thr->callstack_top - 1; /* relookup, may have changed */
66978 ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
66979 thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
66980 thr->heap->dbg_step_thread == thr &&
66981 thr->heap->dbg_step_csindex == thr->callstack_top - 1) ||
66982 thr->heap->dbg_paused) {
66983 *out_immediate = 1;
66984 }
66985
66986 /* If we processed any debug messages breakpoints may have
66987 * changed; restart execution to re-check active breakpoints.
66988 */
66989 if (processed_messages) {
66990 DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
66991 *out_interrupt_retval = DUK__INT_RESTART;
66992 }
66993 } else {
66994 DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
66995 }
66996}
66997#endif /* DUK_USE_DEBUGGER_SUPPORT */
66998
66999DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
67000 duk_int_t ctr;
67001 duk_activation *act;
67003 duk_bool_t immediate = 0;
67004 duk_small_uint_t retval;
67005
67006 DUK_ASSERT(thr != NULL);
67007 DUK_ASSERT(thr->heap != NULL);
67008 DUK_ASSERT(thr->callstack != NULL);
67009 DUK_ASSERT(thr->callstack_top > 0);
67010
67011#if defined(DUK_USE_DEBUG)
67012 thr->heap->inst_count_interrupt += thr->interrupt_init;
67013 DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
67014 "instruction counts: executor=%ld, interrupt=%ld",
67015 (long) thr->interrupt_counter, (long) thr->interrupt_init,
67016 (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
67017#endif
67018
67019 retval = DUK__INT_NOACTION;
67020 ctr = DUK_HTHREAD_INTCTR_DEFAULT;
67021
67022 /*
67023 * Avoid nested calls. Concretely this happens during debugging, e.g.
67024 * when we eval() an expression.
67025 *
67026 * Also don't interrupt if we're currently doing debug processing
67027 * (which can be initiated outside the bytecode executor) as this
67028 * may cause the debugger to be called recursively. Check required
67029 * for correct operation of throw intercept and other "exotic" halting
67030 * scenarios.
67031 */
67032
67033#if defined(DUK_USE_DEBUGGER_SUPPORT)
67034 if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
67035#else
67037#endif
67038 DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
67039
67040 /* Set a high interrupt counter; the original executor
67041 * interrupt invocation will rewrite before exiting.
67042 */
67043 thr->interrupt_init = ctr;
67044 thr->interrupt_counter = ctr - 1;
67045 return DUK__INT_NOACTION;
67046 }
67048
67049 act = thr->callstack + thr->callstack_top - 1;
67050
67053
67054 DUK_UNREF(fun);
67055
67056#if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
67057 /*
67058 * Execution timeout check
67059 */
67060
67061 if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
67062 /* Keep throwing an error whenever we get here. The unusual values
67063 * are set this way because no instruction is ever executed, we just
67064 * throw an error until all try/catch/finally and other catchpoints
67065 * have been exhausted. Duktape/C code gets control at each protected
67066 * call but whenever it enters back into Duktape the RangeError gets
67067 * raised. User exec timeout check must consistently indicate a timeout
67068 * until we've fully bubbled out of Duktape.
67069 */
67070 DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
67071 thr->interrupt_init = 0;
67072 thr->interrupt_counter = 0;
67074 DUK_ERROR_RANGE(thr, "execution timeout");
67075 }
67076#endif /* DUK_USE_EXEC_TIMEOUT_CHECK */
67077
67078#if defined(DUK_USE_DEBUGGER_SUPPORT)
67079 if (!thr->heap->dbg_processing &&
67080 (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
67081 /* Avoid recursive re-entry; enter when we're attached or
67082 * detaching (to finish off the pending detach).
67083 */
67084 duk__interrupt_handle_debugger(thr, &immediate, &retval);
67085 act = thr->callstack + thr->callstack_top - 1; /* relookup if changed */
67086 DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
67087 }
67088#endif /* DUK_USE_DEBUGGER_SUPPORT */
67089
67090 /*
67091 * Update the interrupt counter
67092 */
67093
67094 if (immediate) {
67095 /* Cause an interrupt after executing one instruction. */
67096 ctr = 1;
67097 }
67098
67099 /* The counter value is one less than the init value: init value should
67100 * indicate how many instructions are executed before interrupt. To
67101 * execute 1 instruction (after interrupt handler return), counter must
67102 * be 0.
67103 */
67104 DUK_ASSERT(ctr >= 1);
67105 thr->interrupt_init = ctr;
67106 thr->interrupt_counter = ctr - 1;
67108
67109 return retval;
67110}
67111#endif /* DUK_USE_INTERRUPT_COUNTER */
67112
67113/*
67114 * Debugger handling for executor restart
67115 *
67116 * Check for breakpoints, stepping, etc, and figure out if we should execute
67117 * in checked or normal mode. Note that we can't do this when an activation
67118 * is created, because breakpoint status (and stepping status) may change
67119 * later, so we must recheck every time we're executing an activation.
67120 * This primitive should be side effect free to avoid changes during check.
67121 */
67122
67123#if defined(DUK_USE_DEBUGGER_SUPPORT)
67124DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompiledfunction *fun) {
67125 duk_heap *heap;
67126 duk_tval *tv_tmp;
67127 duk_hstring *filename;
67128 duk_small_uint_t bp_idx;
67129 duk_breakpoint **bp_active;
67130
67131 DUK_ASSERT(thr != NULL);
67132 DUK_ASSERT(act != NULL);
67133 DUK_ASSERT(fun != NULL);
67134
67135 heap = thr->heap;
67136 bp_active = heap->dbg_breakpoints_active;
67137 act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
67138
67140 if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
67141 filename = DUK_TVAL_GET_STRING(tv_tmp);
67142
67143 /* Figure out all active breakpoints. A breakpoint is
67144 * considered active if the current function's fileName
67145 * matches the breakpoint's fileName, AND there is no
67146 * inner function that has matching line numbers
67147 * (otherwise a breakpoint would be triggered both
67148 * inside and outside of the inner function which would
67149 * be confusing). Example:
67150 *
67151 * function foo() {
67152 * print('foo');
67153 * function bar() { <-. breakpoints in these
67154 * print('bar'); | lines should not affect
67155 * } <-' foo() execution
67156 * bar();
67157 * }
67158 *
67159 * We need a few things that are only available when
67160 * debugger support is enabled: (1) a line range for
67161 * each function, and (2) access to the function
67162 * template to access the inner functions (and their
67163 * line ranges).
67164 *
67165 * It's important to have a narrow match for active
67166 * breakpoints so that we don't enter checked execution
67167 * when that's not necessary. For instance, if we're
67168 * running inside a certain function and there's
67169 * breakpoint outside in (after the call site), we
67170 * don't want to slow down execution of the function.
67171 */
67172
67173 for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
67174 duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
67175 duk_hobject **funcs, **funcs_end;
67176 duk_hcompiledfunction *inner_fun;
67177 duk_bool_t bp_match;
67178
67179 if (bp->filename == filename &&
67180 bp->line >= fun->start_line && bp->line <= fun->end_line) {
67181 bp_match = 1;
67182 DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
67183 "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
67185 (long) bp->line,
67186 DUK_HSTRING_GET_DATA(filename),
67187 (long) bp->line,
67188 (long) fun->start_line,
67189 (long) fun->end_line));
67190
67192 funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, fun);
67193 while (funcs != funcs_end) {
67194 inner_fun = (duk_hcompiledfunction *) *funcs;
67196 if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
67197 DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
67198 bp_match = 0;
67199 break;
67200 }
67201 funcs++;
67202 }
67203
67204 if (bp_match) {
67205 /* No need to check for size of bp_active list,
67206 * it's always larger than maximum number of
67207 * breakpoints.
67208 */
67210 *bp_active = heap->dbg_breakpoints + bp_idx;
67211 bp_active++;
67212 }
67213 }
67214 }
67215 }
67216
67217 *bp_active = NULL; /* terminate */
67218
67219 DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
67220
67221 /* Force pause if we were doing "step into" in another activation. */
67222 if (thr->heap->dbg_step_thread != NULL &&
67223 thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO &&
67224 (thr->heap->dbg_step_thread != thr ||
67225 thr->heap->dbg_step_csindex != thr->callstack_top - 1)) {
67226 DUK_D(DUK_DPRINT("STEP INTO ACTIVE, FORCE PAUSED"));
67227 DUK_HEAP_SET_PAUSED(thr->heap);
67228 }
67229
67230 /* Force interrupt right away if we're paused or in "checked mode".
67231 * Step out is handled by callstack unwind.
67232 */
67234 thr->heap->dbg_paused ||
67235 (thr->heap->dbg_step_type != DUK_STEP_TYPE_OUT &&
67236 thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
67237 /* We'll need to interrupt early so recompute the init
67238 * counter to reflect the number of bytecode instructions
67239 * executed so that step counts for e.g. debugger rate
67240 * limiting are accurate.
67241 */
67242 DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
67243 thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
67244 thr->interrupt_counter = 0;
67245 }
67246}
67247#endif /* DUK_USE_DEBUGGER_SUPPORT */
67248
67249/*
67250 * Ecmascript bytecode executor.
67251 *
67252 * Resume execution for the current thread from its current activation.
67253 * Returns when execution would return from the entry level activation,
67254 * leaving a single return value on top of the stack. Function calls
67255 * and thread resumptions are handled internally. If an error occurs,
67256 * a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
67257 * setjmp() jmpbuf.
67258 *
67259 * Ecmascript function calls and coroutine resumptions are handled
67260 * internally (by the outer executor function) without recursive C calls.
67261 * Other function calls are handled using duk_handle_call(), increasing
67262 * C recursion depth.
67263 *
67264 * Abrupt completions (= long control tranfers) are handled either
67265 * directly by reconfiguring relevant stacks and restarting execution,
67266 * or via a longjmp. Longjmp-free handling is preferable for performance
67267 * (especially Emscripten performance), and is used for: break, continue,
67268 * and return.
67269 *
67270 * For more detailed notes, see doc/execution.rst.
67271 *
67272 * Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
67273 * and volatile.
67276/* Presence of 'fun' is config based, there's a marginal performance
67277 * difference and the best option is architecture dependent.
67278 */
67279#if defined(DUK_USE_EXEC_FUN_LOCAL)
67280#define DUK__FUN() fun
67281#else
67282#define DUK__FUN() ((duk_hcompiledfunction *) DUK_ACT_GET_FUNC((thr)->callstack + (thr)->callstack_top - 1))
67283#endif
67284#define DUK__STRICT() (DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
67285
67286/* Reg/const access macros: these are very footprint and performance sensitive
67287 * so modify with care.
67289#define DUK__REG(x) (*(thr->valstack_bottom + (x)))
67290#define DUK__REGP(x) (thr->valstack_bottom + (x))
67291#define DUK__CONST(x) (*(consts + (x)))
67292#define DUK__CONSTP(x) (consts + (x))
67293#if 0
67294#define DUK__REGCONST(x) ((x) < DUK_BC_REGLIMIT ? DUK__REG((x)) : DUK__CONST((x) - DUK_BC_REGLIMIT))
67295#define DUK__REGCONSTP(x) ((x) < DUK_BC_REGLIMIT ? DUK__REGP((x)) : DUK__CONSTP((x) - DUK_BC_REGLIMIT))
67296#define DUK__REGCONST(x) *((((x) < DUK_BC_REGLIMIT ? thr->valstack_bottom : consts2) + (x)))
67297#define DUK__REGCONSTP(x) (((x) < DUK_BC_REGLIMIT ? thr->valstack_bottom : consts2) + (x))
67298#endif
67299/* This macro works when a regconst field is 9 bits, [0,0x1ff]. Adding
67300 * DUK_LIKELY/DUK_UNLIKELY increases code footprint and doesn't seem to
67301 * improve performance on x64 (and actually harms performance in some tests).
67302 */
67303#define DUK__RCISREG(x) (((x) & 0x100) == 0)
67304#define DUK__REGCONST(x) (*((DUK__RCISREG((x)) ? thr->valstack_bottom : consts2) + (x)))
67305#define DUK__REGCONSTP(x) ((DUK__RCISREG((x)) ? thr->valstack_bottom : consts2) + (x))
67306
67307#ifdef DUK_USE_VERBOSE_EXECUTOR_ERRORS
67308#define DUK__INTERNAL_ERROR(msg) do { \
67309 DUK_ERROR_INTERNAL(thr, (msg)); \
67310 } while (0)
67311#else
67312#define DUK__INTERNAL_ERROR(msg) do { \
67313 goto internal_error; \
67314 } while (0)
67315#endif
67316
67317#define DUK__SYNC_CURR_PC() do { \
67318 duk_activation *act; \
67319 act = thr->callstack + thr->callstack_top - 1; \
67320 act->curr_pc = curr_pc; \
67321 } while (0)
67322#define DUK__SYNC_AND_NULL_CURR_PC() do { \
67323 duk_activation *act; \
67324 act = thr->callstack + thr->callstack_top - 1; \
67325 act->curr_pc = curr_pc; \
67326 thr->ptr_curr_pc = NULL; \
67327 } while (0)
67328
67330 duk_hthread *entry_thread,
67331 duk_size_t entry_callstack_top,
67332 duk_int_t entry_call_recursion_depth,
67333 duk_jmpbuf *entry_jmpbuf_ptr) {
67334 duk_small_uint_t lj_ret;
67335
67336 /* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
67337 * before longjmp.
67338 */
67339 DUK_ASSERT(heap->curr_thread != NULL);
67341
67342 /* XXX: signalling the need to shrink check (only if unwound) */
67343
67344 /* Must be restored here to handle e.g. yields properly. */
67345 heap->call_recursion_depth = entry_call_recursion_depth;
67346
67347 /* Switch to caller's setjmp() catcher so that if an error occurs
67348 * during error handling, it is always propagated outwards instead
67349 * of causing an infinite loop in our own handler.
67350 */
67351 heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
67352
67353 lj_ret = duk__handle_longjmp(heap->curr_thread, entry_thread, entry_callstack_top);
67354
67355 if (lj_ret == DUK__LONGJMP_RESTART) {
67356 /* Restart bytecode execution, possibly with a changed thread. */
67357 ;
67358 } else {
67359 /* Rethrow error to calling state. */
67361
67362 /* Longjmp handling has restored jmpbuf_ptr. */
67363 DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);
67364
67365 /* Thread may have changed, e.g. YIELD converted to THROW. */
67368 }
67369}
67370
67371/* Outer executor with setjmp/longjmp handling. */
67373 /* Entry level info. */
67374 duk_hthread *entry_thread;
67375 duk_size_t entry_callstack_top;
67376 duk_int_t entry_call_recursion_depth;
67377 duk_jmpbuf *entry_jmpbuf_ptr;
67378 duk_jmpbuf our_jmpbuf;
67379 duk_heap *heap;
67380
67381 DUK_ASSERT(exec_thr != NULL);
67382 DUK_ASSERT(exec_thr->heap != NULL);
67383 DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
67385 DUK_ASSERT(exec_thr->callstack_top >= 1); /* at least one activation, ours */
67386 DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1) != NULL);
67388
67389 entry_thread = exec_thr;
67390 heap = entry_thread->heap;
67391 entry_callstack_top = entry_thread->callstack_top;
67392 entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
67393 entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
67394
67395 /*
67396 * Note: we currently assume that the setjmp() catchpoint is
67397 * not re-entrant (longjmp() cannot be called more than once
67398 * for a single setjmp()).
67399 *
67400 * See doc/code-issues.rst for notes on variable assignment
67401 * before and after setjmp().
67402 */
67403
67404 for (;;) {
67405 heap->lj.jmpbuf_ptr = &our_jmpbuf;
67406 DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
67407
67408#if defined(DUK_USE_CPP_EXCEPTIONS)
67409 try {
67410#else
67411 DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
67412 if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
67413#endif
67414 /* Execute bytecode until returned or longjmp(). */
67415 duk__js_execute_bytecode_inner(entry_thread, entry_callstack_top);
67416
67417 /* Successful return: restore jmpbuf and return to caller. */
67418 heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
67419
67420 return;
67421#if defined(DUK_USE_CPP_EXCEPTIONS)
67422 } catch (duk_internal_exception &exc) {
67423#else
67424 } else {
67425#endif
67426#if defined(DUK_USE_CPP_EXCEPTIONS)
67427 DUK_UNREF(exc);
67428#endif
67429 DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
67430
67432 entry_thread,
67433 entry_callstack_top,
67434 entry_call_recursion_depth,
67435 entry_jmpbuf_ptr);
67436 }
67437#if defined(DUK_USE_CPP_EXCEPTIONS)
67438 catch (std::exception &exc) {
67439 const char *what = exc.what();
67440 if (!what) {
67441 what = "unknown";
67442 }
67443 DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
67444 try {
67445 DUK_ASSERT(heap->curr_thread != NULL);
67446 DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
67447 } catch (duk_internal_exception exc) {
67448 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
67449 DUK_UNREF(exc);
67451 entry_thread,
67452 entry_callstack_top,
67453 entry_call_recursion_depth,
67454 entry_jmpbuf_ptr);
67455 }
67456 } catch (...) {
67457 DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
67458 try {
67459 DUK_ASSERT(heap->curr_thread != NULL);
67460 DUK_ERROR_API(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
67461 } catch (duk_internal_exception exc) {
67462 DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
67463 DUK_UNREF(exc);
67465 entry_thread,
67466 entry_callstack_top,
67467 entry_call_recursion_depth,
67468 entry_jmpbuf_ptr);
67469 }
67470 }
67471#endif
67472 }
67473
67475}
67476
67477/* Inner executor, performance critical. */
67478DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top) {
67479 /* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
67480 * Critical for performance. It would be safest to make this volatile,
67481 * but that eliminates performance benefits; aliasing guarantees
67482 * should be enough though.
67483 */
67484 duk_instr_t *curr_pc; /* bytecode has a stable pointer */
67485
67486 /* Hot variables for interpretation. Critical for performance,
67487 * but must add sparingly to minimize register shuffling.
67488 */
67489 duk_hthread *thr; /* stable */
67490 duk_tval *consts; /* stable */
67491 duk_tval *consts2; /* stable; precalculated for faster lookups */
67493 /* 'funcs' is quite rarely used, so no local for it */
67494#if defined(DUK_USE_EXEC_FUN_LOCAL)
67496#else
67497 /* 'fun' is quite rarely used, so no local for it */
67498#endif
67499
67500#ifdef DUK_USE_INTERRUPT_COUNTER
67501 duk_int_t int_ctr;
67502#endif
67503
67504#ifdef DUK_USE_ASSERTIONS
67505 duk_size_t valstack_top_base; /* valstack top, should match before interpreting each op (no leftovers) */
67506#endif
67507
67508 /*
67509 * Restart execution by reloading thread state.
67510 *
67511 * Note that 'thr' and any thread configuration may have changed,
67512 * so all local variables are suspect and we need to reinitialize.
67513 *
67514 * The number of local variables should be kept to a minimum: if
67515 * the variables are spilled, they will need to be loaded from
67516 * memory anyway.
67517 *
67518 * Any 'goto restart_execution;' code path in opcode dispatch must
67519 * ensure 'curr_pc' is synced back to act->curr_pc before the goto
67520 * takes place.
67521 *
67522 * The interpreter must be very careful with memory pointers, as
67523 * many pointers are not guaranteed to be 'stable' and may be
67524 * reallocated and relocated on-the-fly quite easily (e.g. by a
67525 * memory allocation or a property access).
67526 *
67527 * The following are assumed to have stable pointers:
67528 * - the current thread
67529 * - the current function
67530 * - the bytecode, constant table, inner function table of the
67531 * current function (as they are a part of the function allocation)
67532 *
67533 * The following are assumed to have semi-stable pointers:
67534 * - the current activation entry: stable as long as callstack
67535 * is not changed (reallocated by growing or shrinking), or
67536 * by any garbage collection invocation (through finalizers)
67537 * - Note in particular that ANY DECREF can invalidate the
67538 * activation pointer, so for the most part a fresh lookup
67539 * is required
67540 *
67541 * The following are not assumed to have stable pointers at all:
67542 * - the value stack (registers) of the current thread
67543 * - the catch stack of the current thread
67544 *
67545 * See execution.rst for discussion.
67546 */
67547
67548 restart_execution:
67549
67550 /* Lookup current thread; use the stable 'entry_thread' for this to
67551 * avoid clobber warnings. Any valid, reachable 'thr' value would be
67552 * fine for this, so using 'entry_thread' is just to silence warnings.
67553 */
67554 thr = entry_thread->heap->curr_thread;
67555 DUK_ASSERT(thr != NULL);
67556 DUK_ASSERT(thr->callstack_top >= 1);
67559
67560 thr->ptr_curr_pc = &curr_pc;
67561
67562 /* Relookup and initialize dispatch loop variables. Debugger check. */
67563 {
67564 duk_activation *act;
67565#if !defined(DUK_USE_EXEC_FUN_LOCAL)
67567#endif
67568
67569 /* Assume interrupt init/counter are properly initialized here. */
67570 /* Assume that thr->valstack_bottom has been set-up before getting here. */
67571
67572 act = thr->callstack + thr->callstack_top - 1;
67574 DUK_ASSERT(fun != NULL);
67575 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
67576 consts = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, fun);
67577 DUK_ASSERT(consts != NULL);
67578 consts2 = consts - DUK_BC_REGLIMIT;
67579
67580#if defined(DUK_USE_DEBUGGER_SUPPORT)
67581 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) && !thr->heap->dbg_processing) {
67582 duk__executor_recheck_debugger(thr, act, fun);
67583 act = thr->callstack + thr->callstack_top - 1; /* relookup after side effects (no side effects currently however) */
67584 }
67585#endif /* DUK_USE_DEBUGGER_SUPPORT */
67586
67587#ifdef DUK_USE_ASSERTIONS
67588 valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
67589#endif
67590
67591 /* Set up curr_pc for opcode dispatch. */
67592 curr_pc = act->curr_pc;
67593 }
67594
67595 DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
67596 "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, catchstack_top=%ld, "
67597 "preventcount=%ld",
67598 (void *) thr,
67599 (long) (thr->callstack_top - 1),
67600 (void *) DUK__FUN(),
67601 (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
67602 (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
67603 (long) (thr->callstack_top - 1),
67604 (long) (thr->valstack_bottom - thr->valstack),
67605 (long) (thr->valstack_top - thr->valstack),
67606 (long) thr->catchstack_top,
67607 (long) thr->callstack_preventcount));
67608
67609 /* Dispatch loop. */
67610
67611 for (;;) {
67612 DUK_ASSERT(thr->callstack_top >= 1);
67613 DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
67614 DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
67615
67616 /* Executor interrupt counter check, used to implement breakpoints,
67617 * debugging interface, execution timeouts, etc. The counter is heap
67618 * specific but is maintained in the current thread to make the check
67619 * as fast as possible. The counter is copied back to the heap struct
67620 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
67621 */
67622#if defined(DUK_USE_INTERRUPT_COUNTER)
67623 int_ctr = thr->interrupt_counter;
67624 if (DUK_LIKELY(int_ctr > 0)) {
67625 thr->interrupt_counter = int_ctr - 1;
67626 } else {
67627 /* Trigger at zero or below */
67628 duk_small_uint_t exec_int_ret;
67629
67630 /* Write curr_pc back for the debugger. */
67631 DUK_ASSERT(thr->callstack_top > 0);
67632 {
67633 duk_activation *act;
67634 act = thr->callstack + thr->callstack_top - 1;
67635 act->curr_pc = (duk_instr_t *) curr_pc;
67636 }
67637
67638 /* Force restart caused by a function return; must recheck
67639 * debugger breakpoints before checking line transitions,
67640 * see GH-303. Restart and then handle interrupt_counter
67641 * zero again.
67642 */
67643#if defined(DUK_USE_DEBUGGER_SUPPORT)
67644 if (thr->heap->dbg_force_restart) {
67645 DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution")); /* GH-303 */
67646 thr->heap->dbg_force_restart = 0;
67647 goto restart_execution;
67648 }
67649#endif
67650
67651 exec_int_ret = duk__executor_interrupt(thr);
67652 if (exec_int_ret == DUK__INT_RESTART) {
67653 /* curr_pc synced back above */
67654 goto restart_execution;
67655 }
67656 }
67657#endif /* DUK_USE_INTERRUPT_COUNTER */
67658#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
67659 /* For cross-checking during development: ensure dispatch count
67660 * matches cumulative interrupt counter init value sums.
67661 */
67662 thr->heap->inst_count_exec++;
67663#endif
67664
67665#if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
67666 {
67667 duk_activation *act;
67668 act = thr->callstack + thr->callstack_top - 1;
67671 DUK_UNREF(act); /* if debugging disabled */
67672
67673 DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld --> %!I",
67674 (long) (curr_pc - DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, DUK__FUN())),
67675 (unsigned long) *curr_pc,
67676 (long) DUK_DEC_OP(*curr_pc),
67677 (long) (thr->valstack_top - thr->valstack),
67678 (long) (thr->valstack_end - thr->valstack),
67679 (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
67680 (duk_instr_t) *curr_pc));
67681 }
67682#endif
67683
67684#if defined(DUK_USE_ASSERTIONS)
67685 /* Quite heavy assert: check valstack policy. Improper
67686 * shuffle instructions can write beyond valstack_top/end
67687 * so this check catches them in the act.
67688 */
67689 {
67690 duk_tval *tv;
67691 tv = thr->valstack_top;
67692 while (tv != thr->valstack_end) {
67694 tv++;
67695 }
67696 }
67697#endif
67698
67699 ins = *curr_pc++;
67700
67701 /* Typing: use duk_small_(u)int_fast_t when decoding small
67702 * opcode fields (op, A, B, C) and duk_(u)int_fast_t when
67703 * decoding larger fields (e.g. BC which is 18 bits). Use
67704 * unsigned variant by default, signed when the value is used
67705 * in signed arithmetic. Using variable names such as 'a', 'b',
67706 * 'c', 'bc', etc makes it easier to spot typing mismatches.
67707 */
67708
67709 /* XXX: the best typing needs to be validated by perf measurement:
67710 * e.g. using a small type which is the cast to a larger duk_idx_t
67711 * may be slower than declaring the variable as a duk_idx_t in the
67712 * first place.
67713 */
67714
67715 /* XXX: use macros for the repetitive tval/refcount handling. */
67716
67717 switch ((int) DUK_DEC_OP(ins)) {
67718 /* XXX: switch cast? */
67719
67720 case DUK_OP_LDREG: {
67722 duk_uint_fast_t bc;
67723 duk_tval *tv1, *tv2;
67724
67725 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67726 bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
67727 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
67728 break;
67729 }
67730
67731 case DUK_OP_STREG: {
67733 duk_uint_fast_t bc;
67734 duk_tval *tv1, *tv2;
67735
67736 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67737 bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
67738 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1); /* side effects */
67739 break;
67740 }
67741
67742 case DUK_OP_LDCONST: {
67744 duk_uint_fast_t bc;
67745 duk_tval *tv1, *tv2;
67746
67747 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67748 bc = DUK_DEC_BC(ins); tv2 = DUK__CONSTP(bc);
67749 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
67750 break;
67751 }
67752
67753 case DUK_OP_LDINT: {
67755 duk_int_fast_t bc;
67756 duk_tval *tv1;
67757#if defined(DUK_USE_FASTINT)
67758 duk_int32_t val;
67759#else
67760 duk_double_t val;
67761#endif
67762
67763#if defined(DUK_USE_FASTINT)
67764 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67765 bc = DUK_DEC_BC(ins); val = (duk_int32_t) (bc - DUK_BC_LDINT_BIAS);
67766 DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv1, val); /* side effects */
67767#else
67768 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67769 bc = DUK_DEC_BC(ins); val = (duk_double_t) (bc - DUK_BC_LDINT_BIAS);
67770 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv1, val); /* side effects */
67771#endif
67772 break;
67773 }
67774
67775 case DUK_OP_LDINTX: {
67777 duk_tval *tv1;
67778 duk_double_t val;
67779
67780 /* LDINTX is not necessarily in FASTINT range, so
67781 * no fast path for now.
67782 *
67783 * XXX: perhaps restrict LDINTX to fastint range, wider
67784 * range very rarely needed.
67785 */
67786
67787 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67789 val = DUK_TVAL_GET_NUMBER(tv1) * ((duk_double_t) (1L << DUK_BC_LDINTX_SHIFT)) +
67790 (duk_double_t) DUK_DEC_BC(ins);
67791#if defined(DUK_USE_FASTINT)
67793#else
67794 DUK_TVAL_SET_NUMBER(tv1, val);
67795#endif
67796 break;
67797 }
67798
67799 case DUK_OP_MPUTOBJ:
67800 case DUK_OP_MPUTOBJI: {
67801 duk_context *ctx = (duk_context *) thr;
67803 duk_tval *tv1;
67804 duk_hobject *obj;
67805 duk_uint_fast_t idx;
67807
67808 /* A -> register of target object
67809 * B -> first register of key/value pair list
67810 * C -> number of key/value pairs
67811 */
67812
67813 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67815 obj = DUK_TVAL_GET_OBJECT(tv1);
67816
67817 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
67818 if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
67819 duk_tval *tv_ind = DUK__REGP(idx);
67821 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67822 }
67823
67824 count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
67825
67826#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67827 if (DUK_UNLIKELY(idx + count * 2 > (duk_uint_fast_t) duk_get_top(ctx))) {
67828 /* XXX: use duk_is_valid_index() instead? */
67829 /* XXX: improve check; check against nregs, not against top */
67830 DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
67831 }
67832#endif
67833
67834 duk_push_hobject(ctx, obj);
67835
67836 while (count > 0) {
67837 /* XXX: faster initialization (direct access or better primitives) */
67838
67839 duk_push_tval(ctx, DUK__REGP(idx));
67840 DUK_ASSERT(duk_is_string(ctx, -1));
67841 duk_push_tval(ctx, DUK__REGP(idx + 1)); /* -> [... obj key value] */
67842 duk_xdef_prop_wec(ctx, -3); /* -> [... obj] */
67843
67844 count--;
67845 idx += 2;
67846 }
67847
67848 duk_pop(ctx); /* [... obj] -> [...] */
67849 break;
67850 }
67851
67852 case DUK_OP_MPUTARR:
67853 case DUK_OP_MPUTARRI: {
67854 duk_context *ctx = (duk_context *) thr;
67856 duk_tval *tv1;
67857 duk_hobject *obj;
67858 duk_uint_fast_t idx;
67860 duk_uint32_t arr_idx;
67861
67862 /* A -> register of target object
67863 * B -> first register of value data (start_index, value1, value2, ..., valueN)
67864 * C -> number of key/value pairs (N)
67865 */
67866
67867 a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67869 obj = DUK_TVAL_GET_OBJECT(tv1);
67870 DUK_ASSERT(obj != NULL);
67871
67872 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
67873 if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
67874 duk_tval *tv_ind = DUK__REGP(idx);
67876 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67877 }
67878
67879 count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
67880
67881#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67882 if (idx + count + 1 > (duk_uint_fast_t) duk_get_top(ctx)) {
67883 /* XXX: use duk_is_valid_index() instead? */
67884 /* XXX: improve check; check against nregs, not against top */
67885 DUK__INTERNAL_ERROR("MPUTARR out of bounds");
67886 }
67887#endif
67888
67889 tv1 = DUK__REGP(idx);
67891 arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
67892 idx++;
67893
67894 duk_push_hobject(ctx, obj);
67895
67896 while (count > 0) {
67897 /* duk_xdef_prop() will define an own property without any array
67898 * special behaviors. We'll need to set the array length explicitly
67899 * in the end. For arrays with elisions, the compiler will emit an
67900 * explicit SETALEN which will update the length.
67901 */
67902
67903 /* XXX: because we're dealing with 'own' properties of a fresh array,
67904 * the array initializer should just ensure that the array has a large
67905 * enough array part and write the values directly into array part,
67906 * and finally set 'length' manually in the end (as already happens now).
67907 */
67908
67909 duk_push_tval(ctx, DUK__REGP(idx)); /* -> [... obj value] */
67910 duk_xdef_prop_index_wec(ctx, -2, arr_idx); /* -> [... obj] */
67911
67912 /* XXX: could use at least one fewer loop counters */
67913 count--;
67914 idx++;
67915 arr_idx++;
67916 }
67917
67918 /* XXX: E5.1 Section 11.1.4 coerces the final length through
67919 * ToUint32() which is odd but happens now as a side effect of
67920 * 'arr_idx' type.
67921 */
67922 duk_hobject_set_length(thr, obj, (duk_uint32_t) arr_idx);
67923
67924 duk_pop(ctx); /* [... obj] -> [...] */
67925 break;
67926 }
67927
67928 case DUK_OP_NEW:
67929 case DUK_OP_NEWI: {
67930 duk_context *ctx = (duk_context *) thr;
67932 duk_uint_fast_t idx;
67934
67935 /* A -> unused (reserved for flags, for consistency with DUK_OP_CALL)
67936 * B -> target register and start reg: constructor, arg1, ..., argN
67937 * (for DUK_OP_NEWI, 'b' is indirect)
67938 * C -> num args (N)
67939 */
67940
67941 /* duk_new() will call the constuctor using duk_handle_call().
67942 * A constructor call prevents a yield from inside the constructor,
67943 * even if the constructor is an Ecmascript function.
67944 */
67945
67946 /* Don't need to sync curr_pc here; duk_new() will do that
67947 * when it augments the created error.
67948 */
67949
67950 /* XXX: unnecessary copying of values? Just set 'top' to
67951 * b + c, and let the return handling fix up the stack frame?
67952 */
67953
67954 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
67955 if (DUK_DEC_OP(ins) == DUK_OP_NEWI) {
67956 duk_tval *tv_ind = DUK__REGP(idx);
67958 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67959 }
67960
67961#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67962 if (idx + c + 1 > (duk_uint_fast_t) duk_get_top(ctx)) {
67963 /* XXX: use duk_is_valid_index() instead? */
67964 /* XXX: improve check; check against nregs, not against top */
67965 DUK__INTERNAL_ERROR("NEW out of bounds");
67966 }
67967#endif
67968
67969 duk_require_stack(ctx, (duk_idx_t) c);
67970 duk_push_tval(ctx, DUK__REGP(idx));
67971 for (i = 0; i < c; i++) {
67972 duk_push_tval(ctx, DUK__REGP(idx + i + 1));
67973 }
67974 duk_new(ctx, (duk_idx_t) c); /* [... constructor arg1 ... argN] -> [retval] */
67975 DUK_DDD(DUK_DDDPRINT("NEW -> %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
67976 duk_replace(ctx, (duk_idx_t) idx);
67977
67978 /* When debugger is enabled, we need to recheck the activation
67979 * status after returning. This is now handled by call handling
67980 * and heap->dbg_force_restart.
67981 */
67982 break;
67983 }
67984
67985 case DUK_OP_REGEXP: {
67986#ifdef DUK_USE_REGEXP_SUPPORT
67987 duk_context *ctx = (duk_context *) thr;
67991
67992 /* A -> target register
67993 * B -> bytecode (also contains flags)
67994 * C -> escaped source
67995 */
67996
67998 duk_push_tval(ctx, DUK__REGCONSTP(b)); /* -> [ ... escaped_source bytecode ] */
67999 duk_regexp_create_instance(thr); /* -> [ ... regexp_instance ] */
68000 DUK_DDD(DUK_DDDPRINT("regexp instance: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
68001 duk_replace(ctx, (duk_idx_t) a);
68002#else
68003 /* The compiler should never emit DUK_OP_REGEXP if there is no
68004 * regexp support.
68005 */
68006 DUK__INTERNAL_ERROR("no regexp support");
68007#endif
68008
68009 break;
68010 }
68011
68012 case DUK_OP_CSREG:
68013 case DUK_OP_CSREGI: {
68014 /*
68015 * Assuming a register binds to a variable declared within this
68016 * function (a declarative binding), the 'this' for the call
68017 * setup is always 'undefined'. E5 Section 10.2.1.1.6.
68018 */
68019
68020 duk_context *ctx = (duk_context *) thr;
68021 duk_small_uint_fast_t b = DUK_DEC_B(ins); /* restricted to regs */
68022 duk_uint_fast_t idx;
68023
68024 /* A -> target register (A, A+1) for call setup
68025 * (for DUK_OP_CSREGI, 'a' is indirect)
68026 * B -> register containing target function (not type checked here)
68027 */
68028
68029 /* XXX: direct manipulation, or duk_replace_tval() */
68030
68031 /* Note: target registers a and a+1 may overlap with DUK__REGP(b).
68032 * Careful here.
68033 */
68034
68035 idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68036 if (DUK_DEC_OP(ins) == DUK_OP_CSREGI) {
68037 duk_tval *tv_ind = DUK__REGP(idx);
68039 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68040 }
68041
68042#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68043 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68044 /* XXX: use duk_is_valid_index() instead? */
68045 /* XXX: improve check; check against nregs, not against top */
68046 DUK__INTERNAL_ERROR("CSREG out of bounds");
68047 }
68048#endif
68049
68050 duk_push_tval(ctx, DUK__REGP(b));
68051 duk_replace(ctx, (duk_idx_t) idx);
68052 duk_push_undefined(ctx);
68053 duk_replace(ctx, (duk_idx_t) (idx + 1));
68054 break;
68055 }
68056
68057 case DUK_OP_GETVAR: {
68058 duk_context *ctx = (duk_context *) thr;
68059 duk_activation *act;
68061 duk_uint_fast_t bc = DUK_DEC_BC(ins);
68062 duk_tval *tv1;
68064
68065 tv1 = DUK__CONSTP(bc);
68068 DUK_ASSERT(name != NULL);
68069 DUK_DDD(DUK_DDDPRINT("GETVAR: '%!O'", (duk_heaphdr *) name));
68070 act = thr->callstack + thr->callstack_top - 1;
68071 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
68072
68073 duk_pop(ctx); /* 'this' binding is not needed here */
68074 duk_replace(ctx, (duk_idx_t) a);
68075 break;
68076 }
68077
68078 case DUK_OP_PUTVAR: {
68079 duk_activation *act;
68081 duk_uint_fast_t bc = DUK_DEC_BC(ins);
68082 duk_tval *tv1;
68084
68085 tv1 = DUK__CONSTP(bc);
68088 DUK_ASSERT(name != NULL);
68089
68090 /* XXX: putvar takes a duk_tval pointer, which is awkward and
68091 * should be reworked.
68092 */
68093
68094 tv1 = DUK__REGP(a); /* val */
68095 act = thr->callstack + thr->callstack_top - 1;
68096 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
68097 break;
68098 }
68099
68100 case DUK_OP_DECLVAR: {
68101 duk_activation *act;
68102 duk_context *ctx = (duk_context *) thr;
68106 duk_tval *tv1;
68108 duk_small_uint_t prop_flags;
68109 duk_bool_t is_func_decl;
68110 duk_bool_t is_undef_value;
68111
68112 tv1 = DUK__REGCONSTP(b);
68115 DUK_ASSERT(name != NULL);
68116
68117 is_undef_value = ((a & DUK_BC_DECLVAR_FLAG_UNDEF_VALUE) != 0);
68118 is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
68119
68120 /* XXX: declvar takes an duk_tval pointer, which is awkward and
68121 * should be reworked.
68122 */
68123
68124 /* Compiler is responsible for selecting property flags (configurability,
68125 * writability, etc).
68126 */
68127 prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
68128
68129 if (is_undef_value) {
68130 duk_push_undefined(ctx);
68131 } else {
68133 }
68134 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
68135
68136 act = thr->callstack + thr->callstack_top - 1;
68137 if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
68138 /* already declared, must update binding value */
68139 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
68140 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
68141 }
68142
68143 duk_pop(ctx);
68144 break;
68145 }
68146
68147 case DUK_OP_DELVAR: {
68148 duk_activation *act;
68149 duk_context *ctx = (duk_context *) thr;
68152 duk_tval *tv1;
68154 duk_bool_t rc;
68155
68156 tv1 = DUK__REGCONSTP(b);
68159 DUK_ASSERT(name != NULL);
68160 DUK_DDD(DUK_DDDPRINT("DELVAR '%!O'", (duk_heaphdr *) name));
68161 act = thr->callstack + thr->callstack_top - 1;
68162 rc = duk_js_delvar_activation(thr, act, name);
68163
68164 duk_push_boolean(ctx, rc);
68165 duk_replace(ctx, (duk_idx_t) a);
68166 break;
68167 }
68168
68169 case DUK_OP_CSVAR:
68170 case DUK_OP_CSVARI: {
68171 /* 'this' value:
68172 * E5 Section 6.b.i
68173 *
68174 * The only (standard) case where the 'this' binding is non-null is when
68175 * (1) the variable is found in an object environment record, and
68176 * (2) that object environment record is a 'with' block.
68177 *
68178 */
68179
68180 duk_context *ctx = (duk_context *) thr;
68181 duk_activation *act;
68183 duk_uint_fast_t idx;
68184 duk_tval *tv1;
68186
68187 tv1 = DUK__REGCONSTP(b);
68190 DUK_ASSERT(name != NULL);
68191 act = thr->callstack + thr->callstack_top - 1;
68192 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
68193
68194 /* Note: target registers a and a+1 may overlap with DUK__REGCONSTP(b)
68195 * and DUK__REGCONSTP(c). Careful here.
68196 */
68197
68198 idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68199 if (DUK_DEC_OP(ins) == DUK_OP_CSVARI) {
68200 duk_tval *tv_ind = DUK__REGP(idx);
68202 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68203 }
68204
68205#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68206 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68207 /* XXX: use duk_is_valid_index() instead? */
68208 /* XXX: improve check; check against nregs, not against top */
68209 DUK__INTERNAL_ERROR("CSVAR out of bounds");
68210 }
68211#endif
68212
68213 duk_replace(ctx, (duk_idx_t) (idx + 1)); /* 'this' binding */
68214 duk_replace(ctx, (duk_idx_t) idx); /* variable value (function, we hope, not checked here) */
68215 break;
68216 }
68217
68218 case DUK_OP_CLOSURE: {
68219 duk_context *ctx = (duk_context *) thr;
68220 duk_activation *act;
68223 duk_uint_fast_t bc = DUK_DEC_BC(ins);
68224 duk_hobject *fun_temp;
68225
68226 /* A -> target reg
68227 * BC -> inner function index
68228 */
68229
68230 DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
68231 (long) a, (long) bc, (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
68232
68233 DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
68235
68236 act = thr->callstack + thr->callstack_top - 1;
68238 fun_temp = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, fun)[bc];
68239 DUK_ASSERT(fun_temp != NULL);
68241
68242 DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
68243 (void *) fun_temp, (duk_heaphdr *) fun_temp));
68244
68245 if (act->lex_env == NULL) {
68246 DUK_ASSERT(act->var_env == NULL);
68248 }
68249 DUK_ASSERT(act->lex_env != NULL);
68250 DUK_ASSERT(act->var_env != NULL);
68251
68252 /* functions always have a NEWENV flag, i.e. they get a
68253 * new variable declaration environment, so only lex_env
68254 * matters here.
68255 */
68257 (duk_hcompiledfunction *) fun_temp,
68258 act->var_env,
68259 act->lex_env,
68260 1 /*add_auto_proto*/);
68261 duk_replace(ctx, (duk_idx_t) a);
68262
68263 break;
68264 }
68265
68266 case DUK_OP_GETPROP: {
68267 duk_context *ctx = (duk_context *) thr;
68271 duk_tval *tv_obj;
68272 duk_tval *tv_key;
68273 duk_bool_t rc;
68274
68275 /* A -> target reg
68276 * B -> object reg/const (may be const e.g. in "'foo'[1]")
68277 * C -> key reg/const
68278 */
68279
68280 tv_obj = DUK__REGCONSTP(b);
68281 tv_key = DUK__REGCONSTP(c);
68282 DUK_DDD(DUK_DDDPRINT("GETPROP: a=%ld obj=%!T, key=%!T",
68283 (long) a,
68284 (duk_tval *) DUK__REGCONSTP(b),
68285 (duk_tval *) DUK__REGCONSTP(c)));
68286 rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
68287 DUK_UNREF(rc); /* ignore */
68288 DUK_DDD(DUK_DDDPRINT("GETPROP --> %!T",
68289 (duk_tval *) duk_get_tval(ctx, -1)));
68290 tv_obj = NULL; /* invalidated */
68291 tv_key = NULL; /* invalidated */
68292
68293 duk_replace(ctx, (duk_idx_t) a); /* val */
68294 break;
68295 }
68296
68297 case DUK_OP_PUTPROP: {
68301 duk_tval *tv_obj;
68302 duk_tval *tv_key;
68303 duk_tval *tv_val;
68304 duk_bool_t rc;
68305
68306 /* A -> object reg
68307 * B -> key reg/const
68308 * C -> value reg/const
68309 *
68310 * Note: intentional difference to register arrangement
68311 * of e.g. GETPROP; 'A' must contain a register-only value.
68312 */
68313
68314 tv_obj = DUK__REGP(a);
68315 tv_key = DUK__REGCONSTP(b);
68316 tv_val = DUK__REGCONSTP(c);
68317 DUK_DDD(DUK_DDDPRINT("PUTPROP: obj=%!T, key=%!T, val=%!T",
68318 (duk_tval *) DUK__REGP(a),
68319 (duk_tval *) DUK__REGCONSTP(b),
68320 (duk_tval *) DUK__REGCONSTP(c)));
68321 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
68322 DUK_UNREF(rc); /* ignore */
68323 DUK_DDD(DUK_DDDPRINT("PUTPROP --> obj=%!T, key=%!T, val=%!T",
68324 (duk_tval *) DUK__REGP(a),
68325 (duk_tval *) DUK__REGCONSTP(b),
68326 (duk_tval *) DUK__REGCONSTP(c)));
68327 tv_obj = NULL; /* invalidated */
68328 tv_key = NULL; /* invalidated */
68329 tv_val = NULL; /* invalidated */
68330
68331 break;
68332 }
68333
68334 case DUK_OP_DELPROP: {
68335 duk_context *ctx = (duk_context *) thr;
68339 duk_tval *tv_obj;
68340 duk_tval *tv_key;
68341 duk_bool_t rc;
68342
68343 /* A -> result reg
68344 * B -> object reg
68345 * C -> key reg/const
68346 */
68347
68348 tv_obj = DUK__REGP(b);
68349 tv_key = DUK__REGCONSTP(c);
68350 rc = duk_hobject_delprop(thr, tv_obj, tv_key, DUK__STRICT());
68351 tv_obj = NULL; /* invalidated */
68352 tv_key = NULL; /* invalidated */
68353
68354 duk_push_boolean(ctx, rc);
68355 duk_replace(ctx, (duk_idx_t) a); /* result */
68356 break;
68357 }
68358
68359 case DUK_OP_CSPROP:
68360 case DUK_OP_CSPROPI: {
68361 duk_context *ctx = (duk_context *) thr;
68364 duk_uint_fast_t idx;
68365 duk_tval *tv_obj;
68366 duk_tval *tv_key;
68367 duk_bool_t rc;
68368
68369 /* E5 Section 11.2.3, step 6.a.i */
68370 /* E5 Section 10.4.3 */
68371
68372 /* XXX: allow object to be a const, e.g. in 'foo'.toString()?
68373 * On the other hand, DUK_REGCONSTP() is slower and generates
68374 * more code.
68375 */
68376
68377 tv_obj = DUK__REGP(b);
68378 tv_key = DUK__REGCONSTP(c);
68379 rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
68380 DUK_UNREF(rc); /* unused */
68381 tv_obj = NULL; /* invalidated */
68382 tv_key = NULL; /* invalidated */
68383
68384 /* Note: target registers a and a+1 may overlap with DUK__REGP(b)
68385 * and DUK__REGCONSTP(c). Careful here.
68386 */
68387
68388 idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68389 if (DUK_DEC_OP(ins) == DUK_OP_CSPROPI) {
68390 duk_tval *tv_ind = DUK__REGP(idx);
68392 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68393 }
68394
68395#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68396 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68397 /* XXX: use duk_is_valid_index() instead? */
68398 /* XXX: improve check; check against nregs, not against top */
68399 DUK__INTERNAL_ERROR("CSPROP out of bounds");
68400 }
68401#endif
68402
68403 duk_push_tval(ctx, DUK__REGP(b)); /* [ ... val obj ] */
68404 duk_replace(ctx, (duk_idx_t) (idx + 1)); /* 'this' binding */
68405 duk_replace(ctx, (duk_idx_t) idx); /* val */
68406 break;
68407 }
68408
68409 case DUK_OP_ADD:
68410 case DUK_OP_SUB:
68411 case DUK_OP_MUL:
68412 case DUK_OP_DIV:
68413 case DUK_OP_MOD: {
68418
68419 if (op == DUK_OP_ADD) {
68420 /*
68421 * Handling DUK_OP_ADD this way is more compact (experimentally)
68422 * than a separate case with separate argument decoding.
68423 */
68425 } else {
68427 }
68428 break;
68429 }
68430
68431 case DUK_OP_BAND:
68432 case DUK_OP_BOR:
68433 case DUK_OP_BXOR:
68434 case DUK_OP_BASL:
68435 case DUK_OP_BLSR:
68436 case DUK_OP_BASR: {
68441
68443 break;
68444 }
68445
68446 case DUK_OP_EQ:
68447 case DUK_OP_NEQ: {
68448 duk_context *ctx = (duk_context *) thr;
68452 duk_bool_t tmp;
68453
68454 /* E5 Sections 11.9.1, 11.9.3 */
68455 tmp = duk_js_equals(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c));
68456 if (DUK_DEC_OP(ins) == DUK_OP_NEQ) {
68457 tmp = !tmp;
68458 }
68459 duk_push_boolean(ctx, tmp);
68460 duk_replace(ctx, (duk_idx_t) a);
68461 break;
68462 }
68463
68464 case DUK_OP_SEQ:
68465 case DUK_OP_SNEQ: {
68466 duk_context *ctx = (duk_context *) thr;
68470 duk_bool_t tmp;
68471
68472 /* E5 Sections 11.9.1, 11.9.3 */
68474 if (DUK_DEC_OP(ins) == DUK_OP_SNEQ) {
68475 tmp = !tmp;
68476 }
68477 duk_push_boolean(ctx, tmp);
68478 duk_replace(ctx, (duk_idx_t) a);
68479 break;
68480 }
68481
68482 /* Note: combining comparison ops must be done carefully because
68483 * of uncomparable values (NaN): it's not necessarily true that
68484 * (x >= y) === !(x < y). Also, evaluation order matters, and
68485 * although it would only seem to affect the compiler this is
68486 * actually not the case, because there are also run-time coercions
68487 * of the arguments (with potential side effects).
68488 *
68489 * XXX: can be combined; check code size.
68490 */
68491
68492 case DUK_OP_GT: {
68493 duk_context *ctx = (duk_context *) thr;
68497 duk_bool_t tmp;
68498
68499 /* x > y --> y < x */
68500 tmp = duk_js_compare_helper(thr,
68501 DUK__REGCONSTP(c), /* y */
68502 DUK__REGCONSTP(b), /* x */
68503 0); /* flags */
68504
68505 duk_push_boolean(ctx, tmp);
68506 duk_replace(ctx, (duk_idx_t) a);
68507 break;
68508 }
68509
68510 case DUK_OP_GE: {
68511 duk_context *ctx = (duk_context *) thr;
68515 duk_bool_t tmp;
68516
68517 /* x >= y --> not (x < y) */
68518 tmp = duk_js_compare_helper(thr,
68519 DUK__REGCONSTP(b), /* x */
68520 DUK__REGCONSTP(c), /* y */
68522 DUK_COMPARE_FLAG_NEGATE); /* flags */
68523
68524 duk_push_boolean(ctx, tmp);
68525 duk_replace(ctx, (duk_idx_t) a);
68526 break;
68527 }
68528
68529 case DUK_OP_LT: {
68530 duk_context *ctx = (duk_context *) thr;
68534 duk_bool_t tmp;
68535
68536 /* x < y */
68537 tmp = duk_js_compare_helper(thr,
68538 DUK__REGCONSTP(b), /* x */
68539 DUK__REGCONSTP(c), /* y */
68541
68542 duk_push_boolean(ctx, tmp);
68543 duk_replace(ctx, (duk_idx_t) a);
68544 break;
68545 }
68546
68547 case DUK_OP_LE: {
68548 duk_context *ctx = (duk_context *) thr;
68552 duk_bool_t tmp;
68553
68554 /* x <= y --> not (x > y) --> not (y < x) */
68555 tmp = duk_js_compare_helper(thr,
68556 DUK__REGCONSTP(c), /* y */
68557 DUK__REGCONSTP(b), /* x */
68558 DUK_COMPARE_FLAG_NEGATE); /* flags */
68559
68560 duk_push_boolean(ctx, tmp);
68561 duk_replace(ctx, (duk_idx_t) a);
68562 break;
68563 }
68564
68565 case DUK_OP_IF: {
68568 duk_bool_t tmp;
68569
68571 if (tmp == (duk_bool_t) a) {
68572 /* if boolean matches A, skip next inst */
68573 curr_pc++;
68574 } else {
68575 ;
68576 }
68577 break;
68578 }
68579
68580 case DUK_OP_JUMP: {
68581 duk_int_fast_t abc = DUK_DEC_ABC(ins);
68582
68583 curr_pc += abc - DUK_BC_JUMP_BIAS;
68584 break;
68585 }
68586
68587 case DUK_OP_RETURN: {
68588 duk_context *ctx = (duk_context *) thr;
68591 /* duk_small_uint_fast_t c = DUK_DEC_C(ins); */
68592 duk_small_uint_t ret_result;
68593
68594 /* A -> flags
68595 * B -> return value reg/const
68596 * C -> currently unused
68597 */
68598
68600
68601 /* duk__handle_return() is guaranteed never to throw, except
68602 * for potential out-of-memory situations which will then
68603 * propagate out of the executor longjmp handler.
68604 */
68605
68608 } else {
68609 duk_push_undefined(ctx);
68610 }
68611 ret_result = duk__handle_return(thr,
68612 entry_thread,
68613 entry_callstack_top);
68614 if (ret_result == DUK__RETHAND_RESTART) {
68615 goto restart_execution;
68616 }
68617 DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
68618
68619 DUK_DDD(DUK_DDDPRINT("exiting executor after RETURN handling"));
68620 return;
68621 }
68622
68623 case DUK_OP_CALL:
68624 case DUK_OP_CALLI: {
68625 duk_context *ctx = (duk_context *) thr;
68628 duk_uint_fast_t idx;
68629 duk_small_uint_t call_flags;
68630 duk_small_uint_t flag_tailcall;
68631 duk_small_uint_t flag_evalcall;
68632 duk_tval *tv_func;
68633 duk_hobject *obj_func;
68634 duk_bool_t setup_rc;
68635 duk_idx_t num_stack_args;
68636#if !defined(DUK_USE_EXEC_FUN_LOCAL)
68638#endif
68639
68640 /* A -> flags
68641 * B -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
68642 * (for DUK_OP_CALLI, 'b' is indirect)
68643 * C -> nargs
68644 */
68645
68646 /* these are not necessarily 0 or 1 (may be other non-zero), that's ok */
68647 flag_tailcall = (a & DUK_BC_CALL_FLAG_TAILCALL);
68648 flag_evalcall = (a & DUK_BC_CALL_FLAG_EVALCALL);
68649
68650 idx = (duk_uint_fast_t) DUK_DEC_B(ins);
68651 if (DUK_DEC_OP(ins) == DUK_OP_CALLI) {
68652 duk_tval *tv_ind = DUK__REGP(idx);
68654 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68655 }
68656
68657#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68658 if (!duk_is_valid_index(ctx, (duk_idx_t) idx)) {
68659 /* XXX: improve check; check against nregs, not against top */
68660 DUK__INTERNAL_ERROR("CALL out of bounds");
68661 }
68662#endif
68663
68664 /*
68665 * To determine whether to use an optimized Ecmascript-to-Ecmascript
68666 * call, we need to know whether the final, non-bound function is an
68667 * Ecmascript function.
68668 *
68669 * This is now implemented so that we start to do an ecma-to-ecma call
68670 * setup which will resolve the bound chain as the first thing. If the
68671 * final function is not eligible, the return value indicates that the
68672 * ecma-to-ecma call is not possible. The setup will overwrite the call
68673 * target at DUK__REGP(idx) with the final, non-bound function (which
68674 * may be a lightfunc), and fudge arguments if necessary.
68675 *
68676 * XXX: If an ecma-to-ecma call is not possible, this initial call
68677 * setup will do bound function chain resolution but won't do the
68678 * "effective this binding" resolution which is quite confusing.
68679 * Perhaps add a helper for doing bound function and effective this
68680 * binding resolution - and call that explicitly? Ecma-to-ecma call
68681 * setup and normal function handling can then assume this prestep has
68682 * been done by the caller.
68683 */
68684
68685 duk_set_top(ctx, (duk_idx_t) (idx + c + 2)); /* [ ... func this arg1 ... argN ] */
68686
68687 call_flags = 0;
68688 if (flag_tailcall) {
68689 /* We request a tail call, but in some corner cases
68690 * call handling can decide that a tail call is
68691 * actually not possible.
68692 * See: test-bug-tailcall-preventyield-assert.c.
68693 */
68694 call_flags |= DUK_CALL_FLAG_IS_TAILCALL;
68695 }
68696
68697 /* Compared to duk_handle_call():
68698 * - protected call: never
68699 * - ignore recursion limit: never
68700 */
68701 num_stack_args = c;
68702 setup_rc = duk_handle_ecma_call_setup(thr,
68703 num_stack_args,
68704 call_flags);
68705
68706 if (setup_rc) {
68707 /* Ecma-to-ecma call possible, may or may not be a tail call.
68708 * Avoid C recursion by being clever.
68709 */
68710 DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
68711 /* curr_pc synced by duk_handle_ecma_call_setup() */
68712 goto restart_execution;
68713 }
68714 DUK_ASSERT(thr->ptr_curr_pc != NULL); /* restored if ecma-to-ecma setup fails */
68715
68716 DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call not possible, target is native (may be lightfunc)"));
68717
68718 /* Recompute argument count: bound function handling may have shifted. */
68719 num_stack_args = duk_get_top(ctx) - (idx + 2);
68720 DUK_DDD(DUK_DDDPRINT("recomputed arg count: %ld\n", (long) num_stack_args));
68721
68722 tv_func = DUK__REGP(idx); /* Relookup if relocated */
68723 if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
68724
68725 call_flags = 0; /* not protected, respect reclimit, not constructor */
68726
68727 /* There is no eval() special handling here: eval() is never
68728 * automatically converted to a lightfunc.
68729 */
68731
68733 num_stack_args,
68734 call_flags);
68735
68736 /* duk_js_call.c is required to restore the stack reserve
68737 * so we only need to reset the top.
68738 */
68739#if !defined(DUK_USE_EXEC_FUN_LOCAL)
68740 fun = DUK__FUN();
68741#endif
68742 duk_set_top(ctx, (duk_idx_t) fun->nregs);
68743
68744 /* No need to reinit setjmp() catchpoint, as call handling
68745 * will store and restore our state.
68746 */
68747 } else {
68748 /* Call setup checks callability. */
68750 obj_func = DUK_TVAL_GET_OBJECT(tv_func);
68751 DUK_ASSERT(obj_func != NULL);
68753
68754 /*
68755 * Other cases, use C recursion.
68756 *
68757 * If a tail call was requested we ignore it and execute a normal call.
68758 * Since Duktape 0.11.0 the compiler emits a RETURN opcode even after
68759 * a tail call to avoid test-bug-tailcall-thread-yield-resume.js.
68760 *
68761 * Direct eval call: (1) call target (before following bound function
68762 * chain) is the built-in eval() function, and (2) call was made with
68763 * the identifier 'eval'.
68764 */
68765
68766 call_flags = 0; /* not protected, respect reclimit, not constructor */
68767
68768 if (DUK_HOBJECT_IS_NATIVEFUNCTION(obj_func) &&
68769 ((duk_hnativefunction *) obj_func)->func == duk_bi_global_object_eval) {
68770 if (flag_evalcall) {
68771 DUK_DDD(DUK_DDDPRINT("call target is eval, call identifier was 'eval' -> direct eval"));
68772 call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
68773 } else {
68774 DUK_DDD(DUK_DDDPRINT("call target is eval, call identifier was not 'eval' -> indirect eval"));
68775 }
68776 }
68777
68779 num_stack_args,
68780 call_flags);
68781
68782 /* duk_js_call.c is required to restore the stack reserve
68783 * so we only need to reset the top.
68784 */
68785#if !defined(DUK_USE_EXEC_FUN_LOCAL)
68786 fun = DUK__FUN();
68787#endif
68788 duk_set_top(ctx, (duk_idx_t) fun->nregs);
68789
68790 /* No need to reinit setjmp() catchpoint, as call handling
68791 * will store and restore our state.
68792 */
68793 }
68794
68795 /* When debugger is enabled, we need to recheck the activation
68796 * status after returning. This is now handled by call handling
68797 * and heap->dbg_force_restart.
68798 */
68799 break;
68800 }
68801
68802 case DUK_OP_TRYCATCH: {
68803 duk_context *ctx = (duk_context *) thr;
68804 duk_activation *act;
68805 duk_catcher *cat;
68806 duk_tval *tv1;
68808 duk_uint_fast_t bc;
68809
68810 /* A -> flags
68811 * BC -> reg_catch; base register for two registers used both during
68812 * trycatch setup and when catch is triggered
68813 *
68814 * If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
68815 * reg_catch + 0: catch binding variable name (string).
68816 * Automatic declarative environment is established for
68817 * the duration of the 'catch' clause.
68818 *
68819 * If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
68820 * reg_catch + 0: with 'target value', which is coerced to
68821 * an object and then used as a bindind object for an
68822 * environment record. The binding is initialized here, for
68823 * the 'try' clause.
68824 *
68825 * Note that a TRYCATCH generated for a 'with' statement has no
68826 * catch or finally parts.
68827 */
68828
68829 /* XXX: TRYCATCH handling should be reworked to avoid creating
68830 * an explicit scope unless it is actually needed (e.g. function
68831 * instances or eval is executed inside the catch block). This
68832 * rework is not trivial because the compiler doesn't have an
68833 * intermediate representation. When the rework is done, the
68834 * opcode format can also be made more straightforward.
68835 */
68836
68837 /* XXX: side effect handling is quite awkward here */
68838
68839 DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
68840 "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
68841 (long) DUK_DEC_BC(ins),
68842 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
68843 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
68844 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
68845 (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
68846 (unsigned long) DUK_DEC_A(ins)));
68847
68848 a = DUK_DEC_A(ins);
68849 bc = DUK_DEC_BC(ins);
68850
68851 act = thr->callstack + thr->callstack_top - 1;
68852 DUK_ASSERT(thr->callstack_top >= 1);
68853
68854 /* 'with' target must be created first, in case we run out of memory */
68855 /* XXX: refactor out? */
68856
68858 DUK_DDD(DUK_DDDPRINT("need to initialize a with binding object"));
68859
68860 if (act->lex_env == NULL) {
68861 DUK_ASSERT(act->var_env == NULL);
68862 DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
68863
68864 /* must relookup act in case of side effects */
68866 act = thr->callstack + thr->callstack_top - 1;
68867 DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
68868 }
68869 DUK_ASSERT(act->lex_env != NULL);
68870 DUK_ASSERT(act->var_env != NULL);
68871
68872 (void) duk_push_object_helper(ctx,
68875 -1); /* no prototype, updated below */
68876
68877 duk_push_tval(ctx, DUK__REGP(bc));
68878 duk_to_object(ctx, -1);
68879 duk_dup(ctx, -1);
68880
68881 /* [ ... env target ] */
68882 /* [ ... env target target ] */
68883
68885 duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); /* always provideThis=true */
68886
68887 /* [ ... env ] */
68888
68889 DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iT",
68890 (duk_tval *) duk_get_tval(ctx, -1)));
68891 }
68892
68893 /* allocate catcher and populate it (should be atomic) */
68894
68896 cat = thr->catchstack + thr->catchstack_top;
68897 DUK_ASSERT(thr->catchstack_top + 1 <= thr->catchstack_size);
68898 thr->catchstack_top++;
68899
68900 cat->flags = DUK_CAT_TYPE_TCF;
68901 cat->h_varname = NULL;
68902
68905 }
68908 }
68910 DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
68912 tv1 = DUK__REGP(bc);
68914
68915 /* borrowed reference; although 'tv1' comes from a register,
68916 * its value was loaded using LDCONST so the constant will
68917 * also exist and be reachable.
68918 */
68919 cat->h_varname = DUK_TVAL_GET_STRING(tv1);
68920 } else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
68921 /* env created above to stack top */
68922 duk_hobject *new_env;
68923
68924 DUK_DDD(DUK_DDDPRINT("lexenv active flag set to catcher"));
68926
68927 DUK_DDD(DUK_DDDPRINT("activating object env: %!iT",
68928 (duk_tval *) duk_get_tval(ctx, -1)));
68929 DUK_ASSERT(act->lex_env != NULL);
68930 new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
68931 DUK_ASSERT(new_env != NULL);
68932
68933 act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
68934 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env); /* side effects */
68935
68936 act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
68937 act->lex_env = new_env;
68938 DUK_HOBJECT_INCREF(thr, new_env);
68939 duk_pop(ctx);
68940 } else {
68941 ;
68942 }
68943
68944 /* Registers 'bc' and 'bc + 1' are written in longjmp handling
68945 * and if their previous values (which are temporaries) become
68946 * unreachable -and- have a finalizer, there'll be a function
68947 * call during error handling which is not supported now (GH-287).
68948 * Ensure that both 'bc' and 'bc + 1' have primitive values to
68949 * guarantee no finalizer calls in error handling. Scrubbing also
68950 * ensures finalizers for the previous values run here rather than
68951 * later. Error handling related values are also written to 'bc'
68952 * and 'bc + 1' but those values never become unreachable during
68953 * error handling, so there's no side effect problem even if the
68954 * error value has a finalizer.
68955 */
68956 duk_to_undefined(ctx, bc);
68957 duk_to_undefined(ctx, bc + 1);
68958
68959 cat = thr->catchstack + thr->catchstack_top - 1; /* relookup (side effects) */
68960 cat->callstack_index = thr->callstack_top - 1;
68961 cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
68962 cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
68963
68964 DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
68965 "idx_base=%ld, h_varname=%!O",
68966 (unsigned long) cat->flags, (long) cat->callstack_index,
68967 (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
68968
68969 curr_pc += 2; /* skip jump slots */
68970 break;
68971 }
68972
68973 /* Pre/post inc/dec for register variables, important for loops. */
68974 case DUK_OP_PREINCR:
68975 case DUK_OP_PREDECR:
68976 case DUK_OP_POSTINCR:
68977 case DUK_OP_POSTDECR: {
68978 duk_context *ctx = (duk_context *) thr;
68980 duk_uint_fast_t bc = DUK_DEC_BC(ins);
68981 duk_tval *tv1, *tv2;
68982 duk_double_t x, y, z;
68983
68984 /* Two lowest bits of opcode are used to distinguish
68985 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
68986 */
68987 DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
68988 DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
68989 DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
68990 DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
68991
68992 tv1 = DUK__REGP(bc);
68993#if defined(DUK_USE_FASTINT)
68994 if (DUK_TVAL_IS_FASTINT(tv1)) {
68995 duk_int64_t x_fi, y_fi, z_fi;
68996 x_fi = DUK_TVAL_GET_FASTINT(tv1);
68997 if (ins & DUK_ENC_OP(0x01)) {
68998 if (x_fi == DUK_FASTINT_MIN) {
68999 goto skip_fastint;
69000 }
69001 y_fi = x_fi - 1;
69002 } else {
69003 if (x_fi == DUK_FASTINT_MAX) {
69004 goto skip_fastint;
69005 }
69006 y_fi = x_fi + 1;
69007 }
69008
69009 DUK_TVAL_SET_FASTINT(tv1, y_fi); /* no need for refcount update */
69010
69011 tv2 = DUK__REGP(a);
69012 z_fi = (ins & DUK_ENC_OP(0x02)) ? x_fi : y_fi;
69013 DUK_TVAL_SET_FASTINT_UPDREF(thr, tv2, z_fi); /* side effects */
69014 break;
69015 }
69016 skip_fastint:
69017#endif
69018 if (DUK_TVAL_IS_NUMBER(tv1)) {
69019 /* Fast path for the case where the register
69020 * is a number (e.g. loop counter).
69021 */
69022
69023 x = DUK_TVAL_GET_NUMBER(tv1);
69024 if (ins & DUK_ENC_OP(0x01)) {
69025 y = x - 1.0;
69026 } else {
69027 y = x + 1.0;
69028 }
69029
69030 DUK_TVAL_SET_NUMBER(tv1, y); /* no need for refcount update */
69031 } else {
69032 x = duk_to_number(ctx, bc);
69033
69034 if (ins & DUK_ENC_OP(0x01)) {
69035 y = x - 1.0;
69036 } else {
69037 y = x + 1.0;
69038 }
69039
69040 duk_push_number(ctx, y);
69041 duk_replace(ctx, bc);
69042 }
69043
69044 tv2 = DUK__REGP(a);
69045 z = (ins & DUK_ENC_OP(0x02)) ? x : y;
69046 DUK_TVAL_SET_NUMBER_UPDREF(thr, tv2, z); /* side effects */
69047 break;
69048 }
69049
69050 /* Preinc/predec for var-by-name, slow path. */
69051 case DUK_OP_PREINCV:
69052 case DUK_OP_PREDECV:
69053 case DUK_OP_POSTINCV:
69054 case DUK_OP_POSTDECV: {
69055 duk_context *ctx = (duk_context *) thr;
69056 duk_activation *act;
69058 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69059 duk_double_t x, y;
69060 duk_tval *tv1;
69062
69063 /* Two lowest bits of opcode are used to distinguish
69064 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69065 */
69066 DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
69067 DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
69068 DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
69069 DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
69070
69071 tv1 = DUK__CONSTP(bc);
69074 DUK_ASSERT(name != NULL);
69075 act = thr->callstack + thr->callstack_top - 1;
69076 (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
69077
69078 /* XXX: fastint fast path would be very useful here */
69079
69080 x = duk_to_number(ctx, -2);
69081 duk_pop_2(ctx);
69082 if (ins & DUK_ENC_OP(0x01)) {
69083 y = x - 1.0;
69084 } else {
69085 y = x + 1.0;
69086 }
69087
69088 duk_push_number(ctx, y);
69089 tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
69090 DUK_ASSERT(tv1 != NULL);
69091 duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
69092 duk_pop(ctx);
69093
69094 duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
69095 duk_replace(ctx, (duk_idx_t) a);
69096 break;
69097 }
69098
69099 /* Preinc/predec for object properties. */
69100 case DUK_OP_PREINCP:
69101 case DUK_OP_PREDECP:
69102 case DUK_OP_POSTINCP:
69103 case DUK_OP_POSTDECP: {
69104 duk_context *ctx = (duk_context *) thr;
69108 duk_tval *tv_obj;
69109 duk_tval *tv_key;
69110 duk_tval *tv_val;
69111 duk_bool_t rc;
69112 duk_double_t x, y;
69113
69114 /* A -> target reg
69115 * B -> object reg/const (may be const e.g. in "'foo'[1]")
69116 * C -> key reg/const
69117 */
69118
69119 /* Two lowest bits of opcode are used to distinguish
69120 * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69121 */
69122 DUK_ASSERT((DUK_OP_PREINCP & 0x03) == 0x00);
69123 DUK_ASSERT((DUK_OP_PREDECP & 0x03) == 0x01);
69124 DUK_ASSERT((DUK_OP_POSTINCP & 0x03) == 0x02);
69125 DUK_ASSERT((DUK_OP_POSTDECP & 0x03) == 0x03);
69126
69127 tv_obj = DUK__REGCONSTP(b);
69128 tv_key = DUK__REGCONSTP(c);
69129 rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
69130 DUK_UNREF(rc); /* ignore */
69131 tv_obj = NULL; /* invalidated */
69132 tv_key = NULL; /* invalidated */
69133
69134 x = duk_to_number(ctx, -1);
69135 duk_pop(ctx);
69136 if (ins & DUK_ENC_OP(0x01)) {
69137 y = x - 1.0;
69138 } else {
69139 y = x + 1.0;
69140 }
69141
69142 duk_push_number(ctx, y);
69143 tv_val = DUK_GET_TVAL_NEGIDX(ctx, -1);
69144 DUK_ASSERT(tv_val != NULL);
69145 tv_obj = DUK__REGCONSTP(b);
69146 tv_key = DUK__REGCONSTP(c);
69147 rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
69148 DUK_UNREF(rc); /* ignore */
69149 tv_obj = NULL; /* invalidated */
69150 tv_key = NULL; /* invalidated */
69151 duk_pop(ctx);
69152
69153 duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
69154 duk_replace(ctx, (duk_idx_t) a);
69155 break;
69156 }
69157
69158 case DUK_OP_EXTRA: {
69159 /* XXX: shared decoding of 'b' and 'c'? */
69160
69161 duk_small_uint_fast_t extraop = DUK_DEC_A(ins);
69162 switch ((int) extraop) {
69163 /* XXX: switch cast? */
69164
69165 case DUK_EXTRAOP_NOP: {
69166 /* nop */
69167 break;
69168 }
69169
69170 case DUK_EXTRAOP_INVALID: {
69171 DUK_ERROR_FMT1(thr, DUK_ERR_INTERNAL_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_BC(ins));
69172 break;
69173 }
69174
69175 case DUK_EXTRAOP_LDTHIS: {
69176 /* Note: 'this' may be bound to any value, not just an object */
69177 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69178 duk_tval *tv1, *tv2;
69179
69180 tv1 = DUK__REGP(bc);
69181 tv2 = thr->valstack_bottom - 1; /* 'this binding' is just under bottom */
69182 DUK_ASSERT(tv2 >= thr->valstack);
69183
69184 DUK_DDD(DUK_DDDPRINT("LDTHIS: %!T to r%ld", (duk_tval *) tv2, (long) bc));
69185
69186 DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
69187 break;
69188 }
69189
69190 case DUK_EXTRAOP_LDUNDEF: {
69191 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69192 duk_tval *tv1;
69193
69194 tv1 = DUK__REGP(bc);
69195 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
69196 break;
69197 }
69198
69199 case DUK_EXTRAOP_LDNULL: {
69200 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69201 duk_tval *tv1;
69202
69203 tv1 = DUK__REGP(bc);
69204 DUK_TVAL_SET_NULL_UPDREF(thr, tv1); /* side effects */
69205 break;
69206 }
69207
69208 case DUK_EXTRAOP_LDTRUE:
69209 case DUK_EXTRAOP_LDFALSE: {
69210 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69211 duk_tval *tv1;
69212 duk_small_uint_fast_t bval = (extraop == DUK_EXTRAOP_LDTRUE ? 1 : 0);
69213
69214 tv1 = DUK__REGP(bc);
69215 DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, bval); /* side effects */
69216 break;
69217 }
69218
69219 case DUK_EXTRAOP_NEWOBJ: {
69220 duk_context *ctx = (duk_context *) thr;
69222
69223 duk_push_object(ctx);
69224 duk_replace(ctx, (duk_idx_t) b);
69225 break;
69226 }
69227
69228 case DUK_EXTRAOP_NEWARR: {
69229 duk_context *ctx = (duk_context *) thr;
69231
69232 duk_push_array(ctx);
69233 duk_replace(ctx, (duk_idx_t) b);
69234 break;
69235 }
69236
69237 case DUK_EXTRAOP_SETALEN: {
69240 duk_tval *tv1;
69241 duk_hobject *h;
69242 duk_uint32_t len;
69243
69244 b = DUK_DEC_B(ins); tv1 = DUK__REGP(b);
69246 h = DUK_TVAL_GET_OBJECT(tv1);
69247
69248 c = DUK_DEC_C(ins); tv1 = DUK__REGP(c);
69250 len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
69251
69252 duk_hobject_set_length(thr, h, len);
69253
69254 break;
69255 }
69256
69257 case DUK_EXTRAOP_TYPEOF: {
69258 duk_context *ctx = (duk_context *) thr;
69259 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69261 duk_replace(ctx, (duk_idx_t) bc);
69262 break;
69263 }
69264
69265 case DUK_EXTRAOP_TYPEOFID: {
69266 duk_context *ctx = (duk_context *) thr;
69267 duk_activation *act;
69271 duk_tval *tv;
69272
69273 /* B -> target register
69274 * C -> constant index of identifier name
69275 */
69276
69277 tv = DUK__REGCONSTP(c); /* XXX: this could be a DUK__CONSTP instead */
69280 act = thr->callstack + thr->callstack_top - 1;
69281 if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
69282 /* -> [... val this] */
69283 tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
69284 duk_push_hstring(ctx, duk_js_typeof(thr, tv));
69285 duk_replace(ctx, (duk_idx_t) b);
69286 duk_pop_2(ctx);
69287 } else {
69288 /* unresolvable, no stack changes */
69290 duk_replace(ctx, (duk_idx_t) b);
69291 }
69292
69293 break;
69294 }
69295
69296 case DUK_EXTRAOP_INITENUM: {
69297 duk_context *ctx = (duk_context *) thr;
69300
69301 /*
69302 * Enumeration semantics come from for-in statement, E5 Section 12.6.4.
69303 * If called with 'null' or 'undefined', this opcode returns 'null' as
69304 * the enumerator, which is special cased in NEXTENUM. This simplifies
69305 * the compiler part
69306 */
69307
69308 /* B -> register for writing enumerator object
69309 * C -> value to be enumerated (register)
69310 */
69311
69312 if (duk_is_null_or_undefined(ctx, (duk_idx_t) c)) {
69313 duk_push_null(ctx);
69314 duk_replace(ctx, (duk_idx_t) b);
69315 } else {
69316 duk_dup(ctx, (duk_idx_t) c);
69317 duk_to_object(ctx, -1);
69318 duk_hobject_enumerator_create(ctx, 0 /*enum_flags*/); /* [ ... val ] --> [ ... enum ] */
69319 duk_replace(ctx, (duk_idx_t) b);
69320 }
69321 break;
69322 }
69323
69324 case DUK_EXTRAOP_NEXTENUM: {
69325 duk_context *ctx = (duk_context *) thr;
69328
69329 /*
69330 * NEXTENUM checks whether the enumerator still has unenumerated
69331 * keys. If so, the next key is loaded to the target register
69332 * and the next instruction is skipped. Otherwise the next instruction
69333 * will be executed, jumping out of the enumeration loop.
69334 */
69335
69336 /* B -> target register for next key
69337 * C -> enum register
69338 */
69339
69340 DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
69341 (duk_tval *) duk_get_tval(ctx, (duk_idx_t) b),
69342 (duk_tval *) duk_get_tval(ctx, (duk_idx_t) c)));
69343
69344 if (duk_is_object(ctx, (duk_idx_t) c)) {
69345 /* XXX: assert 'c' is an enumerator */
69346 duk_dup(ctx, (duk_idx_t) c);
69347 if (duk_hobject_enumerator_next(ctx, 0 /*get_value*/)) {
69348 /* [ ... enum ] -> [ ... next_key ] */
69349 DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
69350 (duk_tval *) duk_get_tval(ctx, -1)));
69351 curr_pc++;
69352 } else {
69353 /* [ ... enum ] -> [ ... ] */
69354 DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
69355 duk_push_undefined(ctx);
69356 }
69357 duk_replace(ctx, (duk_idx_t) b);
69358 } else {
69359 /* 'null' enumerator case -> behave as with an empty enumerator */
69360 DUK_ASSERT(duk_is_null(ctx, (duk_idx_t) c));
69361 DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
69362 }
69363 break;
69364 }
69365
69369 case DUK_EXTRAOP_INITGETI: {
69370 duk_context *ctx = (duk_context *) thr;
69371 duk_bool_t is_set = (extraop == DUK_EXTRAOP_INITSET || extraop == DUK_EXTRAOP_INITSETI);
69373 duk_uint_fast_t idx;
69374
69375 /* B -> object register
69376 * C -> C+0 contains key, C+1 closure (value)
69377 */
69378
69379 /*
69380 * INITSET/INITGET are only used to initialize object literal keys.
69381 * The compiler ensures that there cannot be a previous data property
69382 * of the same name. It also ensures that setter and getter can only
69383 * be initialized once (or not at all).
69384 */
69385
69386 idx = (duk_uint_fast_t) DUK_DEC_C(ins);
69387 if (extraop == DUK_EXTRAOP_INITSETI || extraop == DUK_EXTRAOP_INITGETI) {
69388 duk_tval *tv_ind = DUK__REGP(idx);
69390 idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
69391 }
69392
69393#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
69394 if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
69395 /* XXX: use duk_is_valid_index() instead? */
69396 /* XXX: improve check; check against nregs, not against top */
69397 DUK__INTERNAL_ERROR("INITSET/INITGET out of bounds");
69398 }
69399#endif
69400
69401 /* XXX: this is now a very unoptimal implementation -- this can be
69402 * made very simple by direct manipulation of the object internals,
69403 * given the guarantees above.
69404 */
69405
69408 duk_push_undefined(ctx);
69409 duk_dup(ctx, (duk_idx_t) b);
69410 duk_dup(ctx, (duk_idx_t) (idx + 0));
69411 duk_push_object(ctx); /* -> [ Object defineProperty undefined obj key desc ] */
69412
69413 duk_push_true(ctx);
69415 duk_push_true(ctx);
69417 duk_dup(ctx, (duk_idx_t) (idx + 1));
69418 duk_put_prop_stridx(ctx, -2, (is_set ? DUK_STRIDX_SET : DUK_STRIDX_GET));
69419
69420 DUK_DDD(DUK_DDDPRINT("INITGET/INITSET: obj=%!T, key=%!T, desc=%!T",
69421 (duk_tval *) duk_get_tval(ctx, -3),
69422 (duk_tval *) duk_get_tval(ctx, -2),
69423 (duk_tval *) duk_get_tval(ctx, -1)));
69424
69425 duk_call_method(ctx, 3); /* -> [ Object res ] */
69426 duk_pop_2(ctx);
69427
69428 DUK_DDD(DUK_DDDPRINT("INITGET/INITSET AFTER: obj=%!T",
69429 (duk_tval *) duk_get_tval(ctx, (duk_idx_t) b)));
69430 break;
69431 }
69432
69433 case DUK_EXTRAOP_ENDTRY: {
69434 duk_catcher *cat;
69435 duk_tval *tv1;
69436
69437 DUK_ASSERT(thr->catchstack_top >= 1);
69438 DUK_ASSERT(thr->callstack_top >= 1);
69439 DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69440
69441 cat = thr->catchstack + thr->catchstack_top - 1;
69442
69443 DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
69445
69446 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69447 DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
69448
69449 tv1 = thr->valstack + cat->idx_base;
69450 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69451 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
69452 tv1 = NULL;
69453
69454 tv1 = thr->valstack + cat->idx_base + 1;
69455 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69456 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
69457 tv1 = NULL;
69458
69460 } else {
69461 DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
69462 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69463 /* no need to unwind callstack */
69464 }
69465
69466 curr_pc = cat->pc_base + 1;
69467 break;
69468 }
69469
69470 case DUK_EXTRAOP_ENDCATCH: {
69471 duk_activation *act;
69472 duk_catcher *cat;
69473 duk_tval *tv1;
69474
69475 DUK_ASSERT(thr->catchstack_top >= 1);
69476 DUK_ASSERT(thr->callstack_top >= 1);
69477 DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69478
69479 cat = thr->catchstack + thr->catchstack_top - 1;
69480 DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat)); /* cleared before entering catch part */
69481
69482 act = thr->callstack + thr->callstack_top - 1;
69483
69484 if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
69485 duk_hobject *prev_env;
69486
69487 /* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
69489 DUK_ASSERT(act->lex_env != NULL);
69490
69491 DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
69492
69493 prev_env = act->lex_env;
69494 DUK_ASSERT(prev_env != NULL);
69495 act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
69497 DUK_HOBJECT_DECREF(thr, prev_env); /* side effects */
69498 }
69499
69500 if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69501 DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
69502
69503 tv1 = thr->valstack + cat->idx_base;
69504 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69505 DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
69506 tv1 = NULL;
69507
69508 tv1 = thr->valstack + cat->idx_base + 1;
69509 DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69510 DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
69511 tv1 = NULL;
69512
69514 } else {
69515 DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
69516 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69517 /* no need to unwind callstack */
69518 }
69519
69520 curr_pc = cat->pc_base + 1;
69521 break;
69522 }
69523
69524 case DUK_EXTRAOP_ENDFIN: {
69525 duk_context *ctx = (duk_context *) thr;
69526 duk_catcher *cat;
69527 duk_tval *tv1;
69528 duk_small_uint_t cont_type;
69529 duk_small_uint_t ret_result;
69530
69531 /* Sync and NULL early. */
69533
69534 DUK_ASSERT(thr->catchstack_top >= 1);
69535 DUK_ASSERT(thr->callstack_top >= 1);
69536 DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69537
69538 cat = thr->catchstack + thr->catchstack_top - 1;
69539
69540 /* CATCH flag may be enabled or disabled here; it may be enabled if
69541 * the statement has a catch block but the try block does not throw
69542 * an error.
69543 */
69544 DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat)); /* cleared before entering finally */
69545 /* XXX: assert idx_base */
69546
69547 DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
69548 (duk_tval *) (thr->valstack + cat->idx_base + 0),
69549 (duk_tval *) (thr->valstack + cat->idx_base + 1)));
69550
69551 tv1 = thr->valstack + cat->idx_base + 1; /* type */
69553 cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
69554
69555 switch (cont_type) {
69556 case DUK_LJ_TYPE_NORMAL: {
69557 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
69558 "dismantle catcher, resume execution after ENDFIN"));
69559 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69560 /* no need to unwind callstack */
69561 goto restart_execution;
69562 }
69563 case DUK_LJ_TYPE_RETURN: {
69564 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
69565 "catcher, handle return, lj.value1=%!T", thr->valstack + cat->idx_base));
69566
69567 /* Not necessary to unwind catchstack: return handling will
69568 * do it. The finally flag of 'cat' is no longer set. The
69569 * catch flag may be set, but it's not checked by return handling.
69570 */
69571 DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat)); /* cleared before entering finally */
69572#if 0
69573 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69574#endif
69575
69576 duk_push_tval(ctx, thr->valstack + cat->idx_base);
69577 ret_result = duk__handle_return(thr,
69578 entry_thread,
69579 entry_callstack_top);
69580 if (ret_result == DUK__RETHAND_RESTART) {
69581 goto restart_execution;
69582 }
69583 DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
69584
69585 DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
69586 return;
69587 }
69588 case DUK_LJ_TYPE_BREAK:
69589 case DUK_LJ_TYPE_CONTINUE: {
69590 duk_uint_t label_id;
69591 duk_small_uint_t lj_type;
69592
69593 /* Not necessary to unwind catchstack: break/continue
69594 * handling will do it. The finally flag of 'cat' is
69595 * no longer set. The catch flag may be set, but it's
69596 * not checked by break/continue handling.
69597 */
69598#if 0
69599 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69600#endif
69601
69602 tv1 = thr->valstack + cat->idx_base;
69604#if defined(DUK_USE_FASTINT)
69605 DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
69606 label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
69607#else
69608 label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
69609#endif
69610 lj_type = cont_type;
69611 duk__handle_break_or_continue(thr, label_id, lj_type);
69612 goto restart_execution;
69613 }
69614 default: {
69615 DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
69616 "dismantle catcher, re-throw error",
69617 (long) cont_type));
69618
69619 duk_push_tval(ctx, thr->valstack + cat->idx_base);
69620
69622
69623 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
69624 duk_err_longjmp(thr);
69626 }
69627 }
69628
69629 /* Must restart in all cases because we NULLed thr->ptr_curr_pc. */
69631 break;
69632 }
69633
69634 case DUK_EXTRAOP_THROW: {
69635 duk_context *ctx = (duk_context *) thr;
69636 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69637
69638 /* Note: errors are augmented when they are created, not
69639 * when they are thrown. So, don't augment here, it would
69640 * break re-throwing for instance.
69641 */
69642
69643 /* Sync so that augmentation sees up-to-date activations, NULL
69644 * thr->ptr_curr_pc so that it's not used if side effects occur
69645 * in augmentation or longjmp handling.
69646 */
69648
69649 duk_dup(ctx, (duk_idx_t) bc);
69650 DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
69651 (duk_tval *) duk_get_tval(ctx, -1)));
69652#if defined(DUK_USE_AUGMENT_ERROR_THROW)
69654 DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
69655 (duk_tval *) duk_get_tval(ctx, -1)));
69656#endif
69657
69659
69660 DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
69661 duk_err_longjmp(thr);
69663 break;
69664 }
69665
69666 case DUK_EXTRAOP_INVLHS: {
69667 DUK_ERROR(thr, DUK_ERR_REFERENCE_ERROR, "invalid lvalue");
69668
69670 break;
69671 }
69672
69673 case DUK_EXTRAOP_UNM:
69674 case DUK_EXTRAOP_UNP: {
69675 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69676 duk__vm_arith_unary_op(thr, DUK__REGP(bc), bc, extraop);
69677 break;
69678 }
69679
69680 case DUK_EXTRAOP_DEBUGGER: {
69681 /* Opcode only emitted by compiler when debugger
69682 * support is enabled. Ignore it silently without
69683 * debugger support, in case it has been loaded
69684 * from precompiled bytecode.
69685 */
69686#if defined(DUK_USE_DEBUGGER_SUPPORT)
69687 if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
69688 DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
69690 duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
69691 DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
69692 goto restart_execution;
69693 } else {
69694 DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
69695 }
69696#else
69697 DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
69698#endif
69699 break;
69700 }
69701
69702 case DUK_EXTRAOP_BREAK: {
69703 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69704
69705 DUK_DDD(DUK_DDDPRINT("BREAK: %ld", (long) bc));
69706
69709 goto restart_execution;
69710 }
69711
69712 case DUK_EXTRAOP_CONTINUE: {
69713 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69714
69715 DUK_DDD(DUK_DDDPRINT("CONTINUE: %ld", (long) bc));
69716
69719 goto restart_execution;
69720 }
69721
69722 case DUK_EXTRAOP_BNOT: {
69723 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69724
69725 duk__vm_bitwise_not(thr, DUK__REGP(bc), bc);
69726 break;
69727 }
69728
69729 case DUK_EXTRAOP_LNOT: {
69730 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69731 duk_tval *tv1;
69732
69733 tv1 = DUK__REGP(bc);
69734 duk__vm_logical_not(thr, tv1, tv1);
69735 break;
69736 }
69737
69738 case DUK_EXTRAOP_INSTOF: {
69739 duk_context *ctx = (duk_context *) thr;
69742 duk_bool_t tmp;
69743
69744 tmp = duk_js_instanceof(thr, DUK__REGP(b), DUK__REGCONSTP(c));
69745 duk_push_boolean(ctx, tmp);
69746 duk_replace(ctx, (duk_idx_t) b);
69747 break;
69748 }
69749
69750 case DUK_EXTRAOP_IN: {
69751 duk_context *ctx = (duk_context *) thr;
69754 duk_bool_t tmp;
69755
69756 tmp = duk_js_in(thr, DUK__REGP(b), DUK__REGCONSTP(c));
69757 duk_push_boolean(ctx, tmp);
69758 duk_replace(ctx, (duk_idx_t) b);
69759 break;
69760 }
69761
69762 case DUK_EXTRAOP_LABEL: {
69763 duk_catcher *cat;
69764 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69765
69766 /* allocate catcher and populate it (should be atomic) */
69767
69769 cat = thr->catchstack + thr->catchstack_top;
69770 thr->catchstack_top++;
69771
69773 cat->callstack_index = thr->callstack_top - 1;
69774 cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
69775 cat->idx_base = 0; /* unused for label */
69776 cat->h_varname = NULL;
69777
69778 DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
69779 "idx_base=%ld, h_varname=%!O, label_id=%ld",
69780 (long) cat->flags, (long) cat->callstack_index, (long) cat->pc_base,
69781 (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
69782
69783 curr_pc += 2; /* skip jump slots */
69784 break;
69785 }
69786
69787 case DUK_EXTRAOP_ENDLABEL: {
69788 duk_catcher *cat;
69789#if defined(DUK_USE_DDDPRINT) || defined(DUK_USE_ASSERTIONS)
69790 duk_uint_fast_t bc = DUK_DEC_BC(ins);
69791#endif
69792#if defined(DUK_USE_DDDPRINT)
69793 DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
69794#endif
69795
69796 DUK_ASSERT(thr->catchstack_top >= 1);
69797
69798 cat = thr->catchstack + thr->catchstack_top - 1;
69799 DUK_UNREF(cat);
69802
69803 duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69804 /* no need to unwind callstack */
69805 break;
69806 }
69807
69808 default: {
69809 DUK__INTERNAL_ERROR("invalid extra opcode");
69810 }
69811
69812 } /* end switch */
69813
69814 break;
69815 }
69816
69817 default: {
69818 /* this should never be possible, because the switch-case is
69819 * comprehensive
69820 */
69821 DUK__INTERNAL_ERROR("invalid opcode");
69822 break;
69823 }
69824
69825 } /* end switch */
69826 }
69828
69829#ifndef DUK_USE_VERBOSE_EXECUTOR_ERRORS
69830 internal_error:
69831 DUK_ERROR_INTERNAL(thr, "internal error in bytecode executor");
69832#endif
69833}
69834
69835#undef DUK__LONGJMP_RESTART
69836#undef DUK__LONGJMP_FINISHED
69837#undef DUK__LONGJMP_RETHROW
69838
69839#undef DUK__RETHAND_RESTART
69840#undef DUK__RETHAND_FINISHED
69841
69842#undef DUK__FUN
69843#undef DUK__STRICT
69844#undef DUK__REG
69845#undef DUK__REGP
69846#undef DUK__CONST
69847#undef DUK__CONSTP
69848#undef DUK__RCISREG
69849#undef DUK__REGCONST
69850#undef DUK__REGCONSTP
69851
69852#undef DUK__INTERNAL_ERROR
69853#undef DUK__SYNC_CURR_PC
69854#undef DUK__SYNC_AND_NULL_CURR_PC
69855#line 1 "duk_js_ops.c"
69856/*
69857 * Ecmascript specification algorithm and conversion helpers.
69858 *
69859 * These helpers encapsulate the primitive Ecmascript operation
69860 * semantics, and are used by the bytecode executor and the API
69861 * (among other places). Note that some primitives are only
69862 * implemented as part of the API and have no "internal" helper.
69863 * (This is the case when an internal helper would not really be
69864 * useful; e.g. the operation is rare, uses value stack heavily,
69865 * etc.)
69866 *
69867 * The operation arguments depend on what is required to implement
69868 * the operation:
69869 *
69870 * - If an operation is simple and stateless, and has no side
69871 * effects, it won't take an duk_hthread argument and its
69872 * arguments may be duk_tval pointers (which are safe as long
69873 * as no side effects take place).
69874 *
69875 * - If complex coercions are required (e.g. a "ToNumber" coercion)
69876 * or errors may be thrown, the operation takes an duk_hthread
69877 * argument. This also implies that the operation may have
69878 * arbitrary side effects, invalidating any duk_tval pointers.
69879 *
69880 * - For operations with potential side effects, arguments can be
69881 * taken in several ways:
69882 *
69883 * a) as duk_tval pointers, which makes sense if the "common case"
69884 * can be resolved without side effects (e.g. coercion); the
69885 * arguments are pushed to the valstack for coercion if
69886 * necessary
69887 *
69888 * b) as duk_tval values
69889 *
69890 * c) implicitly on value stack top
69891 *
69892 * d) as indices to the value stack
69893 *
69894 * Future work:
69895 *
69896 * - Argument styles may not be the most sensible in every case now.
69897 *
69898 * - In-place coercions might be useful for several operations, if
69899 * in-place coercion is OK for the bytecode executor and the API.
69900 */
69901
69902/* include removed: duk_internal.h */
69904/*
69905 * [[DefaultValue]] (E5 Section 8.12.8)
69906 *
69907 * ==> implemented in the API.
69908 */
69909
69910/*
69911 * ToPrimitive() (E5 Section 9.1)
69912 *
69913 * ==> implemented in the API.
69914 */
69915
69916/*
69917 * ToBoolean() (E5 Section 9.2)
69918 */
69919
69921 switch (DUK_TVAL_GET_TAG(tv)) {
69922 case DUK_TAG_UNDEFINED:
69923 case DUK_TAG_NULL:
69924 return 0;
69925 case DUK_TAG_BOOLEAN:
69926 return DUK_TVAL_GET_BOOLEAN(tv);
69927 case DUK_TAG_STRING: {
69929 DUK_ASSERT(h != NULL);
69930 return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
69931 }
69932 case DUK_TAG_OBJECT: {
69933 return 1;
69934 }
69935 case DUK_TAG_BUFFER: {
69936 /* mimic semantics for strings */
69938 DUK_ASSERT(h != NULL);
69939 return (DUK_HBUFFER_GET_SIZE(h) > 0 ? 1 : 0);
69940 }
69941 case DUK_TAG_POINTER: {
69942 void *p = DUK_TVAL_GET_POINTER(tv);
69943 return (p != NULL ? 1 : 0);
69944 }
69945 case DUK_TAG_LIGHTFUNC: {
69946 return 1;
69947 }
69948#if defined(DUK_USE_FASTINT)
69949 case DUK_TAG_FASTINT:
69950 if (DUK_TVAL_GET_FASTINT(tv) != 0) {
69951 return 1;
69952 } else {
69953 return 0;
69954 }
69955#endif
69956 default: {
69957 /* number */
69958 duk_double_t d;
69959 int c;
69962 d = DUK_TVAL_GET_DOUBLE(tv);
69963 c = DUK_FPCLASSIFY((double) d);
69964 if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
69965 return 0;
69966 } else {
69967 return 1;
69968 }
69969 }
69970 }
69972}
69973
69974/*
69975 * ToNumber() (E5 Section 9.3)
69976 *
69977 * Value to convert must be on stack top, and is popped before exit.
69978 *
69979 * See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
69980 * http://www.cs.indiana.edu/~burger/fp/index.html
69981 *
69982 * Notes on the conversion:
69983 *
69984 * - There are specific requirements on the accuracy of the conversion
69985 * through a "Mathematical Value" (MV), so this conversion is not
69986 * trivial.
69987 *
69988 * - Quick rejects (e.g. based on first char) are difficult because
69989 * the grammar allows leading and trailing white space.
69990 *
69991 * - Quick reject based on string length is difficult even after
69992 * accounting for white space; there may be arbitrarily many
69993 * decimal digits.
69994 *
69995 * - Standard grammar allows decimal values ("123"), hex values
69996 * ("0x123") and infinities
69997 *
69998 * - Unlike source code literals, ToNumber() coerces empty strings
69999 * and strings with only whitespace to zero (not NaN).
70000 */
70001
70002/* E5 Section 9.3.1 */
70004 duk_context *ctx = (duk_context *) thr;
70005 duk_small_uint_t s2n_flags;
70006 duk_double_t d;
70007
70008 /* Quite lenient, e.g. allow empty as zero, but don't allow trailing
70009 * garbage.
70010 */
70011 s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
70022
70023 duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
70024 d = duk_get_number(ctx, -1);
70025 duk_pop(ctx);
70026
70027 return d;
70028}
70029
70031 duk_context *ctx = (duk_hthread *) thr;
70032
70033 DUK_ASSERT(thr != NULL);
70034 DUK_ASSERT(tv != NULL);
70035
70036 switch (DUK_TVAL_GET_TAG(tv)) {
70037 case DUK_TAG_UNDEFINED: {
70038 /* return a specific NaN (although not strictly necessary) */
70042 return du.d;
70043 }
70044 case DUK_TAG_NULL: {
70045 /* +0.0 */
70046 return 0.0;
70047 }
70048 case DUK_TAG_BOOLEAN: {
70049 if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
70050 return 1.0;
70051 }
70052 return 0.0;
70053 }
70054 case DUK_TAG_STRING: {
70056 duk_push_hstring(ctx, h);
70057 return duk__tonumber_string_raw(thr);
70058 }
70059 case DUK_TAG_OBJECT: {
70060 /* Note: ToPrimitive(object,hint) == [[DefaultValue]](object,hint),
70061 * so use [[DefaultValue]] directly.
70062 */
70063 duk_double_t d;
70064 duk_push_tval(ctx, tv);
70065 duk_to_defaultvalue(ctx, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */
70066
70067 /* recursive call for a primitive value (guaranteed not to cause second
70068 * recursion).
70069 */
70070 d = duk_js_tonumber(thr, duk_require_tval(ctx, -1));
70071
70072 duk_pop(ctx);
70073 return d;
70074 }
70075 case DUK_TAG_BUFFER: {
70076 /* Coerce like a string. This makes sense because addition also treats
70077 * buffers like strings.
70078 */
70080 duk_push_hbuffer(ctx, h);
70081 duk_to_string(ctx, -1); /* XXX: expensive, but numconv now expects to see a string */
70082 return duk__tonumber_string_raw(thr);
70083 }
70084 case DUK_TAG_POINTER: {
70085 /* Coerce like boolean */
70086 void *p = DUK_TVAL_GET_POINTER(tv);
70087 return (p != NULL ? 1.0 : 0.0);
70088 }
70089 case DUK_TAG_LIGHTFUNC: {
70090 /* +(function(){}) -> NaN */
70091 return DUK_DOUBLE_NAN;
70092 }
70093#if defined(DUK_USE_FASTINT)
70094 case DUK_TAG_FASTINT:
70095 return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
70096#endif
70097 default: {
70098 /* number */
70101 return DUK_TVAL_GET_DOUBLE(tv);
70102 }
70103 }
70104
70106}
70107
70108/*
70109 * ToInteger() (E5 Section 9.4)
70110 */
70111
70112/* exposed, used by e.g. duk_bi_date.c */
70115
70116 if (c == DUK_FP_NAN) {
70117 return 0.0;
70118 } else if (c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
70119 /* XXX: FP_ZERO check can be removed, the else clause handles it
70120 * correctly (preserving sign).
70121 */
70122 return x;
70123 } else {
70125 x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */
70126 if (s) {
70127 x = -x;
70128 }
70129 return x;
70130 }
70131}
70132
70134 /* XXX: fastint */
70135 duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */
70136 return duk_js_tointeger_number(d);
70137}
70138
70139/*
70140 * ToInt32(), ToUint32(), ToUint16() (E5 Sections 9.5, 9.6, 9.7)
70141 */
70142
70143/* combined algorithm matching E5 Sections 9.5 and 9.6 */
70147
70148 if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
70149 return 0.0;
70150 }
70151
70152
70153 /* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
70155 x = DUK_FLOOR(DUK_FABS(x));
70156 if (s) {
70157 x = -x;
70158 }
70159
70160 /* NOTE: fmod(x) result sign is same as sign of x, which
70161 * differs from what Javascript wants (see Section 9.6).
70162 */
70163
70164 x = DUK_FMOD(x, DUK_DOUBLE_2TO32); /* -> x in ]-2**32, 2**32[ */
70166 if (x < 0.0) {
70167 x += DUK_DOUBLE_2TO32;
70168 }
70169 /* -> x in [0, 2**32[ */
70170
70171 if (is_toint32) {
70172 if (x >= DUK_DOUBLE_2TO31) {
70173 /* x in [2**31, 2**32[ */
70174
70175 x -= DUK_DOUBLE_2TO32; /* -> x in [-2**31,2**31[ */
70176 }
70177 }
70178
70179 return x;
70180}
70181
70182DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
70184
70185#if defined(DUK_USE_FASTINT)
70186 if (DUK_TVAL_IS_FASTINT(tv)) {
70187 return DUK_TVAL_GET_FASTINT_I32(tv);
70188 }
70189#endif
70190
70191 d = duk_js_tonumber(thr, tv); /* invalidates tv */
70194 DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */
70195 DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */
70196 return (duk_int32_t) d;
70197}
70198
70199
70200DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
70202
70203#if defined(DUK_USE_FASTINT)
70204 if (DUK_TVAL_IS_FASTINT(tv)) {
70205 return DUK_TVAL_GET_FASTINT_U32(tv);
70206 }
70207#endif
70208
70209 d = duk_js_tonumber(thr, tv); /* invalidates tv */
70212 DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */
70213 DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */
70214 return (duk_uint32_t) d;
70215
70216}
70217
70218DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
70219 /* should be a safe way to compute this */
70220 return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
70221}
70222
70223/*
70224 * ToString() (E5 Section 9.8)
70225 *
70226 * ==> implemented in the API.
70227 */
70228
70229/*
70230 * ToObject() (E5 Section 9.9)
70231 *
70232 * ==> implemented in the API.
70233 */
70234
70235/*
70236 * CheckObjectCoercible() (E5 Section 9.10)
70237 *
70238 * Note: no API equivalent now.
70239 */
70240
70241#if 0 /* unused */
70242DUK_INTERNAL void duk_js_checkobjectcoercible(duk_hthread *thr, duk_tval *tv_x) {
70244
70245 /* Note: this must match ToObject() behavior */
70246
70247 if (tag == DUK_TAG_UNDEFINED ||
70248 tag == DUK_TAG_NULL ||
70249 tag == DUK_TAG_POINTER ||
70250 tag == DUK_TAG_BUFFER) {
70251 DUK_ERROR_TYPE(thr, "not object coercible");
70252 }
70253}
70254#endif
70255
70256/*
70257 * IsCallable() (E5 Section 9.11)
70258 *
70259 * XXX: API equivalent is a separate implementation now, and this has
70260 * currently no callers.
70261 */
70262
70263#if 0 /* unused */
70264DUK_INTERNAL duk_bool_t duk_js_iscallable(duk_tval *tv_x) {
70265 duk_hobject *obj;
70266
70267 if (!DUK_TVAL_IS_OBJECT(tv_x)) {
70268 return 0;
70269 }
70270 obj = DUK_TVAL_GET_OBJECT(tv_x);
70271 DUK_ASSERT(obj != NULL);
70272
70273 return DUK_HOBJECT_IS_CALLABLE(obj);
70274}
70275#endif
70276
70277/*
70278 * Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
70279 * 9.12). These have much in common so they can share some helpers.
70280 *
70281 * Future work notes:
70282 *
70283 * - Current implementation (and spec definition) has recursion; this should
70284 * be fixed if possible.
70285 *
70286 * - String-to-number coercion should be possible without going through the
70287 * value stack (and be more compact) if a shared helper is invoked.
70288 */
70289
70290/* Note that this is the same operation for strict and loose equality:
70291 * - E5 Section 11.9.3, step 1.c (loose)
70292 * - E5 Section 11.9.6, step 4 (strict)
70293 */
70294
70296#if defined(DUK_USE_PARANOID_MATH)
70297 /* Straightforward algorithm, makes fewer compiler assumptions. */
70300 if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
70301 return 0;
70302 }
70303 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
70304 return 1;
70305 }
70306 if (x == y) {
70307 return 1;
70308 }
70309 return 0;
70310#else /* DUK_USE_PARANOID_MATH */
70311 /* Better equivalent algorithm. If the compiler is compliant, C and
70312 * Ecmascript semantics are identical for this particular comparison.
70313 * In particular, NaNs must never compare equal and zeroes must compare
70314 * equal regardless of sign. Could also use a macro, but this inlines
70315 * already nicely (no difference on gcc, for instance).
70317 if (x == y) {
70318 /* IEEE requires that NaNs compare false */
70321 return 1;
70322 } else {
70323 /* IEEE requires that zeros compare the same regardless
70324 * of their signed, so if both x and y are zeroes, they
70325 * are caught above.
70326 */
70328 return 0;
70329 }
70330#endif /* DUK_USE_PARANOID_MATH */
70331}
70332
70334#if defined(DUK_USE_PARANOID_MATH)
70337
70338 if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
70339 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
70340 return 1;
70341 }
70342 if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
70343 /* Note: cannot assume that a non-zero return value of signbit() would
70344 * always be the same -- hence cannot (portably) use something like:
70345 *
70346 * signbit(x) == signbit(y)
70347 */
70348 duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
70349 duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
70350 return (sx == sy);
70351 }
70352
70353 /* normal comparison; known:
70354 * - both x and y are not NaNs (but one of them can be)
70355 * - both x and y are not zero (but one of them can be)
70356 * - x and y may be denormal or infinite
70357 */
70358
70359 return (x == y);
70360#else /* DUK_USE_PARANOID_MATH */
70363
70364 if (x == y) {
70365 /* IEEE requires that NaNs compare false */
70368
70369 /* Using classification has smaller footprint than direct comparison. */
70370 if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
70371 /* Note: cannot assume that a non-zero return value of signbit() would
70372 * always be the same -- hence cannot (portably) use something like:
70373 *
70374 * signbit(x) == signbit(y)
70375 */
70376 duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
70377 duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
70378 return (sx == sy);
70379 }
70380 return 1;
70381 } else {
70382 /* IEEE requires that zeros compare the same regardless
70383 * of their signed, so if both x and y are zeroes, they
70384 * are caught above.
70385 */
70387
70388 /* Difference to non-strict/strict comparison is that NaNs compare
70389 * equal and signed zero signs matter.
70390 */
70391 if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
70392 /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
70393 return 1;
70394 }
70395 return 0;
70396 }
70397#endif /* DUK_USE_PARANOID_MATH */
70398}
70399
70401 duk_context *ctx = (duk_context *) thr;
70402 duk_tval *tv_tmp;
70403
70404 /* If flags != 0 (strict or SameValue), thr can be NULL. For loose
70405 * equals comparison it must be != NULL.
70406 */
70407 DUK_ASSERT(flags != 0 || thr != NULL);
70408
70409 /*
70410 * Same type?
70411 *
70412 * Note: since number values have no explicit tag in the 8-byte
70413 * representation, need the awkward if + switch.
70414 */
70415
70416#if defined(DUK_USE_FASTINT)
70417 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
70418 if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
70419 return 1;
70420 } else {
70421 return 0;
70422 }
70423 }
70424 else
70425#endif
70426 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
70427 /* Catches both doubles and cases where only one argument is a fastint */
70428 if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
70429 /* SameValue */
70431 DUK_TVAL_GET_NUMBER(tv_y));
70432 } else {
70433 /* equals and strict equals */
70435 DUK_TVAL_GET_NUMBER(tv_y));
70436 }
70437 } else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
70438 switch (DUK_TVAL_GET_TAG(tv_x)) {
70439 case DUK_TAG_UNDEFINED:
70440 case DUK_TAG_NULL: {
70441 return 1;
70442 }
70443 case DUK_TAG_BOOLEAN: {
70444 return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
70445 }
70446 case DUK_TAG_POINTER: {
70447 return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
70448 }
70449 case DUK_TAG_STRING:
70450 case DUK_TAG_OBJECT: {
70451 /* heap pointer comparison suffices */
70452 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
70453 }
70454 case DUK_TAG_BUFFER: {
70455 if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
70456 /* heap pointer comparison suffices */
70457 return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
70458 } else {
70459 /* non-strict equality for buffers compares contents */
70460 duk_hbuffer *h_x = DUK_TVAL_GET_BUFFER(tv_x);
70461 duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
70462 duk_size_t len_x = DUK_HBUFFER_GET_SIZE(h_x);
70463 duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
70464 void *buf_x;
70465 void *buf_y;
70466 if (len_x != len_y) {
70467 return 0;
70468 }
70469 buf_x = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_x);
70470 buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
70471 /* if len_x == len_y == 0, buf_x and/or buf_y may
70472 * be NULL, but that's OK.
70473 */
70474 DUK_ASSERT(len_x == len_y);
70475 DUK_ASSERT(len_x == 0 || buf_x != NULL);
70476 DUK_ASSERT(len_y == 0 || buf_y != NULL);
70477 return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
70478 }
70479 }
70480 case DUK_TAG_LIGHTFUNC: {
70481 /* At least 'magic' has a significant impact on function
70482 * identity.
70483 */
70484 duk_small_uint_t lf_flags_x;
70485 duk_small_uint_t lf_flags_y;
70486 duk_c_function func_x;
70487 duk_c_function func_y;
70488
70489 DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
70490 DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
70491 return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
70492 }
70493#if defined(DUK_USE_FASTINT)
70494 case DUK_TAG_FASTINT:
70495#endif
70496 default: {
70502 return 0;
70503 }
70504 }
70505 }
70506
70507 if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
70508 return 0;
70509 }
70510
70511 DUK_ASSERT(flags == 0); /* non-strict equality from here on */
70512
70513 /*
70514 * Types are different; various cases for non-strict comparison
70515 *
70516 * Since comparison is symmetric, we use a "swap trick" to reduce
70517 * code size.
70518 */
70519
70520 /* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
70521 if ((DUK_TVAL_IS_UNDEFINED(tv_x) && DUK_TVAL_IS_NULL(tv_y)) ||
70522 (DUK_TVAL_IS_NULL(tv_x) && DUK_TVAL_IS_UNDEFINED(tv_y))) {
70523 return 1;
70524 }
70525
70526 /* Number/string-or-buffer -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
70527 if (DUK_TVAL_IS_NUMBER(tv_x) && (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
70528 /* the next 'if' is guaranteed to match after swap */
70529 tv_tmp = tv_x;
70530 tv_x = tv_y;
70531 tv_y = tv_tmp;
70532 }
70533 if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) && DUK_TVAL_IS_NUMBER(tv_y)) {
70534 /* XXX: this is possible without resorting to the value stack */
70535 duk_double_t d1, d2;
70536 d2 = DUK_TVAL_GET_NUMBER(tv_y);
70537 duk_push_tval(ctx, tv_x);
70538 duk_to_string(ctx, -1); /* buffer values are coerced first to string here */
70539 duk_to_number(ctx, -1);
70540 d1 = duk_require_number(ctx, -1);
70541 duk_pop(ctx);
70542 return duk__js_equals_number(d1, d2);
70543 }
70544
70545 /* Buffer/string -> compare contents. */
70546 if (DUK_TVAL_IS_BUFFER(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
70547 tv_tmp = tv_x;
70548 tv_x = tv_y;
70549 tv_y = tv_tmp;
70550 }
70551 if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_BUFFER(tv_y)) {
70552 duk_hstring *h_x = DUK_TVAL_GET_STRING(tv_x);
70553 duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
70555 duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
70556 const void *buf_x;
70557 const void *buf_y;
70558 if (len_x != len_y) {
70559 return 0;
70560 }
70561 buf_x = (const void *) DUK_HSTRING_GET_DATA(h_x);
70562 buf_y = (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
70563 /* if len_x == len_y == 0, buf_x and/or buf_y may
70564 * be NULL, but that's OK.
70565 */
70566 DUK_ASSERT(len_x == len_y);
70567 DUK_ASSERT(len_x == 0 || buf_x != NULL);
70568 DUK_ASSERT(len_y == 0 || buf_y != NULL);
70569 return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
70570 }
70571
70572 /* Boolean/any -> coerce boolean to number and try again. If boolean is
70573 * compared to a pointer, the final comparison after coercion now always
70574 * yields false (as pointer vs. number compares to false), but this is
70575 * not special cased.
70576 */
70577 if (DUK_TVAL_IS_BOOLEAN(tv_x)) {
70578 tv_tmp = tv_x;
70579 tv_x = tv_y;
70580 tv_y = tv_tmp;
70581 }
70582 if (DUK_TVAL_IS_BOOLEAN(tv_y)) {
70583 /* ToNumber(bool) is +1.0 or 0.0. Tagged boolean value is always 0 or 1. */
70584 duk_bool_t rc;
70585 DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
70586 duk_push_tval(ctx, tv_x);
70588 rc = duk_js_equals_helper(thr,
70589 DUK_GET_TVAL_NEGIDX(ctx, -2),
70590 DUK_GET_TVAL_NEGIDX(ctx, -1),
70591 0 /*flags:nonstrict*/);
70592 duk_pop_2(ctx);
70593 return rc;
70594 }
70595
70596 /* String-number-buffer/object -> coerce object to primitive (apparently without hint), then try again. */
70597 if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_NUMBER(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) &&
70598 DUK_TVAL_IS_OBJECT(tv_y)) {
70599 tv_tmp = tv_x;
70600 tv_x = tv_y;
70601 tv_y = tv_tmp;
70602 }
70603 if (DUK_TVAL_IS_OBJECT(tv_x) &&
70604 (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_NUMBER(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
70605 duk_bool_t rc;
70606 duk_push_tval(ctx, tv_x);
70607 duk_push_tval(ctx, tv_y);
70608 duk_to_primitive(ctx, -2, DUK_HINT_NONE); /* apparently no hint? */
70609 rc = duk_js_equals_helper(thr,
70610 DUK_GET_TVAL_NEGIDX(ctx, -2),
70611 DUK_GET_TVAL_NEGIDX(ctx, -1),
70612 0 /*flags:nonstrict*/);
70613 duk_pop_2(ctx);
70614 return rc;
70616
70617 /* Nothing worked -> not equal. */
70618 return 0;
70619}
70620
70621/*
70622 * Comparisons (x >= y, x > y, x <= y, x < y)
70623 *
70624 * E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
70625 * flags to get the rest.
70626 */
70627
70628/* XXX: this should probably just operate on the stack top, because it
70629 * needs to push stuff on the stack anyway...
70630 */
70631
70632DUK_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) {
70633 duk_size_t prefix_len;
70634 duk_small_int_t rc;
70635
70636 prefix_len = (len1 <= len2 ? len1 : len2);
70637
70638 /* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
70639 * inputs so no zero length check is needed.
70640 */
70641 rc = DUK_MEMCMP((const void *) buf1,
70642 (const void *) buf2,
70643 (size_t) prefix_len);
70644
70645 if (rc < 0) {
70646 return -1;
70647 } else if (rc > 0) {
70648 return 1;
70649 }
70650
70651 /* prefix matches, lengths matter now */
70652 if (len1 < len2) {
70653 /* e.g. "x" < "xx" */
70654 return -1;
70655 } else if (len1 > len2) {
70656 return 1;
70657 }
70658
70659 return 0;
70660}
70661
70663 /*
70664 * String comparison (E5 Section 11.8.5, step 4), which
70665 * needs to compare codepoint by codepoint.
70666 *
70667 * However, UTF-8 allows us to use strcmp directly: the shared
70668 * prefix will be encoded identically (UTF-8 has unique encoding)
70669 * and the first differing character can be compared with a simple
70670 * unsigned byte comparison (which strcmp does).
70671 *
70672 * This will not work properly for non-xutf-8 strings, but this
70673 * is not an issue for compliance.
70674 */
70675
70676 DUK_ASSERT(h1 != NULL);
70677 DUK_ASSERT(h2 != NULL);
70678
70679 return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
70680 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
70684
70685#if 0 /* unused */
70686DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
70687 /* Similar to String comparison. */
70688
70689 DUK_ASSERT(h1 != NULL);
70690 DUK_ASSERT(h2 != NULL);
70691 DUK_UNREF(heap);
70692
70693 return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
70694 (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
70697}
70698#endif
70699
70701 duk_context *ctx = (duk_context *) thr;
70702 duk_double_t d1, d2;
70703 duk_small_int_t c1, c2;
70704 duk_small_int_t s1, s2;
70705 duk_small_int_t rc;
70706 duk_bool_t retval;
70707
70708 /* Fast path for fastints */
70709#if defined(DUK_USE_FASTINT)
70710 if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
70711 duk_int64_t v1 = DUK_TVAL_GET_FASTINT(tv_x);
70712 duk_int64_t v2 = DUK_TVAL_GET_FASTINT(tv_y);
70713 if (v1 < v2) {
70714 /* 'lt is true' */
70715 retval = 1;
70716 } else {
70717 retval = 0;
70718 }
70719 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70720 retval ^= 1;
70721 }
70722 return retval;
70723 }
70724#endif /* DUK_USE_FASTINT */
70725
70726 /* Fast path for numbers (one of which may be a fastint) */
70727#if 1 /* XXX: make fast paths optional for size minimization? */
70728 if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
70729 d1 = DUK_TVAL_GET_NUMBER(tv_x);
70730 d2 = DUK_TVAL_GET_NUMBER(tv_y);
70731 c1 = DUK_FPCLASSIFY(d1);
70732 c2 = DUK_FPCLASSIFY(d2);
70733
70734 if (c1 == DUK_FP_NORMAL && c2 == DUK_FP_NORMAL) {
70735 /* XXX: this is a very narrow check, and doesn't cover
70736 * zeroes, subnormals, infinities, which compare normally.
70737 */
70738
70739 if (d1 < d2) {
70740 /* 'lt is true' */
70741 retval = 1;
70742 } else {
70743 retval = 0;
70744 }
70745 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70746 retval ^= 1;
70747 }
70748 return retval;
70749 }
70750 }
70751#endif
70752
70753 /* Slow path */
70754
70755 duk_push_tval(ctx, tv_x);
70756 duk_push_tval(ctx, tv_y);
70757
70761 } else {
70764 }
70765
70766 /* Note: reuse variables */
70767 tv_x = DUK_GET_TVAL_NEGIDX(ctx, -2);
70768 tv_y = DUK_GET_TVAL_NEGIDX(ctx, -1);
70769
70770 if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
70771 duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
70772 duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
70773 DUK_ASSERT(h1 != NULL);
70774 DUK_ASSERT(h2 != NULL);
70775
70776 rc = duk_js_string_compare(h1, h2);
70777 if (rc < 0) {
70778 goto lt_true;
70779 } else {
70780 goto lt_false;
70781 }
70782 } else {
70783 /* Ordering should not matter (E5 Section 11.8.5, step 3.a) but
70784 * preserve it just in case.
70785 */
70786
70788 d1 = duk_to_number(ctx, -2);
70789 d2 = duk_to_number(ctx, -1);
70790 } else {
70791 d2 = duk_to_number(ctx, -1);
70792 d1 = duk_to_number(ctx, -2);
70793 }
70794
70796 s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
70798 s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
70799
70800 if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
70801 goto lt_undefined;
70802 }
70803
70804 if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
70805 /* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
70806 * steps e, f, and g.
70807 */
70808 goto lt_false;
70809 }
70810
70811 if (d1 == d2) {
70812 goto lt_false;
70813 }
70814
70815 if (c1 == DUK_FP_INFINITE && s1 == 0) {
70816 /* x == +Infinity */
70817 goto lt_false;
70818 }
70819
70820 if (c2 == DUK_FP_INFINITE && s2 == 0) {
70821 /* y == +Infinity */
70822 goto lt_true;
70823 }
70824
70825 if (c2 == DUK_FP_INFINITE && s2 != 0) {
70826 /* y == -Infinity */
70827 goto lt_false;
70828 }
70829
70830 if (c1 == DUK_FP_INFINITE && s1 != 0) {
70831 /* x == -Infinity */
70832 goto lt_true;
70833 }
70834
70835 if (d1 < d2) {
70836 goto lt_true;
70837 }
70838
70839 goto lt_false;
70840 }
70841
70842 lt_undefined:
70843 /* Note: undefined from Section 11.8.5 always results in false
70844 * return (see e.g. Section 11.8.3) - hence special treatment here.
70845 */
70846 retval = 0;
70847 goto cleanup;
70848
70849 lt_true:
70850 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70851 retval = 0;
70852 goto cleanup;
70853 } else {
70854 retval = 1;
70855 goto cleanup;
70856 }
70857 /* never here */
70858
70859 lt_false:
70860 if (flags & DUK_COMPARE_FLAG_NEGATE) {
70861 retval = 1;
70862 goto cleanup;
70863 } else {
70864 retval = 0;
70865 goto cleanup;
70866 }
70867 /* never here */
70868
70869 cleanup:
70870 duk_pop_2(ctx);
70871 return retval;
70872}
70873
70874/*
70875 * instanceof
70876 */
70878/*
70879 * E5 Section 11.8.6 describes the main algorithm, which uses
70880 * [[HasInstance]]. [[HasInstance]] is defined for only
70881 * function objects:
70882 *
70883 * - Normal functions:
70884 * E5 Section 15.3.5.3
70885 * - Functions established with Function.prototype.bind():
70886 * E5 Section 15.3.4.5.3
70887 *
70888 * For other objects, a TypeError is thrown.
70889 *
70890 * Limited Proxy support: don't support 'getPrototypeOf' trap but
70891 * continue lookup in Proxy target if the value is a Proxy.
70892 */
70893
70895 duk_context *ctx = (duk_context *) thr;
70896 duk_hobject *func;
70897 duk_hobject *val;
70899 duk_uint_t sanity;
70900
70901 /*
70902 * Get the values onto the stack first. It would be possible to cover
70903 * some normal cases without resorting to the value stack.
70904 *
70905 * The right hand side could be a light function (as they generally
70906 * behave like objects). Light functions never have a 'prototype'
70907 * property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
70908 * Using duk_require_hobject() is thus correct (except for error msg).
70909 */
70910
70911 duk_push_tval(ctx, tv_x);
70912 duk_push_tval(ctx, tv_y);
70913 func = duk_require_hobject(ctx, -1);
70914
70915 /*
70916 * For bound objects, [[HasInstance]] just calls the target function
70917 * [[HasInstance]]. If that is again a bound object, repeat until
70918 * we find a non-bound Function object.
70919 */
70920
70921 /* XXX: this bound function resolution also happens elsewhere,
70922 * move into a shared helper.
70923 */
70924
70926 do {
70927 /* check func supports [[HasInstance]] (this is checked for every function
70928 * in the bound chain, including the final one)
70929 */
70930
70931 if (!DUK_HOBJECT_IS_CALLABLE(func)) {
70932 /*
70933 * Note: of native Ecmascript objects, only Function instances
70934 * have a [[HasInstance]] internal property. Custom objects might
70935 * also have it, but not in current implementation.
70936 *
70937 * XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
70938 */
70939 DUK_ERROR_TYPE(thr, "invalid instanceof rval");
70940 }
70941
70942 if (!DUK_HOBJECT_HAS_BOUND(func)) {
70943 break;
70944 }
70945
70946 /* [ ... lval rval ] */
70947
70948 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [ ... lval rval new_rval ] */
70949 duk_replace(ctx, -1); /* -> [ ... lval new_rval ] */
70950 func = duk_require_hobject(ctx, -1);
70951
70952 /* func support for [[HasInstance]] checked in the beginning of the loop */
70953 } while (--sanity > 0);
70954
70955 if (sanity == 0) {
70957 }
70958
70959 /*
70960 * 'func' is now a non-bound object which supports [[HasInstance]]
70961 * (which here just means DUK_HOBJECT_FLAG_CALLABLE). Move on
70962 * to execute E5 Section 15.3.5.3.
70963 */
70964
70967
70968 /* [ ... lval rval(func) ] */
70969
70970 /* Handle lightfuncs through object coercion for now. */
70971 /* XXX: direct implementation */
70972 val = duk_get_hobject_or_lfunc_coerce(ctx, -2);
70973 if (!val) {
70974 goto pop_and_false;
70975 }
70976
70977 duk_get_prop_stridx(ctx, -1, DUK_STRIDX_PROTOTYPE); /* -> [ ... lval rval rval.prototype ] */
70978 proto = duk_require_hobject(ctx, -1);
70979 duk_pop(ctx); /* -> [ ... lval rval ] */
70980
70981 DUK_ASSERT(val != NULL);
70982
70983#if defined(DUK_USE_ES6_PROXY)
70984 val = duk_hobject_resolve_proxy_target(thr, val);
70985 DUK_ASSERT(val != NULL);
70986#endif
70987
70989 do {
70990 /*
70991 * Note: prototype chain is followed BEFORE first comparison. This
70992 * means that the instanceof lval is never itself compared to the
70993 * rval.prototype property. This is apparently intentional, see E5
70994 * Section 15.3.5.3, step 4.a.
70995 *
70996 * Also note:
70997 *
70998 * js> (function() {}) instanceof Function
70999 * true
71000 * js> Function instanceof Function
71001 * true
71002 *
71003 * For the latter, h_proto will be Function.prototype, which is the
71004 * built-in Function prototype. Because Function.[[Prototype]] is
71005 * also the built-in Function prototype, the result is true.
71006 */
71007
71008 DUK_ASSERT(val != NULL);
71009 val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
71010
71011 if (!val) {
71012 goto pop_and_false;
71013 }
71014
71015 DUK_ASSERT(val != NULL);
71016#if defined(DUK_USE_ES6_PROXY)
71017 val = duk_hobject_resolve_proxy_target(thr, val);
71018#endif
71019
71020 if (val == proto) {
71021 goto pop_and_true;
71022 }
71023
71024 /* follow prototype chain */
71025 } while (--sanity > 0);
71026
71027 if (sanity == 0) {
71029 }
71031
71032 pop_and_false:
71033 duk_pop_2(ctx);
71034 return 0;
71035
71036 pop_and_true:
71037 duk_pop_2(ctx);
71038 return 1;
71039}
71040
71041/*
71042 * in
71043 */
71044
71045/*
71046 * E5 Sections 11.8.7, 8.12.6.
71047 *
71048 * Basically just a property existence check using [[HasProperty]].
71049 */
71050
71052 duk_context *ctx = (duk_context *) thr;
71053 duk_bool_t retval;
71054
71055 /*
71056 * Get the values onto the stack first. It would be possible to cover
71057 * some normal cases without resorting to the value stack (e.g. if
71058 * lval is already a string).
71059 */
71060
71061 /* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
71062 * must be string coerced before the internal HasProperty() algorithm is
71063 * invoked. A fast path skipping coercion could be safely implemented for
71064 * numbers (as number-to-string coercion has no side effects). For ES6
71065 * proxy behavior, the trap 'key' argument must be in a string coerced
71066 * form (which is a shame).
71067 */
71068
71069 /* TypeError if rval is not an object (or lightfunc which should behave
71070 * like a Function instance).
71071 */
71072 duk_push_tval(ctx, tv_x);
71073 duk_push_tval(ctx, tv_y);
71075 duk_to_string(ctx, -2); /* coerce lval with ToString() */
71076
71077 retval = duk_hobject_hasprop(thr,
71078 DUK_GET_TVAL_NEGIDX(ctx, -1),
71079 DUK_GET_TVAL_NEGIDX(ctx, -2));
71080
71081 duk_pop_2(ctx);
71082 return retval;
71083}
71084
71085/*
71086 * typeof
71087 *
71088 * E5 Section 11.4.3.
71089 *
71090 * Very straightforward. The only question is what to return for our
71091 * non-standard tag / object types.
71092 *
71093 * There is an unfortunate string constant define naming problem with
71094 * typeof return values for e.g. "Object" and "object"; careful with
71095 * the built-in string defines. The LC_XXX defines are used for the
71096 * lowercase variants now.
71097 */
71098
71100 duk_small_int_t stridx = 0;
71101
71102 DUK_UNREF(thr);
71103
71104 switch (DUK_TVAL_GET_TAG(tv_x)) {
71105 case DUK_TAG_UNDEFINED: {
71106 stridx = DUK_STRIDX_LC_UNDEFINED;
71107 break;
71108 }
71109 case DUK_TAG_NULL: {
71110 /* Note: not a typo, "object" is returned for a null value */
71111 stridx = DUK_STRIDX_LC_OBJECT;
71112 break;
71113 }
71114 case DUK_TAG_BOOLEAN: {
71115 stridx = DUK_STRIDX_LC_BOOLEAN;
71116 break;
71117 }
71118 case DUK_TAG_POINTER: {
71119 /* implementation specific */
71120 stridx = DUK_STRIDX_LC_POINTER;
71121 break;
71122 }
71123 case DUK_TAG_STRING: {
71124 stridx = DUK_STRIDX_LC_STRING;
71125 break;
71126 }
71127 case DUK_TAG_OBJECT: {
71128 duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
71129 DUK_ASSERT(obj != NULL);
71130 if (DUK_HOBJECT_IS_CALLABLE(obj)) {
71131 stridx = DUK_STRIDX_LC_FUNCTION;
71132 } else {
71133 stridx = DUK_STRIDX_LC_OBJECT;
71134 }
71135 break;
71136 }
71137 case DUK_TAG_BUFFER: {
71138 /* implementation specific */
71139 stridx = DUK_STRIDX_LC_BUFFER;
71140 break;
71141 }
71142 case DUK_TAG_LIGHTFUNC: {
71143 stridx = DUK_STRIDX_LC_FUNCTION;
71144 break;
71145 }
71146#if defined(DUK_USE_FASTINT)
71147 case DUK_TAG_FASTINT:
71148#endif
71149 default: {
71150 /* number */
71153 stridx = DUK_STRIDX_LC_NUMBER;
71154 break;
71156 }
71157
71158 DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
71159 return DUK_HTHREAD_GET_STRING(thr, stridx);
71160}
71161
71162/*
71163 * Array index and length
71164 *
71165 * Array index: E5 Section 15.4
71166 * Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
71167 *
71168 * The DUK_HSTRING_GET_ARRIDX_SLOW() and DUK_HSTRING_GET_ARRIDX_FAST() macros
71169 * call duk_js_to_arrayindex_string_helper().
71170 */
71171
71172DUK_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) {
71173 duk_uarridx_t res, new_res;
71174
71175 if (blen == 0 || blen > 10) {
71176 goto parse_fail;
71177 }
71178 if (str[0] == (duk_uint8_t) '0' && blen > 1) {
71179 goto parse_fail;
71180 }
71181
71182 /* Accept 32-bit decimal integers, no leading zeroes, signs, etc.
71183 * Leading zeroes are not accepted (zero index "0" is an exception
71184 * handled above).
71185 */
71186
71187 res = 0;
71188 while (blen-- > 0) {
71189 duk_uint8_t c = *str++;
71190 if (c >= (duk_uint8_t) '0' && c <= (duk_uint8_t) '9') {
71191 new_res = res * 10 + (duk_uint32_t) (c - (duk_uint8_t) '0');
71192 if (new_res < res) {
71193 /* overflow, more than 32 bits -> not an array index */
71194 goto parse_fail;
71195 }
71196 res = new_res;
71197 } else {
71198 goto parse_fail;
71199 }
71200 }
71201
71202 *out_idx = res;
71203 return 1;
71204
71205 parse_fail:
71206 *out_idx = DUK_HSTRING_NO_ARRAY_INDEX;
71207 return 0;
71208}
71209
71210/* Called by duk_hstring.h macros */
71212 duk_uarridx_t res;
71213 duk_small_int_t rc;
71214
71215 if (!DUK_HSTRING_HAS_ARRIDX(h)) {
71217 }
71218
71221 &res);
71222 DUK_UNREF(rc);
71223 DUK_ASSERT(rc != 0);
71224 return res;
71225}
71226#line 1 "duk_js_var.c"
71227/*
71228 * Identifier access and function closure handling.
71229 *
71230 * Provides the primitives for slow path identifier accesses: GETVAR,
71231 * PUTVAR, DELVAR, etc. The fast path, direct register accesses, should
71232 * be used for most identifier accesses. Consequently, these slow path
71233 * primitives should be optimized for maximum compactness.
71234 *
71235 * Ecmascript environment records (declarative and object) are represented
71236 * as internal objects with control keys. Environment records have a
71237 * parent record ("outer environment reference") which is represented by
71238 * the implicit prototype for technical reasons (in other words, it is a
71239 * convenient field). The prototype chain is not followed in the ordinary
71240 * sense for variable lookups.
71241 *
71242 * See identifier-handling.rst for more details on the identifier algorithms
71243 * and the internal representation. See function-objects.rst for details on
71244 * what function templates and instances are expected to look like.
71245 *
71246 * Care must be taken to avoid duk_tval pointer invalidation caused by
71247 * e.g. value stack or object resizing.
71248 *
71249 * TODO: properties for function instances could be initialized much more
71250 * efficiently by creating a property allocation for a certain size and
71251 * filling in keys and values directly (and INCREFing both with "bulk incref"
71252 * primitives.
71253 *
71254 * XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
71255 * awkward (especially because they follow the prototype chain); rework
71256 * if "raw" own property helpers are added.
71257 */
71258
71259/* include removed: duk_internal.h */
71260
71261/*
71262 * Local result type for duk__get_identifier_reference() lookup.
71263 */
71264
71265typedef struct {
71266 duk_hobject *holder; /* for object-bound identifiers */
71267 duk_tval *value; /* for register-bound and declarative env identifiers */
71268 duk_int_t attrs; /* property attributes for identifier (relevant if value != NULL) */
71269 duk_tval *this_binding;
71270 duk_hobject *env;
71272
71273/*
71274 * Create a new function object based on a "template function" which contains
71275 * compiled bytecode, constants, etc, but lacks a lexical environment.
71276 *
71277 * Ecmascript requires that each created closure is a separate object, with
71278 * its own set of editable properties. However, structured property values
71279 * (such as the formal arguments list and the variable map) are shared.
71280 * Also the bytecode, constants, and inner functions are shared.
71281 *
71282 * See E5 Section 13.2 for detailed requirements on the function objects;
71283 * there are no similar requirements for function "templates" which are an
71284 * implementation dependent internal feature. Also see function-objects.rst
71285 * for a discussion on the function instance properties provided by this
71286 * implementation.
71287 *
71288 * Notes:
71289 *
71290 * * Order of internal properties should match frequency of use, since the
71291 * properties will be linearly scanned on lookup (functions usually don't
71292 * have enough properties to warrant a hash part).
71293 *
71294 * * The created closure is independent of its template; they do share the
71295 * same 'data' buffer object, but the template object itself can be freed
71296 * even if the closure object remains reachable.
71297 */
71298
71300 duk_tval *tv, *tv_end;
71301 duk_hobject **funcs, **funcs_end;
71302
71303 /* If function creation fails due to out-of-memory, the data buffer
71304 * pointer may be NULL in some cases. That's actually possible for
71305 * GC code, but shouldn't be possible here because the incomplete
71306 * function will be unwound from the value stack and never instantiated.
71307 */
71309 DUK_UNREF(thr);
71310
71313 while (tv < tv_end) {
71314 DUK_TVAL_INCREF(thr, tv);
71315 tv++;
71317
71319 funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
71320 while (funcs < funcs_end) {
71322 funcs++;
71323 }
71324}
71325
71326/* Push a new closure on the stack.
71328 * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
71329 * is created when the function is called, only outer_lex_env matters
71330 * (outer_var_env is ignored and may or may not be same as outer_lex_env).
71331 */
71332
71333DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
71334 /* order: most frequent to least frequent */
71341};
71342
71345 duk_hcompiledfunction *fun_temp,
71346 duk_hobject *outer_var_env,
71347 duk_hobject *outer_lex_env,
71348 duk_bool_t add_auto_proto) {
71349 duk_context *ctx = (duk_context *) thr;
71350 duk_hcompiledfunction *fun_clos;
71352 duk_uint_t len_value;
71353
71354 DUK_ASSERT(fun_temp != NULL);
71358 DUK_ASSERT(outer_var_env != NULL);
71359 DUK_ASSERT(outer_lex_env != NULL);
71360 DUK_UNREF(len_value);
71361
71363 duk_push_hobject(ctx, &fun_temp->obj); /* -> [ ... closure template ] */
71364
71365 fun_clos = (duk_hcompiledfunction *) duk_get_hcompiledfunction(ctx, -2);
71366 DUK_ASSERT(fun_clos != NULL);
71371
71375
71376 /* Note: all references inside 'data' need to get their refcounts
71377 * upped too. This is the case because refcounts are decreased
71378 * through every function referencing 'data' independently.
71379 */
71380
71382 duk__inc_data_inner_refcounts(thr, fun_temp);
71383
71384 fun_clos->nregs = fun_temp->nregs;
71385 fun_clos->nargs = fun_temp->nargs;
71386#if defined(DUK_USE_DEBUGGER_SUPPORT)
71387 fun_clos->start_line = fun_temp->start_line;
71388 fun_clos->end_line = fun_temp->end_line;
71389#endif
71390
71394
71395 /* XXX: could also copy from template, but there's no way to have any
71396 * other value here now (used code has no access to the template).
71397 */
71399
71400 /*
71401 * Init/assert flags, copying them where appropriate. Some flags
71402 * (like NEWENV) are processed separately below.
71403 */
71404
71405 /* XXX: copy flags using a mask */
71406
71408 DUK_HOBJECT_SET_CONSTRUCTABLE(&fun_clos->obj); /* Note: not set in template (has no "prototype") */
71410 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&fun_clos->obj));
71414 /* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
71415 if (DUK_HOBJECT_HAS_STRICT(&fun_temp->obj)) {
71416 DUK_HOBJECT_SET_STRICT(&fun_clos->obj);
71417 }
71418 if (DUK_HOBJECT_HAS_NOTAIL(&fun_temp->obj)) {
71419 DUK_HOBJECT_SET_NOTAIL(&fun_clos->obj);
71420 }
71421 /* DUK_HOBJECT_FLAG_NEWENV: handled below */
71422 if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) {
71423 /* Although NAMEBINDING is not directly needed for using
71424 * function instances, it's needed by bytecode dump/load
71425 * so copy it too.
71426 */
71427 DUK_HOBJECT_SET_NAMEBINDING(&fun_clos->obj);
71428 }
71429 if (DUK_HOBJECT_HAS_CREATEARGS(&fun_temp->obj)) {
71430 DUK_HOBJECT_SET_CREATEARGS(&fun_clos->obj);
71431 }
71435
71436 /*
71437 * Setup environment record properties based on the template and
71438 * its flags.
71439 *
71440 * If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
71441 * records represent identifiers "outside" the function; the
71442 * "inner" environment records are created on demand. Otherwise,
71443 * the environment records are those that will be directly used
71444 * (e.g. for declarations).
71445 *
71446 * _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
71447 * so _Varenv is only set if _Lexenv != _Varenv.
71448 *
71449 * This is relatively complex, see doc/identifier-handling.rst.
71450 */
71451
71452 if (DUK_HOBJECT_HAS_NEWENV(&fun_temp->obj)) {
71453 DUK_HOBJECT_SET_NEWENV(&fun_clos->obj);
71454
71455 if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) {
71457
71458 /*
71459 * Named function expression, name needs to be bound
71460 * in an intermediate environment record. The "outer"
71461 * lexical/variable environment will thus be:
71462 *
71463 * a) { funcname: <func>, __prototype: outer_lex_env }
71464 * b) { funcname: <func>, __prototype: <globalenv> } (if outer_lex_env missing)
71465 */
71466
71467 DUK_ASSERT(duk_has_prop_stridx(ctx, -1, DUK_STRIDX_NAME)); /* required if NAMEBINDING set */
71468
71469 if (outer_lex_env) {
71470 proto = outer_lex_env;
71471 } else {
71473 }
71474
71475 /* -> [ ... closure template env ] */
71479 proto);
71480
71481 /* It's important that duk_xdef_prop() is a 'raw define' so that any
71482 * properties in an ancestor are never an issue (they should never be
71483 * e.g. non-writable, but just in case).
71484 */
71485 duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME); /* -> [ ... closure template env funcname ] */
71486 duk_dup(ctx, -4); /* -> [ ... closure template env funcname closure ] */
71487 duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template env ] */
71488 /* env[funcname] = closure */
71489
71490 /* [ ... closure template env ] */
71491
71493 /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
71494 * will be ignored anyway
71495 */
71496
71497 /* [ ... closure template ] */
71498 } else {
71499 /*
71500 * Other cases (function declaration, anonymous function expression,
71501 * strict direct eval code). The "outer" environment will be whatever
71502 * the caller gave us.
71503 */
71504
71505 duk_push_hobject(ctx, outer_lex_env); /* -> [ ... closure template env ] */
71507 /* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
71508 * will be ignored anyway
71509 */
71510
71511 /* [ ... closure template ] */
71512 }
71513 } else {
71514 /*
71515 * Function gets no new environment when called. This is the
71516 * case for global code, indirect eval code, and non-strict
71517 * direct eval code. There is no direct correspondence to the
71518 * E5 specification, as global/eval code is not exposed as a
71519 * function.
71520 */
71521
71523
71524 duk_push_hobject(ctx, outer_lex_env); /* -> [ ... closure template env ] */
71526
71527 if (outer_var_env != outer_lex_env) {
71528 duk_push_hobject(ctx, outer_var_env); /* -> [ ... closure template env ] */
71530 }
71531 }
71532#ifdef DUK_USE_DDDPRINT
71535 DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipT, lexenv -> %!ipT",
71536 (duk_tval *) duk_get_tval(ctx, -2),
71537 (duk_tval *) duk_get_tval(ctx, -1)));
71538 duk_pop_2(ctx);
71539#endif
71540
71541 /*
71542 * Copy some internal properties directly
71543 *
71544 * The properties will be writable and configurable, but not enumerable.
71545 */
71546
71547 /* [ ... closure template ] */
71548
71549 DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
71550 (duk_tval *) duk_get_tval(ctx, -2),
71551 (duk_tval *) duk_get_tval(ctx, -1)));
71552
71553 for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
71555 if (duk_get_prop_stridx(ctx, -1, stridx)) {
71556 /* [ ... closure template val ] */
71557 DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
71559 } else {
71560 DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
71561 duk_pop(ctx);
71562 }
71563 }
71564
71565 /*
71566 * "length" maps to number of formals (E5 Section 13.2) for function
71567 * declarations/expressions (non-bound functions). Note that 'nargs'
71568 * is NOT necessarily equal to the number of arguments.
71569 */
71570
71571 /* [ ... closure template ] */
71572
71573 len_value = 0;
71574
71575 /* XXX: use helper for size optimization */
71577 /* [ ... closure template formals ] */
71579 DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_UINT_MAX); /* formal arg limits */
71580 len_value = (duk_uint_t) duk_get_length(ctx, -1);
71581 } else {
71582 /* XXX: what to do if _Formals is not empty but compiler has
71583 * optimized it away -- read length from an explicit property
71584 * then?
71585 */
71586 }
71587 duk_pop(ctx);
71588
71589 duk_push_uint(ctx, len_value); /* [ ... closure template len_value ] */
71591
71592 /*
71593 * "prototype" is, by default, a fresh object with the "constructor"
71594 * property.
71595 *
71596 * Note that this creates a circular reference for every function
71597 * instance (closure) which prevents refcount-based collection of
71598 * function instances.
71599 *
71600 * XXX: Try to avoid creating the default prototype object, because
71601 * many functions are not used as constructors and the default
71602 * prototype is unnecessary. Perhaps it could be created on-demand
71603 * when it is first accessed?
71604 */
71605
71606 /* [ ... closure template ] */
71607
71608 if (add_auto_proto) {
71609 duk_push_object(ctx); /* -> [ ... closure template newobj ] */
71610 duk_dup(ctx, -3); /* -> [ ... closure template newobj closure ] */
71611 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* -> [ ... closure template newobj ] */
71612 duk_compact(ctx, -1); /* compact the prototype */
71613 duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); /* -> [ ... closure template ] */
71614 }
71615
71616 /*
71617 * "arguments" and "caller" must be mapped to throwers for strict
71618 * mode and bound functions (E5 Section 15.3.5).
71619 *
71620 * XXX: This is expensive to have for every strict function instance.
71621 * Try to implement as virtual properties or on-demand created properties.
71622 */
71623
71624 /* [ ... closure template ] */
71625
71626 if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
71629 } else {
71630#ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
71631 DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
71632 duk_push_null(ctx);
71634#else
71635 DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
71636#endif
71637 }
71638
71639 /*
71640 * "name" is a non-standard property found in at least V8, Rhino, smjs.
71641 * For Rhino and smjs it is non-writable, non-enumerable, and non-configurable;
71642 * for V8 it is writable, non-enumerable, non-configurable. It is also defined
71643 * for an anonymous function expression in which case the value is an empty string.
71644 * We could also leave name 'undefined' for anonymous functions but that would
71645 * differ from behavior of other engines, so use an empty string.
71646 *
71647 * XXX: make optional? costs something per function.
71648 */
71649
71650 /* [ ... closure template ] */
71651
71652 if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME)) {
71653 /* [ ... closure template name ] */
71654 DUK_ASSERT(duk_is_string(ctx, -1));
71655 } else {
71656 /* [ ... closure template undefined ] */
71657 duk_pop(ctx);
71659 }
71660 duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template ] */
71661
71662 /*
71663 * Compact the closure, in most cases no properties will be added later.
71664 * Also, without this the closures end up having unused property slots
71665 * (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
71666 * A better future solution would be to allocate the closure directly
71667 * to correct size (and setup the properties directly without going
71668 * through the API).
71669 */
71670
71671 duk_compact(ctx, -2);
71672
71673 /*
71674 * Some assertions (E5 Section 13.2).
71675 */
71676
71681 DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE) != 0);
71682 DUK_ASSERT(duk_has_prop_stridx(ctx, -2, DUK_STRIDX_NAME) != 0); /* non-standard */
71683 DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
71684 duk_has_prop_stridx(ctx, -2, DUK_STRIDX_CALLER) != 0);
71685 DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
71687
71688 /*
71689 * Finish
71690 */
71691
71692 /* [ ... closure template ] */
71693
71694 DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
71696 (duk_tval *) duk_get_tval(ctx, -2)));
71697
71698 duk_pop(ctx);
71699
71700 /* [ ... closure ] */
71701}
71702
71703/*
71704 * Delayed activation environment record initialization (for functions
71705 * with NEWENV).
71706 *
71707 * The non-delayed initialization is handled by duk_handle_call().
71708 */
71709
71710/* shared helper */
71713 duk_hobject *func,
71714 duk_size_t idx_bottom) {
71715 duk_context *ctx = (duk_context *) thr;
71716 duk_hobject *env;
71717 duk_hobject *parent;
71718 duk_tval *tv;
71719
71720 DUK_ASSERT(thr != NULL);
71721 DUK_ASSERT(func != NULL);
71722
71724 if (tv) {
71727 parent = DUK_TVAL_GET_OBJECT(tv);
71728 } else {
71729 parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
71730 }
71731
71732 (void) duk_push_object_helper(ctx,
71735 -1); /* no prototype, updated below */
71736 env = duk_require_hobject(ctx, -1);
71737 DUK_ASSERT(env != NULL);
71738 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, env, parent); /* parent env is the prototype */
71739
71740 /* open scope information, for compiled functions only */
71741
71743 duk_push_hthread(ctx, thr);
71745 duk_push_hobject(ctx, func);
71747 duk_push_size_t(ctx, idx_bottom);
71749 }
71750
71751 return env;
71752}
71753
71756 duk_activation *act) {
71757 duk_context *ctx = (duk_context *) thr;
71758 duk_hobject *func;
71759 duk_hobject *env;
71760
71761 func = DUK_ACT_GET_FUNC(act);
71762 DUK_ASSERT(func != NULL);
71763 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func)); /* bound functions are never in act 'func' */
71764
71765 /*
71766 * Delayed initialization only occurs for 'NEWENV' functions.
71767 */
71768
71770 DUK_ASSERT(act->lex_env == NULL);
71771 DUK_ASSERT(act->var_env == NULL);
71772
71774 DUK_ASSERT(env != NULL);
71775
71776 DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
71777#ifdef DUK_USE_DDDPRINT
71778 {
71779 duk_hobject *p = env;
71780 while (p) {
71781 DUK_DDD(DUK_DDDPRINT(" -> %!ipO", (duk_heaphdr *) p));
71782 p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
71783 }
71784 }
71785#endif
71786
71787 act->lex_env = env;
71788 act->var_env = env;
71789 DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (here 2 times) */
71790 DUK_HOBJECT_INCREF(thr, env);
71791
71792 duk_pop(ctx);
71794
71795/*
71796 * Closing environment records.
71797 *
71798 * The environment record MUST be closed with the thread where its activation
71799 * is. In other words (if 'env' is open):
71800 *
71801 * - 'thr' must match _env.thread
71802 * - 'func' must match _env.callee
71803 * - 'regbase' must match _env.regbase
71804 *
71805 * These are not looked up from the env to minimize code size.
71806 *
71807 * XXX: should access the own properties directly instead of using the API
71808 */
71809
71811 duk_context *ctx = (duk_context *) thr;
71813
71814 DUK_ASSERT(thr != NULL);
71815 DUK_ASSERT(env != NULL);
71816 /* func is NULL for lightfuncs */
71817
71819 DUK_DDD(DUK_DDDPRINT("environment record not a declarative record, "
71820 "or already closed: %!iO",
71821 (duk_heaphdr *) env));
71822 return;
71823 }
71824
71825 DUK_DDD(DUK_DDDPRINT("closing environment record: %!iO, func: %!iO, regbase: %ld",
71826 (duk_heaphdr *) env, (duk_heaphdr *) func, (long) regbase));
71827
71828 duk_push_hobject(ctx, env);
71829
71830 /* assertions: env must be closed in the same thread as where it runs */
71831#ifdef DUK_USE_ASSERTIONS
71832 {
71833 /* [... env] */
71834
71836 DUK_ASSERT(duk_is_object(ctx, -1));
71837 DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) func);
71838 }
71839 duk_pop(ctx);
71840
71842 DUK_ASSERT(duk_is_object(ctx, -1));
71843 DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) thr);
71844 }
71845 duk_pop(ctx);
71846
71848 DUK_ASSERT(duk_is_number(ctx, -1));
71849 DUK_ASSERT(duk_get_number(ctx, -1) == (double) regbase);
71850 }
71851 duk_pop(ctx);
71852
71853 /* [... env] */
71854 }
71855#endif
71856
71857 if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
71858 duk_hobject *varmap;
71859 duk_hstring *key;
71860 duk_tval *tv;
71861 duk_uint_t regnum;
71862
71863 /* XXX: additional conditions when to close variables? we don't want to do it
71864 * unless the environment may have "escaped" (referenced in a function closure).
71865 * With delayed environments, the existence is probably good enough of a check.
71866 */
71867
71868 /* XXX: any way to detect faster whether something needs to be closed?
71869 * We now look up _Callee and then skip the rest.
71870 */
71871
71872 /* Note: we rely on the _Varmap having a bunch of nice properties, like:
71873 * - being compacted and unmodified during this process
71874 * - not containing an array part
71875 * - having correct value types
71876 */
71877
71878 /* [... env] */
71879
71881 DUK_DDD(DUK_DDDPRINT("env has no callee property, nothing to close; re-delete the control properties just in case"));
71882 duk_pop(ctx);
71883 goto skip_varmap;
71884 }
71885
71886 /* [... env callee] */
71887
71889 DUK_DDD(DUK_DDDPRINT("callee has no varmap property, nothing to close; delete the control properties"));
71890 duk_pop_2(ctx);
71891 goto skip_varmap;
71892 }
71893 varmap = duk_require_hobject(ctx, -1);
71894 DUK_ASSERT(varmap != NULL);
71895
71896 DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
71897
71898 /* [... env callee varmap] */
71899
71900 DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
71901
71902 for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
71903 key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
71904 DUK_ASSERT(key != NULL); /* assume keys are compacted */
71905
71906 DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
71907
71908 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
71909 DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* assume value is a number */
71910 regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
71911 DUK_ASSERT_DISABLE(regnum >= 0); /* unsigned */
71912 DUK_ASSERT(regnum < ((duk_hcompiledfunction *) func)->nregs); /* regnum is sane */
71913 DUK_ASSERT(thr->valstack + regbase + regnum >= thr->valstack);
71914 DUK_ASSERT(thr->valstack + regbase + regnum < thr->valstack_top);
71915
71916 /* XXX: slightly awkward */
71917 duk_push_hstring(ctx, key);
71918 duk_push_tval(ctx, thr->valstack + regbase + regnum);
71919 DUK_DDD(DUK_DDDPRINT("closing identifier '%s' -> reg %ld, value %!T",
71920 (const char *) duk_require_string(ctx, -2),
71921 (long) regnum,
71922 (duk_tval *) duk_get_tval(ctx, -1)));
71923
71924 /* [... env callee varmap key val] */
71925
71926 /* if property already exists, overwrites silently */
71927 duk_xdef_prop(ctx, -5, DUK_PROPDESC_FLAGS_WE); /* writable but not deletable */
71928 }
71929
71930 duk_pop_2(ctx);
71931
71932 /* [... env] */
71933 }
71934
71935 skip_varmap:
71936
71937 /* [... env] */
71938
71942
71943 duk_pop(ctx);
71944
71946
71947 DUK_DDD(DUK_DDDPRINT("environment record after being closed: %!O",
71948 (duk_heaphdr *) env));
71949}
71950
71951/*
71952 * GETIDREF: a GetIdentifierReference-like helper.
71953 *
71954 * Provides a parent traversing lookup and a single level lookup
71955 * (for HasBinding).
71956 *
71957 * Instead of returning the value, returns a bunch of values allowing
71958 * the caller to read, write, or delete the binding. Value pointers
71959 * are duk_tval pointers which can be mutated directly as long as
71960 * refcounts are properly updated. Note that any operation which may
71961 * reallocate valstacks or compact objects may invalidate the returned
71962 * duk_tval (but not object) pointers, so caller must be very careful.
71963 *
71964 * If starting environment record 'env' is given, 'act' is ignored.
71965 * However, if 'env' is NULL, the caller may identify, in 'act', an
71966 * activation which hasn't had its declarative environment initialized
71967 * yet. The activation registers are then looked up, and its parent
71968 * traversed normally.
71969 *
71970 * The 'out' structure values are only valid if the function returns
71971 * success (non-zero).
71972 */
71973
71974/* lookup name from an open declarative record's registers */
71978 duk_hobject *env,
71979 duk__id_lookup_result *out) {
71980 duk_hthread *env_thr;
71981 duk_hobject *env_func;
71982 duk_size_t env_regbase;
71983 duk_hobject *varmap;
71984 duk_tval *tv;
71985 duk_size_t reg_rel;
71986 duk_size_t idx;
71987
71988 DUK_ASSERT(thr != NULL);
71989 DUK_ASSERT(name != NULL);
71990 DUK_ASSERT(env != NULL);
71991 DUK_ASSERT(out != NULL);
71992
71994
71996 if (!tv) {
71997 /* env is closed, should be missing _Callee, _Thread, _Regbase */
72001 return 0;
72002 }
72003
72007 env_func = DUK_TVAL_GET_OBJECT(tv);
72008 DUK_ASSERT(env_func != NULL);
72009
72011 if (!tv) {
72012 return 0;
72013 }
72015 varmap = DUK_TVAL_GET_OBJECT(tv);
72016 DUK_ASSERT(varmap != NULL);
72017
72019 if (!tv) {
72020 return 0;
72021 }
72023 reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
72024 DUK_ASSERT_DISABLE(reg_rel >= 0); /* unsigned */
72025 DUK_ASSERT(reg_rel < ((duk_hcompiledfunction *) env_func)->nregs);
72026
72028 DUK_ASSERT(tv != NULL);
72032 env_thr = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
72033 DUK_ASSERT(env_thr != NULL);
72034
72035 /* Note: env_thr != thr is quite possible and normal, so careful
72036 * with what thread is used for valstack lookup.
72037 */
72038
72040 DUK_ASSERT(tv != NULL);
72042 env_regbase = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
72043
72044 idx = env_regbase + reg_rel;
72045 tv = env_thr->valstack + idx;
72046 DUK_ASSERT(tv >= env_thr->valstack && tv < env_thr->valstack_end); /* XXX: more accurate? */
72047
72048 out->value = tv;
72049 out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
72050 out->this_binding = NULL; /* implicit this value always undefined for
72051 * declarative environment records.
72052 */
72053 out->env = env;
72054 out->holder = NULL;
72055
72056 return 1;
72057}
72058
72059/* lookup name from current activation record's functions' registers */
72063 duk_activation *act,
72064 duk__id_lookup_result *out) {
72065 duk_tval *tv;
72066 duk_hobject *func;
72067 duk_hobject *varmap;
72068 duk_size_t reg_rel;
72069 duk_size_t idx;
72070
72071 DUK_ASSERT(thr != NULL);
72072 DUK_ASSERT(name != NULL);
72073 DUK_ASSERT(act != NULL);
72074 DUK_ASSERT(out != NULL);
72075
72076 func = DUK_ACT_GET_FUNC(act);
72077 DUK_ASSERT(func != NULL);
72079
72081 return 0;
72082 }
72083
72085 if (!tv) {
72086 return 0;
72087 }
72089 varmap = DUK_TVAL_GET_OBJECT(tv);
72090 DUK_ASSERT(varmap != NULL);
72091
72093 if (!tv) {
72094 return 0;
72095 }
72097 reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
72098 DUK_ASSERT_DISABLE(reg_rel >= 0);
72099 DUK_ASSERT(reg_rel < ((duk_hcompiledfunction *) func)->nregs);
72101 idx = act->idx_bottom + reg_rel;
72102 DUK_ASSERT(idx >= act->idx_bottom);
72103 tv = thr->valstack + idx;
72104
72105 out->value = tv;
72106 out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
72107 out->this_binding = NULL; /* implicit this value always undefined for
72108 * declarative environment records.
72109 */
72110 out->env = NULL;
72111 out->holder = NULL;
72112
72113 return 1;
72114}
72115
72118 duk_hobject *env,
72120 duk_activation *act,
72121 duk_bool_t parents,
72122 duk__id_lookup_result *out) {
72123 duk_tval *tv;
72124 duk_tval *tv_target;
72125 duk_tval tv_name;
72126 duk_uint_t sanity;
72127
72128 DUK_ASSERT(thr != NULL);
72129 DUK_ASSERT(env != NULL || act != NULL);
72130 DUK_ASSERT(name != NULL);
72131 DUK_ASSERT(out != NULL);
72132
72133 DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
72135
72136 /*
72137 * Conceptually, we look for the identifier binding by starting from
72138 * 'env' and following to chain of environment records (represented
72139 * by the prototype chain).
72140 *
72141 * If 'env' is NULL, the current activation does not yet have an
72142 * allocated declarative environment record; this should be treated
72143 * exactly as if the environment record existed but had no bindings
72144 * other than register bindings.
72145 *
72146 * Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
72147 * the environment will always be initialized immediately; hence
72148 * a NULL 'env' should only happen with the flag set. This is the
72149 * case for: (1) function calls, and (2) strict, direct eval calls.
72150 */
72151
72152 if (env == NULL && act != NULL) {
72153 duk_hobject *func;
72154
72155 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
72156 "delayed env case, look up activation regs first"));
72157
72158 /*
72159 * Try registers
72160 */
72161
72162 if (duk__getid_activation_regs(thr, name, act, out)) {
72163 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72164 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72165 "(found from register bindings when env=NULL)",
72166 (duk_heaphdr *) name, (duk_tval *) out->value,
72167 (long) out->attrs, (duk_tval *) out->this_binding,
72168 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72169 return 1;
72170 }
72171
72172 DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
72173
72174 /*
72175 * Not found in registers, proceed to the parent record.
72176 * Here we need to determine what the parent would be,
72177 * if 'env' was not NULL (i.e. same logic as when initializing
72178 * the record).
72179 *
72180 * Note that environment initialization is only deferred when
72181 * DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
72182 * - Function code
72183 * - Strict eval code
72184 *
72185 * We only need to check _Lexenv here; _Varenv exists only if it
72186 * differs from _Lexenv (and thus _Lexenv will also be present).
72187 */
72188
72189 if (!parents) {
72190 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
72191 "(not found from register bindings when env=NULL)"));
72192 goto fail_not_found;
72193 }
72194
72195 func = DUK_ACT_GET_FUNC(act);
72196 DUK_ASSERT(func != NULL);
72198
72200 if (tv) {
72202 env = DUK_TVAL_GET_OBJECT(tv);
72203 } else {
72205 env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
72206 }
72207
72208 DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
72209 (duk_heaphdr *) env));
72210 }
72211
72212 /*
72213 * Prototype walking starting from 'env'.
72214 *
72215 * ('act' is not needed anywhere here.)
72216 */
72217
72219 while (env != NULL) {
72220 duk_small_int_t cl;
72221 duk_int_t attrs;
72222
72223 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
72224 (duk_heaphdr *) name,
72225 (void *) env,
72226 (duk_heaphdr *) env));
72227
72228 DUK_ASSERT(env != NULL);
72231
72234 if (cl == DUK_HOBJECT_CLASS_DECENV) {
72235 /*
72236 * Declarative environment record.
72237 *
72238 * Identifiers can never be stored in ancestors and are
72239 * always plain values, so we can use an internal helper
72240 * and access the value directly with an duk_tval ptr.
72241 *
72242 * A closed environment is only indicated by it missing
72243 * the "book-keeping" properties required for accessing
72244 * register-bound variables.
72245 */
72246
72248 /* already closed */
72249 goto skip_regs;
72250 }
72251
72252 if (duk__getid_open_decl_env_regs(thr, name, env, out)) {
72253 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72254 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72255 "(declarative environment record, scope open, found in regs)",
72256 (duk_heaphdr *) name, (duk_tval *) out->value,
72257 (long) out->attrs, (duk_tval *) out->this_binding,
72258 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72259 return 1;
72260 }
72261 skip_regs:
72262
72264 if (tv) {
72265 out->value = tv;
72266 out->attrs = attrs;
72267 out->this_binding = NULL; /* implicit this value always undefined for
72268 * declarative environment records.
72269 */
72270 out->env = env;
72271 out->holder = env;
72272
72273 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72274 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72275 "(declarative environment record, found in properties)",
72276 (duk_heaphdr *) name, (duk_tval *) out->value,
72277 (long) out->attrs, (duk_tval *) out->this_binding,
72278 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72279 return 1;
72280 }
72281 } else {
72282 /*
72283 * Object environment record.
72284 *
72285 * Binding (target) object is an external, uncontrolled object.
72286 * Identifier may be bound in an ancestor property, and may be
72287 * an accessor. Target can also be a Proxy which we must support
72288 * here.
72289 */
72290
72291 /* XXX: we could save space by using _Target OR _This. If _Target, assume
72292 * this binding is undefined. If _This, assumes this binding is _This, and
72293 * target is also _This. One property would then be enough.
72294 */
72295
72296 duk_hobject *target;
72297 duk_bool_t found;
72298
72300
72302 DUK_ASSERT(tv_target != NULL);
72303 DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
72304 target = DUK_TVAL_GET_OBJECT(tv_target);
72305 DUK_ASSERT(target != NULL);
72306
72307 /* Target may be a Proxy or property may be an accessor, so we must
72308 * use an actual, Proxy-aware hasprop check here.
72309 *
72310 * out->holder is NOT set to the actual duk_hobject where the
72311 * property is found, but rather the object binding target object.
72312 */
72313
72314 if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(target)) {
72315 DUK_ASSERT(name != NULL);
72316 DUK_TVAL_SET_STRING(&tv_name, name);
72317
72318 found = duk_hobject_hasprop(thr, tv_target, &tv_name);
72319 } else {
72320 /* XXX: duk_hobject_hasprop() would be correct for
72321 * non-Proxy objects too, but it is about ~20-25%
72322 * slower at present so separate code paths for
72323 * Proxy and non-Proxy now.
72324 */
72325 found = duk_hobject_hasprop_raw(thr, target, name);
72326 }
72327
72328 if (found) {
72329 out->value = NULL; /* can't get value, may be accessor */
72330 out->attrs = 0; /* irrelevant when out->value == NULL */
72332 out->this_binding = tv; /* may be NULL */
72333 out->env = env;
72334 out->holder = target;
72335
72336 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72337 "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72338 "(object environment record)",
72339 (duk_heaphdr *) name, (duk_tval *) out->value,
72340 (long) out->attrs, (duk_tval *) out->this_binding,
72341 (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72342 return 1;
72343 }
72344 }
72345
72346 if (!parents) {
72347 DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
72348 "(not found from first traversed env)"));
72349 goto fail_not_found;
72350 }
72351
72352 if (sanity-- == 0) {
72354 }
72355 env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
72356 };
72357
72358 /*
72359 * Not found (even in global object)
72360 */
72361
72362 fail_not_found:
72363 return 0;
72364}
72365
72366/*
72367 * HASVAR: check identifier binding from a given environment record
72368 * without traversing its parents.
72369 *
72370 * This primitive is not exposed to user code as such, but is used
72371 * internally for e.g. declaration binding instantiation.
72372 *
72373 * See E5 Sections:
72374 * 10.2.1.1.1 HasBinding(N)
72375 * 10.2.1.2.1 HasBinding(N)
72376 *
72377 * Note: strictness has no bearing on this check. Hence we don't take
72378 * a 'strict' parameter.
72379 */
72380
72381#if 0 /*unused*/
72383duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
72384 duk_hobject *env,
72385 duk_hstring *name) {
72387 duk_bool_t parents;
72388
72389 DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
72390 "(env -> %!dO)",
72391 (void *) thr, (void *) env, (duk_heaphdr *) name,
72392 (duk_heaphdr *) env));
72393
72394 DUK_ASSERT(thr != NULL);
72395 DUK_ASSERT(env != NULL);
72396 DUK_ASSERT(name != NULL);
72397
72400
72403
72404 /* lookup results is ignored */
72405 parents = 0;
72406 return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
72407}
72408#endif
72409
72410/*
72411 * GETVAR
72412 *
72413 * See E5 Sections:
72414 * 11.1.2 Identifier Reference
72415 * 10.3.1 Identifier Resolution
72416 * 11.13.1 Simple Assignment [example of where the Reference is GetValue'd]
72417 * 8.7.1 GetValue (V)
72418 * 8.12.1 [[GetOwnProperty]] (P)
72419 * 8.12.2 [[GetProperty]] (P)
72420 * 8.12.3 [[Get]] (P)
72421 *
72422 * If 'throw' is true, always leaves two values on top of stack: [val this].
72423 *
72424 * If 'throw' is false, returns 0 if identifier cannot be resolved, and the
72425 * stack will be unaffected in this case. If identifier is resolved, returns
72426 * 1 and leaves [val this] on top of stack.
72427 *
72428 * Note: the 'strict' flag of a reference returned by GetIdentifierReference
72429 * is ignored by GetValue. Hence we don't take a 'strict' parameter.
72430 *
72431 * The 'throw' flag is needed for implementing 'typeof' for an unreferenced
72432 * identifier. An unreference identifier in other contexts generates a
72433 * ReferenceError.
72434 */
72435
72438 duk_hobject *env,
72439 duk_activation *act,
72441 duk_bool_t throw_flag) {
72442 duk_context *ctx = (duk_context *) thr;
72444 duk_tval tv_tmp_obj;
72445 duk_tval tv_tmp_key;
72446 duk_bool_t parents;
72447
72448 DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
72449 "(env -> %!dO)",
72450 (void *) thr, (void *) env, (void *) act,
72451 (duk_heaphdr *) name, (duk_heaphdr *) env));
72452
72453 DUK_ASSERT(thr != NULL);
72454 DUK_ASSERT(name != NULL);
72455 /* env and act may be NULL */
72456
72459
72460 parents = 1; /* follow parent chain */
72461 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72462 if (ref.value) {
72463 DUK_ASSERT(ref.this_binding == NULL); /* always for register bindings */
72464 duk_push_tval(ctx, ref.value);
72465 duk_push_undefined(ctx);
72466 } else {
72467 DUK_ASSERT(ref.holder != NULL);
72468
72469 /* Note: getprop may invoke any getter and invalidate any
72470 * duk_tval pointers, so this must be done first.
72471 */
72472
72473 if (ref.this_binding) {
72474 duk_push_tval(ctx, ref.this_binding);
72475 } else {
72476 duk_push_undefined(ctx);
72477 }
72478
72479 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
72480 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72481 (void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key); /* [this value] */
72482
72483 /* ref.value, ref.this.binding invalidated here by getprop call */
72485 duk_insert(ctx, -2); /* [this value] -> [value this] */
72486 }
72487
72488 return 1;
72489 } else {
72490 if (throw_flag) {
72492 "identifier '%s' undefined",
72493 (const char *) DUK_HSTRING_GET_DATA(name));
72494 }
72495
72496 return 0;
72497 }
72498}
72499
72502 duk_hobject *env,
72504 duk_bool_t throw_flag) {
72505 return duk__getvar_helper(thr, env, NULL, name, throw_flag);
72506}
72507
72510 duk_activation *act,
72512 duk_bool_t throw_flag) {
72513 DUK_ASSERT(act != NULL);
72514 return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
72515}
72517/*
72518 * PUTVAR
72519 *
72520 * See E5 Sections:
72521 * 11.1.2 Identifier Reference
72522 * 10.3.1 Identifier Resolution
72523 * 11.13.1 Simple Assignment [example of where the Reference is PutValue'd]
72524 * 8.7.2 PutValue (V,W) [see especially step 3.b, undefined -> automatic global in non-strict mode]
72525 * 8.12.4 [[CanPut]] (P)
72526 * 8.12.5 [[Put]] (P)
72527 *
72528 * Note: may invalidate any valstack (or object) duk_tval pointers because
72529 * putting a value may reallocate any object or any valstack. Caller beware.
72530 */
72531
72534 duk_hobject *env,
72535 duk_activation *act,
72537 duk_tval *val,
72538 duk_bool_t strict) {
72540 duk_tval tv_tmp_obj;
72541 duk_tval tv_tmp_key;
72542 duk_bool_t parents;
72543
72544 DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
72545 "(env -> %!dO, val -> %!T)",
72546 (void *) thr, (void *) env, (void *) act,
72547 (duk_heaphdr *) name, (void *) val, (long) strict,
72548 (duk_heaphdr *) env, (duk_tval *) val));
72549
72550 DUK_ASSERT(thr != NULL);
72551 DUK_ASSERT(name != NULL);
72552 DUK_ASSERT(val != NULL);
72553 /* env and act may be NULL */
72554
72558
72559 /*
72560 * In strict mode E5 protects 'eval' and 'arguments' from being
72561 * assigned to (or even declared anywhere). Attempt to do so
72562 * should result in a compile time SyntaxError. See the internal
72563 * design documentation for details.
72564 *
72565 * Thus, we should never come here, run-time, for strict code,
72566 * and name 'eval' or 'arguments'.
72567 */
72568
72569 DUK_ASSERT(!strict ||
72570 (name != DUK_HTHREAD_STRING_EVAL(thr) &&
72572
72573 /*
72574 * Lookup variable and update in-place if found.
72575 */
72576
72577 parents = 1; /* follow parent chain */
72578
72579 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72580 if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
72581 /* Update duk_tval in-place if pointer provided and the
72582 * property is writable. If the property is not writable
72583 * (immutable binding), use duk_hobject_putprop() which
72584 * will respect mutability.
72585 */
72586 duk_tval *tv_val;
72587
72588 DUK_ASSERT(ref.this_binding == NULL); /* always for register bindings */
72589
72590 tv_val = ref.value;
72591 DUK_ASSERT(tv_val != NULL);
72592 DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val); /* side effects */
72593
72594 /* ref.value and ref.this_binding invalidated here */
72595 } else {
72596 DUK_ASSERT(ref.holder != NULL);
72597
72598 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
72599 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72600 (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
72601
72602 /* ref.value and ref.this_binding invalidated here */
72603 }
72604
72605 return;
72606 }
72607
72608 /*
72609 * Not found: write to global object (non-strict) or ReferenceError
72610 * (strict); see E5 Section 8.7.2, step 3.
72611 */
72612
72613 if (strict) {
72614 DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
72615 DUK_ERROR(thr, DUK_ERR_REFERENCE_ERROR, "identifier not defined");
72616 }
72617
72618 DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
72619
72620 DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
72621 DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72622 (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0); /* 0 = no throw */
72623
72624 /* NB: 'val' may be invalidated here because put_value may realloc valstack,
72625 * caller beware.
72626 */
72627}
72628
72631 duk_hobject *env,
72633 duk_tval *val,
72634 duk_bool_t strict) {
72635 duk__putvar_helper(thr, env, NULL, name, val, strict);
72636}
72637
72640 duk_activation *act,
72642 duk_tval *val,
72643 duk_bool_t strict) {
72644 DUK_ASSERT(act != NULL);
72645 duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
72646}
72647
72648/*
72649 * DELVAR
72650 *
72651 * See E5 Sections:
72652 * 11.4.1 The delete operator
72653 * 10.2.1.1.5 DeleteBinding (N) [declarative environment record]
72654 * 10.2.1.2.5 DeleteBinding (N) [object environment record]
72655 *
72656 * Variable bindings established inside eval() are deletable (configurable),
72657 * other bindings are not, including variables declared in global level.
72658 * Registers are always non-deletable, and the deletion of other bindings
72659 * is controlled by the configurable flag.
72660 *
72661 * For strict mode code, the 'delete' operator should fail with a compile
72662 * time SyntaxError if applied to identifiers. Hence, no strict mode
72663 * run-time deletion of identifiers should ever happen. This function
72664 * should never be called from strict mode code!
72665 */
72666
72669 duk_hobject *env,
72670 duk_activation *act,
72671 duk_hstring *name) {
72673 duk_bool_t parents;
72674
72675 DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
72676 "(env -> %!dO)",
72677 (void *) thr, (void *) env, (void *) act,
72678 (duk_heaphdr *) name, (duk_heaphdr *) env));
72679
72680 DUK_ASSERT(thr != NULL);
72681 DUK_ASSERT(name != NULL);
72682 /* env and act may be NULL */
72683
72685
72686 parents = 1; /* follow parent chain */
72687
72688 if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72689 if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
72690 /* Identifier found in registers (always non-deletable)
72691 * or declarative environment record and non-configurable.
72692 */
72693 return 0;
72694 }
72695 DUK_ASSERT(ref.holder != NULL);
72696
72697 return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
72698 }
72699
72700 /*
72701 * Not found (even in global object).
72702 *
72703 * In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
72704 * step 3.b. In strict mode this case is a compile time SyntaxError so
72705 * we should not come here.
72706 */
72708 DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
72709 "(treated as silent success)",
72710 (duk_heaphdr *) name));
72711 return 1;
72712}
72713
72714#if 0 /*unused*/
72716duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
72717 duk_hobject *env,
72718 duk_hstring *name) {
72719 return duk__delvar_helper(thr, env, NULL, name);
72720}
72721#endif
72722
72725 duk_activation *act,
72726 duk_hstring *name) {
72727 DUK_ASSERT(act != NULL);
72728 return duk__delvar_helper(thr, act->lex_env, act, name);
72729}
72730
72731/*
72732 * DECLVAR
72733 *
72734 * See E5 Sections:
72735 * 10.4.3 Entering Function Code
72736 * 10.5 Declaration Binding Instantion
72737 * 12.2 Variable Statement
72738 * 11.1.2 Identifier Reference
72739 * 10.3.1 Identifier Resolution
72740 *
72741 * Variable declaration behavior is mainly discussed in Section 10.5,
72742 * and is not discussed in the execution semantics (Sections 11-13).
72743 *
72744 * Conceptually declarations happen when code (global, eval, function)
72745 * is entered, before any user code is executed. In practice, register-
72746 * bound identifiers are 'declared' automatically (by virtue of being
72747 * allocated to registers with the initial value 'undefined'). Other
72748 * identifiers are declared in the function prologue with this primitive.
72749 *
72750 * Since non-register bindings eventually back to an internal object's
72751 * properties, the 'prop_flags' argument is used to specify binding
72752 * type:
72753 *
72754 * - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
72755 * - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
72756 * - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
72757 * doesn't really matter for internal objects
72758 *
72759 * All bindings are non-deletable mutable bindings except:
72760 *
72761 * - Declarations in eval code (mutable, deletable)
72762 * - 'arguments' binding in strict function code (immutable)
72763 * - Function name binding of a function expression (immutable)
72764 *
72765 * Declarations may go to declarative environment records (always
72766 * so for functions), but may also go to object environment records
72767 * (e.g. global code). The global object environment has special
72768 * behavior when re-declaring a function (but not a variable); see
72769 * E5.1 specification, Section 10.5, step 5.e.
72770 *
72771 * Declarations always go to the 'top-most' environment record, i.e.
72772 * we never check the record chain. It's not an error even if a
72773 * property (even an immutable or non-deletable one) of the same name
72774 * already exists.
72775 *
72776 * If a declared variable already exists, its value needs to be updated
72777 * (if possible). Returns 1 if a PUTVAR needs to be done by the caller;
72778 * otherwise returns 0.
72779 */
72780
72783 duk_hobject *env,
72785 duk_tval *val,
72786 duk_small_int_t prop_flags,
72787 duk_bool_t is_func_decl) {
72788 duk_context *ctx = (duk_context *) thr;
72789 duk_hobject *holder;
72790 duk_bool_t parents;
72792 duk_tval *tv;
72793
72794 DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
72795 "(env -> %!iO)",
72796 (void *) thr, (void *) env, (duk_heaphdr *) name,
72797 (duk_tval *) val, (unsigned long) prop_flags,
72798 (unsigned int) is_func_decl, (duk_heaphdr *) env));
72799
72800 DUK_ASSERT(thr != NULL);
72801 DUK_ASSERT(env != NULL);
72802 DUK_ASSERT(name != NULL);
72803 DUK_ASSERT(val != NULL);
72804
72805 /* Note: in strict mode the compiler should reject explicit
72806 * declaration of 'eval' or 'arguments'. However, internal
72807 * bytecode may declare 'arguments' in the function prologue.
72808 * We don't bother checking (or asserting) for these now.
72809 */
72810
72811 /* Note: val is a stable duk_tval pointer. The caller makes
72812 * a value copy into its stack frame, so 'tv_val' is not subject
72813 * to side effects here.
72814 */
72815
72816 /*
72817 * Check whether already declared.
72818 *
72819 * We need to check whether the binding exists in the environment
72820 * without walking its parents. However, we still need to check
72821 * register-bound identifiers and the prototype chain of an object
72822 * environment target object.
72823 */
72824
72825 parents = 0; /* just check 'env' */
72826 if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
72827 duk_int_t e_idx;
72828 duk_int_t h_idx;
72829 duk_small_int_t flags;
72830
72831 /*
72832 * Variable already declared, ignore re-declaration.
72833 * The only exception is the updated behavior of E5.1 for
72834 * global function declarations, E5.1 Section 10.5, step 5.e.
72835 * This behavior does not apply to global variable declarations.
72836 */
72837
72838 if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
72839 DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
72840 return 1; /* 1 -> needs a PUTVAR */
72841 }
72842
72843 /*
72844 * Special behavior in E5.1.
72845 *
72846 * Note that even though parents == 0, the conflicting property
72847 * may be an inherited property (currently our global object's
72848 * prototype is Object.prototype). Step 5.e first operates on
72849 * the existing property (which is potentially in an ancestor)
72850 * and then defines a new property in the global object (and
72851 * never modifies the ancestor).
72852 *
72853 * Also note that this logic would become even more complicated
72854 * if the conflicting property might be a virtual one. Object
72855 * prototype has no virtual properties, though.
72856 *
72857 * XXX: this is now very awkward, rework.
72858 */
72859
72860 DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
72861 "updated E5.1 processing"));
72862
72863 DUK_ASSERT(ref.holder != NULL);
72864 holder = ref.holder;
72865
72866 /* holder will be set to the target object, not the actual object
72867 * where the property was found (see duk__get_identifier_reference()).
72868 */
72870 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder)); /* global object doesn't have array part */
72871
72872 /* XXX: use a helper for prototype traversal; no loop check here */
72873 /* must be found: was found earlier, and cannot be inherited */
72874 for (;;) {
72875 DUK_ASSERT(holder != NULL);
72876 duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx);
72877 if (e_idx >= 0) {
72878 break;
72879 }
72880 /* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
72881 * asserted above.
72882 */
72883 holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
72884 }
72885 DUK_ASSERT(holder != NULL);
72886 DUK_ASSERT(e_idx >= 0);
72887 /* SCANBUILD: scan-build produces a NULL pointer dereference warning
72888 * below; it never actually triggers because holder is actually never
72889 * NULL.
72890 */
72891
72892 /* ref.holder is global object, holder is the object with the
72893 * conflicting property.
72894 */
72895
72896 flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
72897 if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
72898 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
72899 DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
72900 "accessor -> reject"));
72901 goto fail_existing_attributes;
72902 }
72903 if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
72904 (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
72905 DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
72906 "plain property which is not writable and "
72907 "enumerable -> reject"));
72908 goto fail_existing_attributes;
72909 }
72910
72911 DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
72912 "is plain, enumerable, and writable -> "
72913 "allow redeclaration"));
72914 }
72915
72916 if (holder == ref.holder) {
72917 /* XXX: if duk_hobject_define_property_internal() was updated
72918 * to handle a pre-existing accessor property, this would be
72919 * a simple call (like for the ancestor case).
72920 */
72921 DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
72922
72923 if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
72924 duk_hobject *tmp;
72925
72926 tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
72927 DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
72929 DUK_UNREF(tmp);
72930 tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
72931 DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
72933 DUK_UNREF(tmp);
72934 } else {
72935 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
72937 }
72938
72939 /* Here val would be potentially invalid if we didn't make
72940 * a value copy at the caller.
72941 */
72942
72943 tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
72944 DUK_TVAL_SET_TVAL(tv, val);
72945 DUK_TVAL_INCREF(thr, tv);
72946 DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
72947
72948 DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
72949 "value -> %!T, prop_flags=0x%08lx",
72950 (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
72951 (unsigned long) prop_flags));
72952 } else {
72953 DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
72954
72956 duk_push_tval(ctx, val);
72957 duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
72958 }
72959
72960 return 0;
72961 }
72962
72963 /*
72964 * Not found (in registers or record objects). Declare
72965 * to current variable environment.
72966 */
72967
72968 /*
72969 * Get holder object
72970 */
72971
72972 if (DUK_HOBJECT_IS_DECENV(env)) {
72973 holder = env;
72974 } else {
72976
72978 DUK_ASSERT(tv != NULL);
72980 holder = DUK_TVAL_GET_OBJECT(tv);
72981 DUK_ASSERT(holder != NULL);
72982 }
72983
72984 /*
72985 * Define new property
72986 *
72987 * Note: this may fail if the holder is not extensible.
72988 */
72989
72990 /* XXX: this is awkward as we use an internal method which doesn't handle
72991 * extensibility etc correctly. Basically we'd want to do a [[DefineOwnProperty]]
72992 * or Object.defineProperty() here.
72993 */
72994
72995 if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
72996 goto fail_not_extensible;
72998
72999 duk_push_hobject(ctx, holder);
73000 duk_push_hstring(ctx, name);
73001 duk_push_tval(ctx, val);
73002 duk_xdef_prop(ctx, -3, prop_flags); /* [holder name val] -> [holder] */
73003 duk_pop(ctx);
73004
73005 return 0;
73006
73007 fail_existing_attributes:
73008 fail_not_extensible:
73009 DUK_ERROR_TYPE(thr, "declaration failed");
73010 return 0;
73011}
73012
73015 duk_activation *act,
73017 duk_tval *val,
73018 duk_small_int_t prop_flags,
73019 duk_bool_t is_func_decl) {
73020 duk_hobject *env;
73021 duk_tval tv_val_copy;
73022
73023 /*
73024 * Make a value copy of the input val. This ensures that
73025 * side effects cannot invalidate the pointer.
73026 */
73027
73028 DUK_TVAL_SET_TVAL(&tv_val_copy, val);
73029 val = &tv_val_copy;
73030
73031 /*
73032 * Delayed env creation check
73033 */
73034
73035 if (!act->var_env) {
73036 DUK_ASSERT(act->lex_env == NULL);
73038 }
73039 DUK_ASSERT(act->lex_env != NULL);
73040 DUK_ASSERT(act->var_env != NULL);
73041
73042 env = act->var_env;
73043 DUK_ASSERT(env != NULL);
73045
73046 return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
73047}
73048#line 1 "duk_lexer.c"
73049/*
73050 * Lexer for source files, ToNumber() string conversions, RegExp expressions,
73051 * and JSON.
73052 *
73053 * Provides a stream of Ecmascript tokens from an UTF-8/CESU-8 buffer. The
73054 * caller can also rewind the token stream into a certain position which is
73055 * needed by the compiler part for multi-pass scanning. Tokens are
73056 * represented as duk_token structures, and contain line number information.
73057 * Token types are identified with DUK_TOK_* defines.
73058 *
73059 * Characters are decoded into a fixed size lookup window consisting of
73060 * decoded Unicode code points, with window positions past the end of the
73061 * input filled with an invalid codepoint (-1). The tokenizer can thus
73062 * perform multiple character lookups efficiently and with few sanity
73063 * checks (such as access outside the end of the input), which keeps the
73064 * tokenization code small at the cost of performance.
73065 *
73066 * Character data in tokens, such as identifier names and string literals,
73067 * is encoded into CESU-8 format on-the-fly while parsing the token in
73068 * question. The string data is made reachable to garbage collection by
73069 * placing the token-related values in value stack entries allocated for
73070 * this purpose by the caller. The characters exist in Unicode code point
73071 * form only in the fixed size lookup window, which keeps character data
73072 * expansion (of especially ASCII data) low.
73073 *
73074 * Token parsing supports the full range of Unicode characters as described
73075 * in the E5 specification. Parsing has been optimized for ASCII characters
73076 * because ordinary Ecmascript code consists almost entirely of ASCII
73077 * characters. Matching of complex Unicode codepoint sets (such as in the
73078 * IdentifierStart and IdentifierPart productions) is optimized for size,
73079 * and is done using a linear scan of a bit-packed list of ranges. This is
73080 * very slow, but should never be entered unless the source code actually
73081 * contains Unicode characters.
73082 *
73083 * Ecmascript tokenization is partially context sensitive. First,
73084 * additional future reserved words are recognized in strict mode (see E5
73085 * Section 7.6.1.2). Second, a forward slash character ('/') can be
73086 * recognized either as starting a RegExp literal or as a division operator,
73087 * depending on context. The caller must provide necessary context flags
73088 * when requesting a new token.
73089 *
73090 * Future work:
73091 *
73092 * * Make line number tracking optional, as it consumes space.
73093 *
73094 * * Add a feature flag for disabling UTF-8 decoding of input, as most
73095 * source code is ASCII. Because of Unicode escapes written in ASCII,
73096 * this does not allow Unicode support to be removed from e.g.
73097 * duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
73098 * encoding of e.g. string literals.
73099 *
73100 * * Add a feature flag for disabling Unicode compliance of e.g. identifier
73101 * names. This allows for a build more than a kilobyte smaller, because
73102 * Unicode ranges needed by duk_unicode_is_identifier_start() and
73103 * duk_unicode_is_identifier_part() can be dropped. String literals
73104 * should still be allowed to contain escaped Unicode, so this still does
73105 * not allow removal of CESU-8 encoding of e.g. string literals.
73106 *
73107 * * Character lookup tables for codepoints above BMP could be stripped.
73108 *
73109 * * Strictly speaking, E5 specification requires that source code consists
73110 * of 16-bit code units, and if not, must be conceptually converted to
73111 * that format first. The current lexer processes Unicode code points
73112 * and allows characters outside the BMP. These should be converted to
73113 * surrogate pairs while reading the source characters into the window,
73114 * not after tokens have been formed (as is done now). However, the fix
73115 * is not trivial because two characters are decoded from one codepoint.
73117 * * Optimize for speed as well as size. Large if-else ladders are (at
73118 * least potentially) slow.
73119 */
73120
73121/* include removed: duk_internal.h */
73124 * Various defines and file specific helper macros
73126
73127#define DUK__MAX_RE_DECESC_DIGITS 9
73128#define DUK__MAX_RE_QUANT_DIGITS 9 /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
73130/* whether to use macros or helper function depends on call count */
73131#define DUK__ISDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
73132#define DUK__ISHEXDIGIT(x) duk__is_hex_digit((x))
73133#define DUK__ISOCTDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
73134#define DUK__ISDIGIT03(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
73135#define DUK__ISDIGIT47(x) ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
73137/* lexer character window helpers */
73138#define DUK__LOOKUP(lex_ctx,index) ((lex_ctx)->window[(index)].codepoint)
73139#define DUK__ADVANCECHARS(lex_ctx,count) duk__advance_bytes((lex_ctx), (count) * sizeof(duk_lexer_codepoint))
73140#define DUK__ADVANCEBYTES(lex_ctx,count) duk__advance_bytes((lex_ctx), (count))
73141#define DUK__INITBUFFER(lex_ctx) duk__initbuffer((lex_ctx))
73142#define DUK__APPENDBUFFER(lex_ctx,x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
73143
73144/* lookup shorthands (note: assume context variable is named 'lex_ctx') */
73145#define DUK__L0() DUK__LOOKUP(lex_ctx, 0)
73146#define DUK__L1() DUK__LOOKUP(lex_ctx, 1)
73147#define DUK__L2() DUK__LOOKUP(lex_ctx, 2)
73148#define DUK__L3() DUK__LOOKUP(lex_ctx, 3)
73149#define DUK__L4() DUK__LOOKUP(lex_ctx, 4)
73150#define DUK__L5() DUK__LOOKUP(lex_ctx, 5)
73151
73152/* packed advance/token number macro used by multiple functions */
73153#define DUK__ADVTOK(advbytes,tok) ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
73154
73155/*
73156 * Advance lookup window by N characters, filling in new characters as
73157 * necessary. After returning caller is guaranteed a character window of
73158 * at least DUK_LEXER_WINDOW_SIZE characters.
73159 *
73160 * The main function duk__advance_bytes() is called at least once per every
73161 * token so it has a major lexer/compiler performance impact. There are two
73162 * variants for the main duk__advance_bytes() algorithm: a sliding window
73163 * approach which is slightly faster at the cost of larger code footprint,
73164 * and a simple copying one.
73165 *
73166 * Decoding directly from the source string would be another lexing option.
73167 * But the lookup window based approach has the advantage of hiding the
73168 * source string and its encoding effectively which gives more flexibility
73169 * going forward to e.g. support chunked streaming of source from flash.
73170 *
73171 * Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
73172 * U+10FFFF, causing an error if the input is unparseable. Leniency means:
73173 *
73174 * * Unicode code point validation is intentionally not performed,
73175 * except to check that the codepoint does not exceed 0x10ffff.
73176 *
73177 * * In particular, surrogate pairs are allowed and not combined, which
73178 * allows source files to represent all SourceCharacters with CESU-8.
73179 * Broken surrogate pairs are allowed, as Ecmascript does not mandate
73180 * their validation.
73181 *
73182 * * Allow non-shortest UTF-8 encodings.
73183 *
73184 * Leniency here causes few security concerns because all character data is
73185 * decoded into Unicode codepoints before lexer processing, and is then
73186 * re-encoded into CESU-8. The source can be parsed as strict UTF-8 with
73187 * a compiler option. However, Ecmascript source characters include -all-
73188 * 16-bit unsigned integer codepoints, so leniency seems to be appropriate.
73189 *
73190 * Note that codepoints above the BMP are not strictly SourceCharacters,
73191 * but the lexer still accepts them as such. Before ending up in a string
73192 * or an identifier name, codepoints above BMP are converted into surrogate
73193 * pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
73194 * expected by Ecmascript.
73195 *
73196 * An alternative approach to dealing with invalid or partial sequences
73197 * would be to skip them and replace them with e.g. the Unicode replacement
73198 * character U+FFFD. This has limited utility because a replacement character
73199 * will most likely cause a parse error, unless it occurs inside a string.
73200 * Further, Ecmascript source is typically pure ASCII.
73201 *
73202 * See:
73203 *
73204 * http://en.wikipedia.org/wiki/UTF-8
73205 * http://en.wikipedia.org/wiki/CESU-8
73206 * http://tools.ietf.org/html/rfc3629
73207 * http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
73209 * Future work:
73210 *
73211 * * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
73212 * in strict UTF-8 mode.
73213 *
73214 * * Size optimize. An attempt to use a 16-byte lookup table for the first
73215 * byte resulted in a code increase though.
73216 *
73217 * * Is checking against maximum 0x10ffff really useful? 4-byte encoding
73218 * imposes a certain limit anyway.
73219 *
73220 * * Support chunked streaming of source code. Can be implemented either
73221 * by streaming chunks of bytes or chunks of codepoints.
73222 */
73223
73224#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
73225DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
73226 duk_lexer_codepoint *cp, *cp_end;
73228 duk_small_uint_t contlen;
73229 const duk_uint8_t *p, *p_end;
73230#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73231 duk_ucodepoint_t mincp;
73232#endif
73233 duk_int_t input_line;
73234
73235 /* Use temporaries and update lex_ctx only when finished. */
73236 input_line = lex_ctx->input_line;
73237 p = lex_ctx->input + lex_ctx->input_offset;
73238 p_end = lex_ctx->input + lex_ctx->input_length;
73239
73240 cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
73241 cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
73242
73243 for (; cp != cp_end; cp++) {
73244 cp->offset = (duk_size_t) (p - lex_ctx->input);
73245 cp->line = input_line;
73246
73247 /* XXX: potential issue with signed pointers, p_end < p. */
73248 if (DUK_UNLIKELY(p >= p_end)) {
73249 /* If input_offset were assigned a negative value, it would
73250 * result in a large positive value. Most likely it would be
73251 * larger than input_length and be caught here. In any case
73252 * no memory unsafe behavior would happen.
73253 */
73254 cp->codepoint = -1;
73255 continue;
73256 }
73257
73258 x = (duk_ucodepoint_t) (*p++);
73259
73260 /* Fast path. */
73261
73262 if (DUK_LIKELY(x < 0x80UL)) {
73263 DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
73264 if (DUK_UNLIKELY(x <= 0x000dUL)) {
73265 if ((x == 0x000aUL) ||
73266 ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
73267 /* lookup for 0x000a above assumes shortest encoding now */
73268
73269 /* E5 Section 7.3, treat the following as newlines:
73270 * LF
73271 * CR [not followed by LF]
73272 * LS
73273 * PS
73274 *
73275 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
73276 * the line number.
73277 */
73278 input_line++;
73279 }
73280 }
73281
73282 cp->codepoint = (duk_codepoint_t) x;
73283 continue;
73284 }
73285
73286 /* Slow path. */
73287
73288 if (x < 0xc0UL) {
73289 /* 10xx xxxx -> invalid */
73290 goto error_encoding;
73291 } else if (x < 0xe0UL) {
73292 /* 110x xxxx 10xx xxxx */
73293 contlen = 1;
73294#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73295 mincp = 0x80UL;
73296#endif
73297 x = x & 0x1fUL;
73298 } else if (x < 0xf0UL) {
73299 /* 1110 xxxx 10xx xxxx 10xx xxxx */
73300 contlen = 2;
73301#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73302 mincp = 0x800UL;
73303#endif
73304 x = x & 0x0fUL;
73305 } else if (x < 0xf8UL) {
73306 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
73307 contlen = 3;
73308#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73309 mincp = 0x10000UL;
73310#endif
73311 x = x & 0x07UL;
73312 } else {
73313 /* no point in supporting encodings of 5 or more bytes */
73314 goto error_encoding;
73315 }
73316
73317 DUK_ASSERT(p_end >= p);
73318 if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
73319 goto error_clipped;
73320 }
73321
73322 while (contlen > 0) {
73324 y = *p++;
73325 if ((y & 0xc0U) != 0x80U) {
73326 /* check that byte has the form 10xx xxxx */
73327 goto error_encoding;
73328 }
73329 x = x << 6;
73330 x += y & 0x3fUL;
73331 contlen--;
73332 }
73333
73334 /* check final character validity */
73335
73336 if (x > 0x10ffffUL) {
73337 goto error_encoding;
73338 }
73339#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73340 if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
73341 goto error_encoding;
73342 }
73343#endif
73344
73345 DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
73346 if ((x == 0x2028UL) || (x == 0x2029UL)) {
73347 input_line++;
73349
73350 cp->codepoint = (duk_codepoint_t) x;
73351 }
73352
73353 lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
73354 lex_ctx->input_line = input_line;
73355 return;
73356
73357 error_clipped: /* clipped codepoint */
73358 error_encoding: /* invalid codepoint encoding or codepoint */
73359 lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
73360 lex_ctx->input_line = input_line;
73361
73362 DUK_ERROR_SYNTAX(lex_ctx->thr, "utf-8 decode failed");
73363}
73364
73365DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
73366 duk_small_uint_t used_bytes, avail_bytes;
73367
73368 DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
73370 DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
73371 DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
73372 DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
73373
73374 /* Zero 'count' is also allowed to make call sites easier.
73375 * Arithmetic in bytes generates better code in GCC.
73377
73378 lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes); /* avoid multiply */
73379 used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
73380 avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
73381 if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
73382 /* Not enough data to provide a full window, so "scroll" window to
73383 * start of buffer and fill up the rest.
73384 */
73385 DUK_MEMMOVE((void *) lex_ctx->buffer,
73386 (const void *) lex_ctx->window,
73387 (size_t) avail_bytes);
73388 lex_ctx->window = lex_ctx->buffer;
73389 duk__fill_lexer_buffer(lex_ctx, avail_bytes);
73390 }
73391}
73392
73394 lex_ctx->window = lex_ctx->buffer;
73395 duk__fill_lexer_buffer(lex_ctx, 0);
73396}
73397#else /* DUK_USE_LEXER_SLIDING_WINDOW */
73398DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
73400 duk_small_uint_t len;
73402 const duk_uint8_t *p;
73403#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73404 duk_ucodepoint_t mincp;
73405#endif
73406 duk_size_t input_offset;
73407
73408 input_offset = lex_ctx->input_offset;
73409 if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
73410 /* If input_offset were assigned a negative value, it would
73411 * result in a large positive value. Most likely it would be
73412 * larger than input_length and be caught here. In any case
73413 * no memory unsafe behavior would happen.
73414 */
73415 return -1;
73416 }
73417
73418 p = lex_ctx->input + input_offset;
73419 x = (duk_ucodepoint_t) (*p);
73420
73421 if (DUK_LIKELY(x < 0x80UL)) {
73422 /* 0xxx xxxx -> fast path */
73423
73424 /* input offset tracking */
73425 lex_ctx->input_offset++;
73426
73427 DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
73428 if (DUK_UNLIKELY(x <= 0x000dUL)) {
73429 if ((x == 0x000aUL) ||
73430 ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
73431 lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
73432 /* lookup for 0x000a above assumes shortest encoding now */
73433
73434 /* E5 Section 7.3, treat the following as newlines:
73435 * LF
73436 * CR [not followed by LF]
73437 * LS
73438 * PS
73439 *
73440 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
73441 * the line number.
73442 */
73443 lex_ctx->input_line++;
73444 }
73445 }
73446
73447 return (duk_codepoint_t) x;
73448 }
73449
73450 /* Slow path. */
73451
73452 if (x < 0xc0UL) {
73453 /* 10xx xxxx -> invalid */
73454 goto error_encoding;
73455 } else if (x < 0xe0UL) {
73456 /* 110x xxxx 10xx xxxx */
73457 len = 2;
73458#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73459 mincp = 0x80UL;
73460#endif
73461 x = x & 0x1fUL;
73462 } else if (x < 0xf0UL) {
73463 /* 1110 xxxx 10xx xxxx 10xx xxxx */
73464 len = 3;
73465#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73466 mincp = 0x800UL;
73467#endif
73468 x = x & 0x0fUL;
73469 } else if (x < 0xf8UL) {
73470 /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
73471 len = 4;
73472#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73473 mincp = 0x10000UL;
73474#endif
73475 x = x & 0x07UL;
73476 } else {
73477 /* no point in supporting encodings of 5 or more bytes */
73478 goto error_encoding;
73479 }
73480
73481 DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
73482 if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
73483 goto error_clipped;
73484 }
73485
73486 p++;
73487 for (i = 1; i < len; i++) {
73489 y = *p++;
73490 if ((y & 0xc0U) != 0x80U) {
73491 /* check that byte has the form 10xx xxxx */
73492 goto error_encoding;
73493 }
73494 x = x << 6;
73495 x += y & 0x3fUL;
73496 }
73497
73498 /* check final character validity */
73499
73500 if (x > 0x10ffffUL) {
73501 goto error_encoding;
73502 }
73503#if defined(DUK_USE_STRICT_UTF8_SOURCE)
73504 if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
73505 goto error_encoding;
73506 }
73507#endif
73508
73509 /* input offset tracking */
73510 lex_ctx->input_offset += len;
73511
73512 /* line tracking */
73513 DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
73514 if ((x == 0x2028UL) || (x == 0x2029UL)) {
73515 lex_ctx->input_line++;
73516 }
73517
73518 return (duk_codepoint_t) x;
73519
73520 error_clipped: /* clipped codepoint */
73521 error_encoding: /* invalid codepoint encoding or codepoint */
73522 DUK_ERROR_SYNTAX(lex_ctx->thr, "utf-8 decode failed");
73523 return 0;
73524}
73525
73526DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
73527 duk_small_uint_t keep_bytes;
73528 duk_lexer_codepoint *cp, *cp_end;
73529
73530 DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
73532
73533 /* Zero 'count' is also allowed to make call sites easier. */
73534
73535 keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
73536 DUK_MEMMOVE((void *) lex_ctx->window,
73537 (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
73538 (size_t) keep_bytes);
73539
73540 cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
73541 cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
73542 for (; cp != cp_end; cp++) {
73543 cp->offset = lex_ctx->input_offset;
73544 cp->line = lex_ctx->input_line;
73545 cp->codepoint = duk__read_char(lex_ctx);
73546 }
73547}
73548
73550 /* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
73551 duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)); /* fill window */
73552}
73553#endif /* DUK_USE_LEXER_SLIDING_WINDOW */
73554
73555/*
73556 * (Re)initialize the temporary byte buffer. May be called extra times
73557 * with little impact.
73558 */
73559
73561 /* Reuse buffer as is unless buffer has grown large. */
73563 /* Keep current size */
73564 } else {
73566 }
73567
73568 DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
73569}
73570
73571/*
73572 * Append a Unicode codepoint to the temporary byte buffer. Performs
73573 * CESU-8 surrogate pair encoding for codepoints above the BMP.
73574 * Existing surrogate pairs are allowed and also encoded into CESU-8.
73575 */
73576
73578 /*
73579 * Since character data is only generated by decoding the source or by
73580 * the compiler itself, we rely on the input codepoints being correct
73581 * and avoid a check here.
73582 *
73583 * Character data can also come here through decoding of Unicode
73584 * escapes ("\udead\ubeef") so all 16-but unsigned values can be
73585 * present, even when the source file itself is strict UTF-8.
73586 */
73587
73588 DUK_ASSERT(x >= 0 && x <= 0x10ffff);
73589
73590 DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
73591}
73592
73593/*
73594 * Intern the temporary byte buffer into a valstack slot
73595 * (in practice, slot1 or slot2).
73596 */
73597
73598DUK_LOCAL void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
73599 duk_context *ctx = (duk_context *) lex_ctx->thr;
73600
73601 DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
73602
73603 DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
73604 duk_replace(ctx, valstack_idx);
73605}
73606
73607/*
73608 * Init lexer context
73609 */
73610
73612 DUK_ASSERT(lex_ctx != NULL);
73613
73614 DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx));
73615#if defined(DUK_USE_EXPLICIT_NULL_INIT)
73616#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
73617 lex_ctx->window = NULL;
73618#endif
73619 lex_ctx->thr = NULL;
73620 lex_ctx->input = NULL;
73621 lex_ctx->buf = NULL;
73622#endif
73623}
73624
73625/*
73626 * Set lexer input position and reinitialize lookup window.
73628
73629/* NB: duk_lexer_getpoint() is a macro only */
73630
73632 DUK_ASSERT_DISABLE(pt->offset >= 0); /* unsigned */
73633 DUK_ASSERT(pt->line >= 1);
73634 lex_ctx->input_offset = pt->offset;
73635 lex_ctx->input_line = pt->line;
73636 duk__init_lexer_window(lex_ctx);
73637}
73638
73639/*
73640 * Lexing helpers
73641 */
73642
73643/* numeric value of a hex digit (also covers octal and decimal digits) */
73647 /* Here 'x' is a Unicode codepoint */
73648 if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
73649 t = duk_hex_dectab[x];
73650 if (DUK_LIKELY(t >= 0)) {
73651 return t;
73652 }
73654
73655 /* Throwing an error this deep makes the error rather vague, but
73656 * saves hundreds of bytes of code.
73657 */
73658 DUK_ERROR_SYNTAX(lex_ctx->thr, "decode error");
73659 return 0;
73660}
73661
73662/* having this as a separate function provided a size benefit */
73664 if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
73665 return (duk_hex_dectab[x] >= 0);
73666 }
73667 return 0;
73668}
73669
73671 /* validation performed by duk__hexval */
73672 return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 4) |
73673 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint));
73674}
73675
73677 /* validation performed by duk__hexval */
73678 return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 12) |
73679 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint) << 8) |
73680 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 2].codepoint) << 4) |
73681 (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 3].codepoint));
73682}
73683
73684/*
73685 * Parse Ecmascript source InputElementDiv or InputElementRegExp
73686 * (E5 Section 7), skipping whitespace, comments, and line terminators.
73687 *
73688 * Possible results are:
73689 * (1) a token
73690 * (2) a line terminator (skipped)
73691 * (3) a comment (skipped)
73692 * (4) EOF
73693 *
73694 * White space is automatically skipped from the current position (but
73695 * not after the input element). If input has already ended, returns
73696 * DUK_TOK_EOF indefinitely. If a parse error occurs, uses an DUK_ERROR()
73697 * macro call (and hence a longjmp through current heap longjmp context).
73698 * Comments and line terminator tokens are automatically skipped.
73699 *
73700 * The input element being matched is determined by regexp_mode; if set,
73701 * parses a InputElementRegExp, otherwise a InputElementDiv. The
73702 * difference between these are handling of productions starting with a
73703 * forward slash.
73704 *
73705 * If strict_mode is set, recognizes additional future reserved words
73706 * specific to strict mode, and refuses to parse octal literals.
73707 *
73708 * The matching strategy below is to (currently) use a six character
73709 * lookup window to quickly determine which production is the -longest-
73710 * matching one, and then parse that. The top-level if-else clauses
73711 * match the first character, and the code blocks for each clause
73712 * handle -all- alternatives for that first character. Ecmascript
73713 * specification uses the "longest match wins" semantics, so the order
73714 * of the if-clauses matters.
73715 *
73716 * Misc notes:
73717 *
73718 * * Ecmascript numeric literals do not accept a sign character.
73719 * Consequently e.g. "-1.0" is parsed as two tokens: a negative
73720 * sign and a positive numeric literal. The compiler performs
73721 * the negation during compilation, so this has no adverse impact.
73722 *
73723 * * There is no token for "undefined": it is just a value available
73724 * from the global object (or simply established by doing a reference
73725 * to an undefined value).
73726 *
73727 * * Some contexts want Identifier tokens, which are IdentifierNames
73728 * excluding reserved words, while some contexts want IdentifierNames
73729 * directly. In the latter case e.g. "while" is interpreted as an
73730 * identifier name, not a DUK_TOK_WHILE token. The solution here is
73731 * to provide both token types: DUK_TOK_WHILE goes to 't' while
73732 * DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
73733 * the identifier / keyword name.
73734 *
73735 * * Directive prologue needs to identify string literals such as
73736 * "use strict" and 'use strict', which are sensitive to line
73737 * continuations and escape sequences. For instance, "use\u0020strict"
73738 * is a valid directive but is distinct from "use strict". The solution
73739 * here is to decode escapes while tokenizing, but to keep track of the
73740 * number of escapes. Directive detection can then check that the
73741 * number of escapes is zero.
73742 *
73743 * * Multi-line comments with one or more internal LineTerminator are
73744 * treated like a line terminator to comply with automatic semicolon
73745 * insertion.
73746 */
73747
73750 duk_token *out_token,
73751 duk_bool_t strict_mode,
73752 duk_bool_t regexp_mode) {
73753 duk_codepoint_t x; /* temporary, must be signed and 32-bit to hold Unicode code points */
73754 duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
73755 * init is unnecessary but suppresses "may be used uninitialized" warnings.
73756 */
73757 duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */
73758
73759 if (++lex_ctx->token_count >= lex_ctx->token_limit) {
73760 DUK_ERROR_RANGE(lex_ctx->thr, "token limit");
73761 return; /* unreachable */
73762 }
73763
73764 out_token->t = DUK_TOK_EOF;
73765 out_token->t_nores = -1; /* marker: copy t if not changed */
73766#if 0 /* not necessary to init, disabled for faster parsing */
73767 out_token->num = DUK_DOUBLE_NAN;
73768 out_token->str1 = NULL;
73769 out_token->str2 = NULL;
73770#endif
73771 out_token->num_escapes = 0;
73772 /* out_token->lineterm set by caller */
73773
73774 /* This would be nice, but parsing is faster without resetting the
73775 * value slots. The only side effect is that references to temporary
73776 * string values may linger until lexing is finished; they're then
73777 * freed normally.
73778 */
73779#if 0
73780 duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
73781 duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
73782#endif
73783
73784 /* 'advtok' indicates how much to advance and which token id to assign
73785 * at the end. This shared functionality minimizes code size. All
73786 * code paths are required to set 'advtok' to some value, so no default
73787 * init value is used. Code paths calling DUK_ERROR() never return so
73788 * they don't need to set advtok.
73789 */
73790
73791 /*
73792 * Matching order:
73793 *
73794 * Punctuator first chars, also covers comments, regexps
73795 * LineTerminator
73796 * Identifier or reserved word, also covers null/true/false literals
73797 * NumericLiteral
73798 * StringLiteral
73799 * EOF
73800 *
73801 * The order does not matter as long as the longest match is
73802 * always correctly identified. There are order dependencies
73803 * in the clauses, so it's not trivial to convert to a switch.
73804 */
73805
73806 restart_lineupdate:
73807 out_token->start_line = lex_ctx->window[0].line;
73808
73809 restart:
73810 out_token->start_offset = lex_ctx->window[0].offset;
73811
73812 x = DUK__L0();
73813
73814 switch (x) {
73815 case DUK_ASC_SPACE:
73816 case DUK_ASC_HT: /* fast paths for space and tab */
73817 DUK__ADVANCECHARS(lex_ctx, 1);
73818 goto restart;
73819 case DUK_ASC_LF: /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
73820 DUK__ADVANCECHARS(lex_ctx, 1);
73821 got_lineterm = 1;
73822 goto restart_lineupdate;
73823 case DUK_ASC_SLASH: /* '/' */
73824 if (DUK__L1() == '/') {
73825 /*
73826 * E5 Section 7.4, allow SourceCharacter (which is any 16-bit
73827 * code point).
73828 */
73829
73830 /* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but it unnecessary */
73831 for (;;) {
73832 x = DUK__L0();
73833 if (x < 0 || duk_unicode_is_line_terminator(x)) {
73834 break;
73835 }
73836 DUK__ADVANCECHARS(lex_ctx, 1);
73837 }
73838 goto restart; /* line terminator will be handled on next round */
73839 } else if (DUK__L1() == '*') {
73840 /*
73841 * E5 Section 7.4. If the multi-line comment contains a newline,
73842 * it is treated like a single line terminator for automatic
73843 * semicolon insertion.
73844 */
73845
73846 duk_bool_t last_asterisk = 0;
73847 DUK__ADVANCECHARS(lex_ctx, 2);
73848 for (;;) {
73849 x = DUK__L0();
73850 if (x < 0) {
73851 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof in multiline comment");
73852 }
73853 DUK__ADVANCECHARS(lex_ctx, 1);
73854 if (last_asterisk && x == '/') {
73855 break;
73856 }
73858 got_lineterm = 1;
73859 }
73860 last_asterisk = (x == '*');
73861 }
73862 goto restart_lineupdate;
73863 } else if (regexp_mode) {
73864#if defined(DUK_USE_REGEXP_SUPPORT)
73865 /*
73866 * "/" followed by something in regexp mode. See E5 Section 7.8.5.
73867 *
73868 * RegExp parsing is a bit complex. First, the regexp body is delimited
73869 * by forward slashes, but the body may also contain forward slashes as
73870 * part of an escape sequence or inside a character class (delimited by
73871 * square brackets). A mini state machine is used to implement these.
73872 *
73873 * Further, an early (parse time) error must be thrown if the regexp
73874 * would cause a run-time error when used in the expression new RegExp(...).
73875 * Parsing here simply extracts the (candidate) regexp, and also accepts
73876 * invalid regular expressions (which are delimited properly). The caller
73877 * (compiler) must perform final validation and regexp compilation.
73878 *
73879 * RegExp first char may not be '/' (single line comment) or '*' (multi-
73880 * line comment). These have already been checked above, so there is no
73881 * need below for special handling of the first regexp character as in
73882 * the E5 productions.
73883 *
73884 * About unicode escapes within regexp literals:
73885 *
73886 * E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
73887 * However, Section 6 states that regexps accept the escapes,
73888 * see paragraph starting with "In string literals...".
73889 * The regexp grammar, which sees the decoded regexp literal
73890 * (after lexical parsing) DOES have a \uHHHH unicode escape.
73891 * So, for instance:
73892 *
73893 * /\u1234/
73894 *
73895 * should first be parsed by the lexical grammar as:
73896 *
73897 * '\' 'u' RegularExpressionBackslashSequence
73898 * '1' RegularExpressionNonTerminator
73899 * '2' RegularExpressionNonTerminator
73900 * '3' RegularExpressionNonTerminator
73901 * '4' RegularExpressionNonTerminator
73902 *
73903 * and the escape itself is then parsed by the regexp engine.
73904 * This is the current implementation.
73905 *
73906 * Minor spec inconsistency:
73907 *
73908 * E5 Section 7.8.5 RegularExpressionBackslashSequence is:
73909 *
73910 * \ RegularExpressionNonTerminator
73911 *
73912 * while Section A.1 RegularExpressionBackslashSequence is:
73913 *
73914 * \ NonTerminator
73915 *
73916 * The latter is not normative and a typo.
73917 *
73918 */
73919
73920 /* first, parse regexp body roughly */
73921
73922 duk_small_int_t state = 0; /* 0=base, 1=esc, 2=class, 3=class+esc */
73923
73924 DUK__INITBUFFER(lex_ctx);
73925 for (;;) {
73926 DUK__ADVANCECHARS(lex_ctx, 1); /* skip opening slash on first loop */
73927 x = DUK__L0();
73928 if (x < 0 || duk_unicode_is_line_terminator(x)) {
73929 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in regexp");
73930 }
73931 x = DUK__L0(); /* re-read to avoid spill / fetch */
73932 if (state == 0) {
73933 if (x == '/') {
73934 DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing slash */
73935 break;
73936 } else if (x == '\\') {
73937 state = 1;
73938 } else if (x == '[') {
73939 state = 2;
73940 }
73941 } else if (state == 1) {
73942 state = 0;
73943 } else if (state == 2) {
73944 if (x == ']') {
73945 state = 0;
73946 } else if (x == '\\') {
73947 state = 3;
73948 }
73949 } else { /* state == 3 */
73950 state = 2;
73951 }
73952 DUK__APPENDBUFFER(lex_ctx, x);
73953 }
73954 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
73955 out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
73956
73957 /* second, parse flags */
73958
73959 DUK__INITBUFFER(lex_ctx);
73960 for (;;) {
73961 x = DUK__L0();
73963 break;
73964 }
73965 x = DUK__L0(); /* re-read to avoid spill / fetch */
73966 DUK__APPENDBUFFER(lex_ctx, x);
73967 DUK__ADVANCECHARS(lex_ctx, 1);
73968 }
73969 duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
73970 out_token->str2 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
73971
73972 DUK__INITBUFFER(lex_ctx); /* free some memory */
73973
73974 /* validation of the regexp is caller's responsibility */
73975
73976 advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
73977#else
73978 DUK_ERROR_SYNTAX(lex_ctx->thr, "regexp support disabled");
73979#endif
73980 } else if (DUK__L1() == '=') {
73981 /* "/=" and not in regexp mode */
73982 advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
73983 } else {
73984 /* "/" and not in regexp mode */
73985 advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
73986 }
73987 break;
73988 case DUK_ASC_LCURLY: /* '{' */
73989 advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
73990 break;
73991 case DUK_ASC_RCURLY: /* '}' */
73992 advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
73993 break;
73994 case DUK_ASC_LPAREN: /* '(' */
73995 advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
73996 break;
73997 case DUK_ASC_RPAREN: /* ')' */
73998 advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
73999 break;
74000 case DUK_ASC_LBRACKET: /* '[' */
74001 advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
74002 break;
74003 case DUK_ASC_RBRACKET: /* ']' */
74004 advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
74005 break;
74006 case DUK_ASC_PERIOD: /* '.' */
74007 if (DUK__ISDIGIT(DUK__L1())) {
74008 /* Period followed by a digit can only start DecimalLiteral
74009 * (handled in slow path). We could jump straight into the
74010 * DecimalLiteral handling but should avoid goto to inside
74011 * a block.
74012 */
74013 goto slow_path;
74014 }
74015 advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
74016 break;
74017 case DUK_ASC_SEMICOLON: /* ';' */
74018 advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
74019 break;
74020 case DUK_ASC_COMMA: /* ',' */
74021 advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
74022 break;
74023 case DUK_ASC_LANGLE: /* '<' */
74024 if (DUK__L1() == '<' && DUK__L2() == '=') {
74025 advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
74026 } else if (DUK__L1() == '=') {
74027 advtok = DUK__ADVTOK(2, DUK_TOK_LE);
74028 } else if (DUK__L1() == '<') {
74029 advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
74030 } else {
74031 advtok = DUK__ADVTOK(1, DUK_TOK_LT);
74032 }
74033 break;
74034 case DUK_ASC_RANGLE: /* '>' */
74035 if (DUK__L1() == '>' && DUK__L2() == '>' && DUK__L3() == '=') {
74036 advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
74037 } else if (DUK__L1() == '>' && DUK__L2() == '>') {
74038 advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
74039 } else if (DUK__L1() == '>' && DUK__L2() == '=') {
74040 advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
74041 } else if (DUK__L1() == '=') {
74042 advtok = DUK__ADVTOK(2, DUK_TOK_GE);
74043 } else if (DUK__L1() == '>') {
74044 advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
74045 } else {
74046 advtok = DUK__ADVTOK(1, DUK_TOK_GT);
74047 }
74048 break;
74049 case DUK_ASC_EQUALS: /* '=' */
74050 if (DUK__L1() == '=' && DUK__L2() == '=') {
74051 advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
74052 } else if (DUK__L1() == '=') {
74053 advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
74054 } else {
74055 advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
74056 }
74057 break;
74058 case DUK_ASC_EXCLAMATION: /* '!' */
74059 if (DUK__L1() == '=' && DUK__L2() == '=') {
74060 advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
74061 } else if (DUK__L1() == '=') {
74062 advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
74063 } else {
74064 advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
74065 }
74066 break;
74067 case DUK_ASC_PLUS: /* '+' */
74068 if (DUK__L1() == '+') {
74069 advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
74070 } else if (DUK__L1() == '=') {
74071 advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
74072 } else {
74073 advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
74074 }
74075 break;
74076 case DUK_ASC_MINUS: /* '-' */
74077 if (DUK__L1() == '-') {
74078 advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
74079 } else if (DUK__L1() == '=') {
74080 advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
74081 } else {
74082 advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
74083 }
74084 break;
74085 case DUK_ASC_STAR: /* '*' */
74086 if (DUK__L1() == '=') {
74087 advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
74088 } else {
74089 advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
74090 }
74091 break;
74092 case DUK_ASC_PERCENT: /* '%' */
74093 if (DUK__L1() == '=') {
74094 advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
74095 } else {
74096 advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
74097 }
74098 break;
74099 case DUK_ASC_AMP: /* '&' */
74100 if (DUK__L1() == '&') {
74101 advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
74102 } else if (DUK__L1() == '=') {
74103 advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
74104 } else {
74105 advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
74106 }
74107 break;
74108 case DUK_ASC_PIPE: /* '|' */
74109 if (DUK__L1() == '|') {
74110 advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
74111 } else if (DUK__L1() == '=') {
74112 advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
74113 } else {
74114 advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
74115 }
74116 break;
74117 case DUK_ASC_CARET: /* '^' */
74118 if (DUK__L1() == '=') {
74119 advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
74120 } else {
74121 advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
74122 }
74123 break;
74124 case DUK_ASC_TILDE: /* '~' */
74125 advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
74126 break;
74127 case DUK_ASC_QUESTION: /* '?' */
74128 advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
74129 break;
74130 case DUK_ASC_COLON: /* ':' */
74131 advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
74132 break;
74133 case DUK_ASC_DOUBLEQUOTE: /* '"' */
74134 case DUK_ASC_SINGLEQUOTE: { /* '\'' */
74135 duk_small_int_t quote = x; /* Note: duk_uint8_t type yields larger code */
74136 duk_small_int_t adv;
74137
74138 DUK__INITBUFFER(lex_ctx);
74139 for (;;) {
74140 DUK__ADVANCECHARS(lex_ctx, 1); /* eat opening quote on first loop */
74141 x = DUK__L0();
74142 if (x < 0 || duk_unicode_is_line_terminator(x)) {
74143 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in string literal");
74144 }
74145 if (x == quote) {
74146 DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing quote */
74147 break;
74148 }
74149 if (x == '\\') {
74150 /* DUK__L0 -> '\' char
74151 * DUK__L1 ... DUK__L5 -> more lookup
74152 */
74153
74154 x = DUK__L1();
74155
74156 /* How much to advance before next loop; note that next loop
74157 * will advance by 1 anyway, so -1 from the total escape
74158 * length (e.g. len('\uXXXX') - 1 = 6 - 1). As a default,
74159 * 1 is good.
74160 */
74161 adv = 2 - 1; /* note: long live range */
74162
74163 if (x < 0) {
74164 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in string literal");
74165 }
74167 /* line continuation */
74168 if (x == 0x000d && DUK__L2() == 0x000a) {
74169 /* CR LF again a special case */
74170 adv = 3 - 1;
74171 }
74172 } else if (x == '\'') {
74173 DUK__APPENDBUFFER(lex_ctx, 0x0027);
74174 } else if (x == '"') {
74175 DUK__APPENDBUFFER(lex_ctx, 0x0022);
74176 } else if (x == '\\') {
74177 DUK__APPENDBUFFER(lex_ctx, 0x005c);
74178 } else if (x == 'b') {
74179 DUK__APPENDBUFFER(lex_ctx, 0x0008);
74180 } else if (x == 'f') {
74181 DUK__APPENDBUFFER(lex_ctx, 0x000c);
74182 } else if (x == 'n') {
74183 DUK__APPENDBUFFER(lex_ctx, 0x000a);
74184 } else if (x == 'r') {
74185 DUK__APPENDBUFFER(lex_ctx, 0x000d);
74186 } else if (x == 't') {
74187 DUK__APPENDBUFFER(lex_ctx, 0x0009);
74188 } else if (x == 'v') {
74189 DUK__APPENDBUFFER(lex_ctx, 0x000b);
74190 } else if (x == 'x') {
74191 adv = 4 - 1;
74193 } else if (x == 'u') {
74194 adv = 6 - 1;
74196 } else if (DUK__ISDIGIT(x)) {
74197 duk_codepoint_t ch = 0; /* initialized to avoid warnings of unused var */
74198
74199 /*
74200 * Octal escape or zero escape:
74201 * \0 (lookahead not DecimalDigit)
74202 * \1 ... \7 (lookahead not DecimalDigit)
74203 * \ZeroToThree OctalDigit (lookahead not DecimalDigit)
74204 * \FourToSeven OctalDigit (no lookahead restrictions)
74205 * \ZeroToThree OctalDigit OctalDigit (no lookahead restrictions)
74206 *
74207 * Zero escape is part of the standard syntax. Octal escapes are
74208 * defined in E5 Section B.1.2, and are only allowed in non-strict mode.
74209 * Any other productions starting with a decimal digit are invalid.
74210 */
74211
74212 if (x == '0' && !DUK__ISDIGIT(DUK__L2())) {
74213 /* Zero escape (also allowed in non-strict mode) */
74214 ch = 0;
74215 /* adv = 2 - 1 default OK */
74216#if defined(DUK_USE_OCTAL_SUPPORT)
74217 } else if (strict_mode) {
74218 /* No other escape beginning with a digit in strict mode */
74219 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid escape in string literal");
74220 } else if (DUK__ISDIGIT03(x) && DUK__ISOCTDIGIT(DUK__L2()) && DUK__ISOCTDIGIT(DUK__L3())) {
74221 /* Three digit octal escape, digits validated. */
74222 adv = 4 - 1;
74223 ch = (duk__hexval(lex_ctx, x) << 6) +
74224 (duk__hexval(lex_ctx, DUK__L2()) << 3) +
74225 duk__hexval(lex_ctx, DUK__L3());
74226 } else if (((DUK__ISDIGIT03(x) && !DUK__ISDIGIT(DUK__L3())) || DUK__ISDIGIT47(x)) &&
74228 /* Two digit octal escape, digits validated.
74229 *
74230 * The if-condition is a bit tricky. We could catch e.g.
74231 * '\039' in the three-digit escape and fail it there (by
74232 * validating the digits), but we want to avoid extra
74233 * additional validation code.
74234 */
74235 adv = 3 - 1;
74236 ch = (duk__hexval(lex_ctx, x) << 3) +
74237 duk__hexval(lex_ctx, DUK__L2());
74238 } else if (DUK__ISDIGIT(x) && !DUK__ISDIGIT(DUK__L2())) {
74239 /* One digit octal escape, digit validated. */
74240 /* adv = 2 default OK */
74241 ch = duk__hexval(lex_ctx, x);
74242#else
74243 /* fall through to error */
74244#endif
74245 } else {
74246 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid escape in string literal");
74247 }
74248
74249 DUK__APPENDBUFFER(lex_ctx, ch);
74250 } else {
74251 /* escaped NonEscapeCharacter */
74252 DUK__APPENDBUFFER(lex_ctx, x);
74253 }
74254 DUK__ADVANCECHARS(lex_ctx, adv);
74255
74256 /* Track number of escapes; count not really needed but directive
74257 * prologues need to detect whether there were any escapes or line
74258 * continuations or not.
74259 */
74260 out_token->num_escapes++;
74261 } else {
74262 /* part of string */
74263 DUK__APPENDBUFFER(lex_ctx, x);
74264 }
74265 }
74266
74267 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74268 out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74269
74270 DUK__INITBUFFER(lex_ctx); /* free some memory */
74271
74272 advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
74273 break;
74274 }
74275 default:
74276 goto slow_path;
74277 } /* switch */
74278
74279 goto skip_slow_path;
74280
74281 slow_path:
74283 if (x == 0x000d && DUK__L1() == 0x000a) {
74284 /*
74285 * E5 Section 7.3: CR LF is detected as a single line terminator for
74286 * line numbers. Here we also detect it as a single line terminator
74287 * token.
74288 */
74289 DUK__ADVANCECHARS(lex_ctx, 2);
74290 } else {
74291 DUK__ADVANCECHARS(lex_ctx, 1);
74292 }
74293 got_lineterm = 1;
74294 goto restart_lineupdate;
74295 } else if (duk_unicode_is_identifier_start(x) || x == '\\') {
74296 /*
74297 * Parse an identifier and then check whether it is:
74298 * - reserved word (keyword or other reserved word)
74299 * - "null" (NullLiteral)
74300 * - "true" (BooleanLiteral)
74301 * - "false" (BooleanLiteral)
74302 * - anything else => identifier
74303 *
74304 * This does not follow the E5 productions cleanly, but is
74305 * useful and compact.
74306 *
74307 * Note that identifiers may contain Unicode escapes,
74308 * see E5 Sections 6 and 7.6. They must be decoded first,
74309 * and the result checked against allowed characters.
74310 * The above if-clause accepts an identifier start and an
74311 * '\' character -- no other token can begin with a '\'.
74312 *
74313 * Note that "get" and "set" are not reserved words in E5
74314 * specification so they are recognized as plain identifiers
74315 * (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
74316 * used now). The compiler needs to work around this.
74317 *
74318 * Strictly speaking, following Ecmascript longest match
74319 * specification, an invalid escape for the first character
74320 * should cause a syntax error. However, an invalid escape
74321 * for IdentifierParts should just terminate the identifier
74322 * early (longest match), and let the next tokenization
74323 * fail. For instance Rhino croaks with 'foo\z' when
74324 * parsing the identifier. This has little practical impact.
74325 */
74326
74327 duk_small_int_t i, i_end;
74328 duk_bool_t first = 1;
74329 duk_hstring *str;
74330
74331 DUK__INITBUFFER(lex_ctx);
74332 for (;;) {
74333 /* re-lookup first char on first loop */
74334 if (DUK__L0() == '\\') {
74335 duk_codepoint_t ch;
74336 if (DUK__L1() != 'u') {
74337 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid unicode escape in identifier");
74338 }
74339
74340 ch = duk__decode_uniesc_from_window(lex_ctx, 2);
74341
74342 /* IdentifierStart is stricter than IdentifierPart, so if the first
74343 * character is escaped, must have a stricter check here.
74344 */
74346 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid unicode escape in identifier");
74347 }
74348 DUK__APPENDBUFFER(lex_ctx, ch);
74349 DUK__ADVANCECHARS(lex_ctx, 6);
74350
74351 /* Track number of escapes: necessary for proper keyword
74352 * detection.
74353 */
74354 out_token->num_escapes++;
74355 } else {
74356 /* Note: first character is checked against this. But because
74357 * IdentifierPart includes all IdentifierStart characters, and
74358 * the first character (if unescaped) has already been checked
74359 * in the if condition, this is OK.
74360 */
74362 break;
74363 }
74364 DUK__APPENDBUFFER(lex_ctx, DUK__L0());
74365 DUK__ADVANCECHARS(lex_ctx, 1);
74366 }
74367 first = 0;
74368 }
74369
74370 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74371 out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74372 str = out_token->str1;
74373 DUK_ASSERT(str != NULL);
74374 out_token->t_nores = DUK_TOK_IDENTIFIER;
74375
74376 DUK__INITBUFFER(lex_ctx); /* free some memory */
74377
74378 /*
74379 * Interned identifier is compared against reserved words, which are
74380 * currently interned into the heap context. See genbuiltins.py.
74381 *
74382 * Note that an escape in the identifier disables recognition of
74383 * keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
74384 * identifier named "if"). This is not necessarily compliant,
74385 * see test-dec-escaped-char-in-keyword.js.
74386 *
74387 * Note: "get" and "set" are awkward. They are not officially
74388 * ReservedWords (and indeed e.g. "var set = 1;" is valid), and
74389 * must come out as DUK_TOK_IDENTIFIER. The compiler needs to
74390 * work around this a bit.
74391 */
74392
74393 /* XXX: optimize by adding the token numbers directly into the
74394 * always interned duk_hstring objects (there should be enough
74395 * flag bits free for that)?
74396 */
74397
74399
74400 advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
74401 if (out_token->num_escapes == 0) {
74402 for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
74403 DUK_ASSERT(i >= 0 && i < DUK_HEAP_NUM_STRINGS);
74404 if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
74405 advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
74406 break;
74407 }
74408 }
74409 }
74410 } else if (DUK__ISDIGIT(x) || (x == '.')) {
74411 /* Note: decimal number may start with a period, but must be followed by a digit */
74412
74413 /*
74414 * DecimalLiteral, HexIntegerLiteral, OctalIntegerLiteral
74415 * "pre-parsing", followed by an actual, accurate parser step.
74416 *
74417 * Note: the leading sign character ('+' or '-') is -not- part of
74418 * the production in E5 grammar, and that the a DecimalLiteral
74419 * starting with a '0' must be followed by a non-digit. Leading
74420 * zeroes are syntax errors and must be checked for.
74421 *
74422 * XXX: the two step parsing process is quite awkward, it would
74423 * be more straightforward to allow numconv to parse the longest
74424 * valid prefix (it already does that, it only needs to indicate
74425 * where the input ended). However, the lexer decodes characters
74426 * using a lookup window, so this is not a trivial change.
74427 */
74428
74429 /* XXX: because of the final check below (that the literal is not
74430 * followed by a digit), this could maybe be simplified, if we bail
74431 * out early from a leading zero (and if there are no periods etc).
74432 * Maybe too complex.
74433 */
74434
74435 duk_double_t val;
74436 duk_bool_t int_only = 0;
74437 duk_bool_t allow_hex = 0;
74438 duk_small_int_t state; /* 0=before period/exp,
74439 * 1=after period, before exp
74440 * 2=after exp, allow '+' or '-'
74441 * 3=after exp and exp sign
74442 */
74443 duk_small_uint_t s2n_flags;
74445
74446 DUK__INITBUFFER(lex_ctx);
74447 y = DUK__L1();
74448 if (x == '0' && (y == 'x' || y == 'X')) {
74449 DUK__APPENDBUFFER(lex_ctx, x);
74450 DUK__APPENDBUFFER(lex_ctx, y);
74451 DUK__ADVANCECHARS(lex_ctx, 2);
74452 int_only = 1;
74453 allow_hex = 1;
74454#if defined(DUK_USE_OCTAL_SUPPORT)
74455 } else if (!strict_mode && x == '0' && DUK__ISDIGIT(y)) {
74456 /* Note: if DecimalLiteral starts with a '0', it can only be
74457 * followed by a period or an exponent indicator which starts
74458 * with 'e' or 'E'. Hence the if-check above ensures that
74459 * OctalIntegerLiteral is the only valid NumericLiteral
74460 * alternative at this point (even if y is, say, '9').
74461 */
74462
74463 DUK__APPENDBUFFER(lex_ctx, x);
74464 DUK__ADVANCECHARS(lex_ctx, 1);
74465 int_only = 1;
74466#endif
74467 }
74468
74469 state = 0;
74470 for (;;) {
74471 x = DUK__L0(); /* re-lookup curr char on first round */
74472 if (DUK__ISDIGIT(x)) {
74473 /* Note: intentionally allow leading zeroes here, as the
74474 * actual parser will check for them.
74475 */
74476 if (state == 2) {
74477 state = 3;
74478 }
74479 } else if (allow_hex && DUK__ISHEXDIGIT(x)) {
74480 /* Note: 'e' and 'E' are also accepted here. */
74481 ;
74482 } else if (x == '.') {
74483 if (state >= 1 || int_only) {
74484 break;
74485 } else {
74486 state = 1;
74487 }
74488 } else if (x == 'e' || x == 'E') {
74489 if (state >= 2 || int_only) {
74490 break;
74491 } else {
74492 state = 2;
74493 }
74494 } else if (x == '-' || x == '+') {
74495 if (state != 2) {
74496 break;
74497 } else {
74498 state = 3;
74499 }
74500 } else {
74501 break;
74502 }
74503 DUK__APPENDBUFFER(lex_ctx, x);
74504 DUK__ADVANCECHARS(lex_ctx, 1);
74505 }
74506
74507 /* XXX: better coercion */
74508 duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74509
74510 s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
74514#if defined(DUK_USE_OCTAL_SUPPORT)
74515 (strict_mode ? 0 : DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) |
74516#endif
74518
74519 duk_dup((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74520 duk_numconv_parse((duk_context *) lex_ctx->thr, 10 /*radix*/, s2n_flags);
74521 val = duk_to_number((duk_context *) lex_ctx->thr, -1);
74522 if (DUK_ISNAN(val)) {
74523 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid numeric literal");
74524 }
74525 duk_replace((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx); /* could also just pop? */
74526
74527 DUK__INITBUFFER(lex_ctx); /* free some memory */
74528
74529 /* Section 7.8.3 (note): NumericLiteral must be followed by something other than
74530 * IdentifierStart or DecimalDigit.
74531 */
74532
74534 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid numeric literal");
74535 }
74536
74537 out_token->num = val;
74538 advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
74539 } else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
74540 DUK__ADVANCECHARS(lex_ctx, 1);
74541 goto restart;
74542 } else if (x < 0) {
74543 advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
74544 } else {
74545 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid token");
74546 }
74547 skip_slow_path:
74548
74549 /*
74550 * Shared exit path
74551 */
74552
74553 DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
74554 out_token->t = advtok & 0xff;
74555 if (out_token->t_nores < 0) {
74556 out_token->t_nores = out_token->t;
74557 }
74558 out_token->lineterm = got_lineterm;
74559
74560 /* Automatic semicolon insertion is allowed if a token is preceded
74561 * by line terminator(s), or terminates a statement list (right curly
74562 * or EOF).
74563 */
74564 if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
74565 out_token->allow_auto_semi = 1;
74566 } else {
74567 out_token->allow_auto_semi = 0;
74568 }
74569}
74570
74571#if defined(DUK_USE_REGEXP_SUPPORT)
74572
74573/*
74574 * Parse a RegExp token. The grammar is described in E5 Section 15.10.
74575 * Terminal constructions (such as quantifiers) are parsed directly here.
74576 *
74577 * 0xffffffffU is used as a marker for "infinity" in quantifiers. Further,
74578 * DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
74579 * will be accepted for a quantifier.
74580 */
74581
74583 duk_small_int_t advtok = 0; /* init is unnecessary but suppresses "may be used uninitialized" warnings */
74584 duk_codepoint_t x, y;
74585
74586 if (++lex_ctx->token_count >= lex_ctx->token_limit) {
74587 DUK_ERROR_RANGE(lex_ctx->thr, "token limit");
74588 return; /* unreachable */
74589 }
74590
74591 DUK_MEMZERO(out_token, sizeof(*out_token));
74592
74593 x = DUK__L0();
74594 y = DUK__L1();
74595
74596 DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
74597
74598 switch (x) {
74599 case '|': {
74601 break;
74602 }
74603 case '^': {
74605 break;
74606 }
74607 case '$': {
74608 advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
74609 break;
74610 }
74611 case '?': {
74612 out_token->qmin = 0;
74613 out_token->qmax = 1;
74614 if (y == '?') {
74615 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74616 out_token->greedy = 0;
74617 } else {
74618 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74619 out_token->greedy = 1;
74620 }
74621 break;
74622 }
74623 case '*': {
74624 out_token->qmin = 0;
74625 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74626 if (y == '?') {
74627 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74628 out_token->greedy = 0;
74629 } else {
74630 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74631 out_token->greedy = 1;
74632 }
74633 break;
74634 }
74635 case '+': {
74636 out_token->qmin = 1;
74637 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74638 if (y == '?') {
74639 advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74640 out_token->greedy = 0;
74641 } else {
74642 advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74643 out_token->greedy = 1;
74644 }
74645 break;
74646 }
74647 case '{': {
74648 /* Production allows 'DecimalDigits', including leading zeroes */
74649 duk_uint_fast32_t val1 = 0;
74651 duk_small_int_t digits = 0;
74652#if defined(DUK_USE_ES6_REGEXP_BRACES)
74653 duk_lexer_point lex_pt;
74654#endif
74655
74656#if defined(DUK_USE_ES6_REGEXP_BRACES)
74657 /* Store lexer position, restoring if quantifier is invalid. */
74658 DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
74659#endif
74660
74661 for (;;) {
74662 DUK__ADVANCECHARS(lex_ctx, 1); /* eat '{' on entry */
74663 x = DUK__L0();
74664 if (DUK__ISDIGIT(x)) {
74665 digits++;
74666 val1 = val1 * 10 + (duk_uint_fast32_t) duk__hexval(lex_ctx, x);
74667 } else if (x == ',') {
74668 if (digits > DUK__MAX_RE_QUANT_DIGITS) {
74669 goto invalid_quantifier;
74670 }
74671 if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
74672 goto invalid_quantifier;
74673 }
74674 if (DUK__L1() == '}') {
74675 /* form: { DecimalDigits , }, val1 = min count */
74676 if (digits == 0) {
74677 goto invalid_quantifier;
74678 }
74679 out_token->qmin = val1;
74680 out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74681 DUK__ADVANCECHARS(lex_ctx, 2);
74682 break;
74683 }
74684 val2 = val1;
74685 val1 = 0;
74686 digits = 0; /* not strictly necessary because of lookahead '}' above */
74687 } else if (x == '}') {
74688 if (digits > DUK__MAX_RE_QUANT_DIGITS) {
74689 goto invalid_quantifier;
74690 }
74691 if (digits == 0) {
74692 goto invalid_quantifier;
74693 }
74694 if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
74695 /* val2 = min count, val1 = max count */
74696 out_token->qmin = val2;
74697 out_token->qmax = val1;
74698 } else {
74699 /* val1 = count */
74700 out_token->qmin = val1;
74701 out_token->qmax = val1;
74702 }
74703 DUK__ADVANCECHARS(lex_ctx, 1);
74704 break;
74705 } else {
74706 goto invalid_quantifier;
74707 }
74708 }
74709 if (DUK__L0() == '?') {
74710 out_token->greedy = 0;
74711 DUK__ADVANCECHARS(lex_ctx, 1);
74712 } else {
74713 out_token->greedy = 1;
74714 }
74715 advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
74716 break;
74717 invalid_quantifier:
74718#if defined(DUK_USE_ES6_REGEXP_BRACES)
74719 /* Failed to match the quantifier, restore lexer and parse
74720 * opening brace as a literal.
74721 */
74722 DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
74723 advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
74724 out_token->num = '{';
74725#else
74726 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp quantifier");
74727#endif
74728 break;
74729 }
74730 case '.': {
74732 break;
74733 }
74734 case '\\': {
74735 /* The E5.1 specification does not seem to allow IdentifierPart characters
74736 * to be used as identity escapes. Unfortunately this includes '$', which
74737 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
74738 * Many other implementations (including V8 and Rhino, for instance) do
74739 * accept '\$' as a valid identity escape, which is quite pragmatic.
74740 * See: test-regexp-identity-escape-dollar.js.
74741 */
74742
74743 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR); /* default: char escape (two chars) */
74744 if (y == 'b') {
74746 } else if (y == 'B') {
74748 } else if (y == 'f') {
74749 out_token->num = 0x000c;
74750 } else if (y == 'n') {
74751 out_token->num = 0x000a;
74752 } else if (y == 't') {
74753 out_token->num = 0x0009;
74754 } else if (y == 'r') {
74755 out_token->num = 0x000d;
74756 } else if (y == 'v') {
74757 out_token->num = 0x000b;
74758 } else if (y == 'c') {
74759 x = DUK__L2();
74760 if ((x >= 'a' && x <= 'z') ||
74761 (x >= 'A' && x <= 'Z')) {
74762 out_token->num = (x % 32);
74763 advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
74764 } else {
74765 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74766 }
74767 } else if (y == 'x') {
74768 out_token->num = duk__decode_hexesc_from_window(lex_ctx, 2);
74769 advtok = DUK__ADVTOK(4, DUK_RETOK_ATOM_CHAR);
74770 } else if (y == 'u') {
74771 out_token->num = duk__decode_uniesc_from_window(lex_ctx, 2);
74772 advtok = DUK__ADVTOK(6, DUK_RETOK_ATOM_CHAR);
74773 } else if (y == 'd') {
74774 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
74775 } else if (y == 'D') {
74777 } else if (y == 's') {
74778 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
74779 } else if (y == 'S') {
74781 } else if (y == 'w') {
74783 } else if (y == 'W') {
74785 } else if (DUK__ISDIGIT(y)) {
74786 /* E5 Section 15.10.2.11 */
74787 if (y == '0') {
74788 if (DUK__ISDIGIT(DUK__L2())) {
74789 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74790 }
74791 out_token->num = 0x0000;
74792 advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
74793 } else {
74794 /* XXX: shared parsing? */
74795 duk_uint_fast32_t val = 0;
74797 for (i = 0; ; i++) {
74798 if (i >= DUK__MAX_RE_DECESC_DIGITS) {
74799 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74800 }
74801 DUK__ADVANCECHARS(lex_ctx, 1); /* eat backslash on entry */
74802 x = DUK__L0();
74803 if (!DUK__ISDIGIT(x)) {
74804 break;
74805 }
74806 val = val * 10 + (duk_uint_fast32_t) duk__hexval(lex_ctx, x);
74807 }
74808 /* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
74810 out_token->num = val;
74811 }
74812 } else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
74814 y == '$' ||
74815#endif
74816 y == DUK_UNICODE_CP_ZWNJ ||
74817 y == DUK_UNICODE_CP_ZWJ) {
74818 /* IdentityEscape, with dollar added as a valid additional
74819 * non-standard escape (see test-regexp-identity-escape-dollar.js).
74820 * Careful not to match end-of-buffer (<0) here.
74821 */
74822 out_token->num = y;
74823 } else {
74824 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74825 }
74826 break;
74827 }
74828 case '(': {
74829 /* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
74830
74831 if (y == '?') {
74832 if (DUK__L2() == '=') {
74833 /* (?= */
74835 } else if (DUK__L2() == '!') {
74836 /* (?! */
74838 } else if (DUK__L2() == ':') {
74839 /* (?: */
74841 }
74842 } else {
74843 /* ( */
74845 }
74846 break;
74847 }
74848 case ')': {
74850 break;
74851 }
74852 case '[': {
74853 /*
74854 * To avoid creating a heavy intermediate value for the list of ranges,
74855 * only the start token ('[' or '[^') is parsed here. The regexp
74856 * compiler parses the ranges itself.
74857 */
74859 if (y == '^') {
74861 }
74862 break;
74863 }
74864#if !defined(DUK_USE_ES6_REGEXP_BRACES)
74865 case '}':
74866#endif
74867 case ']': {
74868 /* Although these could be parsed as PatternCharacters unambiguously (here),
74869 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
74870 */
74871 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp character");
74872 break;
74873 }
74874 case -1: {
74875 /* EOF */
74876 advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
74877 break;
74878 }
74879 default: {
74880 /* PatternCharacter, all excluded characters are matched by cases above */
74881 advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
74882 out_token->num = x;
74883 break;
74884 }
74885 }
74886
74887 /*
74888 * Shared exit path
74889 */
74890
74891 DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
74892 out_token->t = advtok & 0xff;
74893}
74894
74895/*
74896 * Special parser for character classes; calls callback for every
74897 * range parsed and returns the number of ranges present.
74898 */
74900/* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
74901 * required anyway. We could use that BUT we need to update the regexp compiler
74902 * 'nranges' too. Work this out a bit more cleanly to save space.
74903 */
74904
74905/* XXX: the handling of character range detection is a bit convoluted.
74906 * Try to simplify and make smaller.
74907 */
74908
74909/* XXX: logic for handling character ranges is now incorrect, it will accept
74910 * e.g. [\d-z] whereas it should croak from it? SMJS accepts this too, though.
74911 *
74912 * Needs a read through and a lot of additional tests.
74913 */
74914
74917 duk_re_range_callback gen_range,
74918 void *userdata,
74919 const duk_uint16_t *ranges,
74920 duk_small_int_t num) {
74921 const duk_uint16_t *ranges_end;
74922
74923 DUK_UNREF(lex_ctx);
74924
74925 ranges_end = ranges + num;
74926 while (ranges < ranges_end) {
74927 /* mark range 'direct', bypass canonicalization (see Wiki) */
74928 gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
74929 ranges += 2;
74930 }
74931}
74932
74933DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
74934 duk_codepoint_t start = -1;
74935 duk_codepoint_t ch;
74937 duk_bool_t dash = 0;
74938
74939 DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
74940
74941 for (;;) {
74942 x = DUK__L0();
74943 DUK__ADVANCECHARS(lex_ctx, 1);
74944
74945 ch = -1; /* not strictly necessary, but avoids "uninitialized variable" warnings */
74946 DUK_UNREF(ch);
74947
74948 if (x < 0) {
74949 DUK_ERROR_SYNTAX(lex_ctx->thr, "eof in character class");
74950 } else if (x == ']') {
74951 DUK_ASSERT(!dash); /* lookup should prevent this */
74952 if (start >= 0) {
74953 gen_range(userdata, start, start, 0);
74954 }
74955 break;
74956 } else if (x == '-') {
74957 if (start >= 0 && !dash && DUK__L0() != ']') {
74958 /* '-' as a range indicator */
74959 dash = 1;
74960 continue;
74961 } else {
74962 /* '-' verbatim */
74963 ch = x;
74964 }
74965 } else if (x == '\\') {
74966 /*
74967 * The escapes are same as outside a character class, except that \b has a
74968 * different meaning, and \B and backreferences are prohibited (see E5
74969 * Section 15.10.2.19). However, it's difficult to share code because we
74970 * handle e.g. "\n" very differently: here we generate a single character
74971 * range for it.
74972 */
74973
74974 x = DUK__L0();
74975 DUK__ADVANCECHARS(lex_ctx, 1);
74976
74977 if (x == 'b') {
74978 /* Note: '\b' in char class is different than outside (assertion),
74979 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
74980 * check below.
74981 */
74982 ch = 0x0008;
74983 } else if (x == 'f') {
74984 ch = 0x000c;
74985 } else if (x == 'n') {
74986 ch = 0x000a;
74987 } else if (x == 't') {
74988 ch = 0x0009;
74989 } else if (x == 'r') {
74990 ch = 0x000d;
74991 } else if (x == 'v') {
74992 ch = 0x000b;
74993 } else if (x == 'c') {
74994 x = DUK__L0();
74995 DUK__ADVANCECHARS(lex_ctx, 1);
74996 if ((x >= 'a' && x <= 'z') ||
74997 (x >= 'A' && x <= 'Z')) {
74998 ch = (x % 32);
74999 } else {
75000 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
75001 return; /* never reached, but avoids warnings of
75002 * potentially unused variables.
75003 */
75004 }
75005 } else if (x == 'x') {
75006 ch = duk__decode_hexesc_from_window(lex_ctx, 0);
75007 DUK__ADVANCECHARS(lex_ctx, 2);
75008 } else if (x == 'u') {
75009 ch = duk__decode_uniesc_from_window(lex_ctx, 0);
75010 DUK__ADVANCECHARS(lex_ctx, 4);
75011 } else if (x == 'd') {
75013 gen_range,
75014 userdata,
75016 sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
75017 ch = -1;
75018 } else if (x == 'D') {
75020 gen_range,
75021 userdata,
75023 sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
75024 ch = -1;
75025 } else if (x == 's') {
75027 gen_range,
75028 userdata,
75030 sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
75031 ch = -1;
75032 } else if (x == 'S') {
75034 gen_range,
75035 userdata,
75037 sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
75038 ch = -1;
75039 } else if (x == 'w') {
75041 gen_range,
75042 userdata,
75044 sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
75045 ch = -1;
75046 } else if (x == 'W') {
75048 gen_range,
75049 userdata,
75051 sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
75052 ch = -1;
75053 } else if (DUK__ISDIGIT(x)) {
75054 /* DecimalEscape, only \0 is allowed, no leading zeroes are allowed */
75055 if (x == '0' && !DUK__ISDIGIT(DUK__L0())) {
75056 ch = 0x0000;
75057 } else {
75058 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
75059 }
75060 } else if (!duk_unicode_is_identifier_part(x)
75062 || x == '$'
75063#endif
75064 ) {
75065 /* IdentityEscape */
75066 ch = x;
75067 } else {
75068 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
75069 }
75070 } else {
75071 /* character represents itself */
75072 ch = x;
75073 }
75074
75075 /* ch is a literal character here or -1 if parsed entity was
75076 * an escape such as "\s".
75077 */
75078
75079 if (ch < 0) {
75080 /* multi-character sets not allowed as part of ranges, see
75081 * E5 Section 15.10.2.15, abstract operation CharacterRange.
75082 */
75083 if (start >= 0) {
75084 if (dash) {
75085 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid range");
75086 } else {
75087 gen_range(userdata, start, start, 0);
75088 start = -1;
75089 /* dash is already 0 */
75090 }
75091 }
75092 } else {
75093 if (start >= 0) {
75094 if (dash) {
75095 if (start > ch) {
75096 DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid range");
75097 }
75098 gen_range(userdata, start, ch, 0);
75099 start = -1;
75100 dash = 0;
75101 } else {
75102 gen_range(userdata, start, start, 0);
75103 start = ch;
75104 /* dash is already 0 */
75105 }
75106 } else {
75107 start = ch;
75108 }
75109 }
75110 }
75111
75112 return;
75113}
75115#endif /* DUK_USE_REGEXP_SUPPORT */
75116#line 1 "duk_numconv.c"
75118 * Number-to-string and string-to-number conversions.
75119 *
75120 * Slow path number-to-string and string-to-number conversion is based on
75121 * a Dragon4 variant, with fast paths for small integers. Big integer
75122 * arithmetic is needed for guaranteeing that the conversion is correct
75123 * and uses a minimum number of digits. The big number arithmetic has a
75124 * fixed maximum size and does not require dynamic allocations.
75125 *
75126 * See: doc/number-conversion.rst.
75127 */
75128
75129/* include removed: duk_internal.h */
75130
75131#define DUK__IEEE_DOUBLE_EXP_BIAS 1023
75132#define DUK__IEEE_DOUBLE_EXP_MIN (-1022) /* biased exp == 0 -> denormal, exp -1022 */
75133
75134#define DUK__DIGITCHAR(x) duk_lc_digits[(x)]
75135
75136/*
75137 * Tables generated with src/gennumdigits.py.
75138 *
75139 * duk__str2num_digits_for_radix indicates, for each radix, how many input
75140 * digits should be considered significant for string-to-number conversion.
75141 * The input is also padded to this many digits to give the Dragon4
75142 * conversion enough (apparent) precision to work with.
75143 *
75144 * duk__str2num_exp_limits indicates, for each radix, the radix-specific
75145 * minimum/maximum exponent values (for a Dragon4 integer mantissa)
75146 * below and above which the number is guaranteed to underflow to zero
75147 * or overflow to Infinity. This allows parsing to keep bigint values
75148 * bounded.
75149 */
75150
75151DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
75152 69, 44, 35, 30, 27, 25, 23, 22, 20, 20, /* 2 to 11 */
75153 20, 19, 19, 18, 18, 17, 17, 17, 16, 16, /* 12 to 21 */
75154 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, /* 22 to 31 */
75155 14, 14, 14, 14, 14 /* 31 to 36 */
75156};
75157
75158typedef struct {
75159 duk_int16_t upper;
75160 duk_int16_t lower;
75162
75164 { 957, -1147 }, { 605, -725 }, { 479, -575 }, { 414, -496 },
75165 { 372, -446 }, { 342, -411 }, { 321, -384 }, { 304, -364 },
75166 { 291, -346 }, { 279, -334 }, { 268, -323 }, { 260, -312 },
75167 { 252, -304 }, { 247, -296 }, { 240, -289 }, { 236, -283 },
75168 { 231, -278 }, { 227, -273 }, { 223, -267 }, { 220, -263 },
75169 { 216, -260 }, { 213, -256 }, { 210, -253 }, { 208, -249 },
75170 { 205, -246 }, { 203, -244 }, { 201, -241 }, { 198, -239 },
75171 { 196, -237 }, { 195, -234 }, { 193, -232 }, { 191, -230 },
75172 { 190, -228 }, { 188, -226 }, { 187, -225 },
75174
75175/*
75176 * Limited functionality bigint implementation.
75177 *
75178 * Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
75179 * with the caller responsible for ensuring this is never exceeded. No memory
75180 * allocation (except stack) is needed for bigint computation. Operations
75181 * have been tailored for number conversion needs.
75182 *
75183 * Argument order is "assignment order", i.e. target first, then arguments:
75184 * x <- y * z --> duk__bi_mul(x, y, z);
75185 */
75186
75187/* This upper value has been experimentally determined; debug build will check
75188 * bigint size with assertions.
75189 */
75190#define DUK__BI_MAX_PARTS 37 /* 37x32 = 1184 bits */
75191
75192#ifdef DUK_USE_DDDPRINT
75193#define DUK__BI_PRINT(name,x) duk__bi_print((name),(x))
75194#else
75195#define DUK__BI_PRINT(name,x)
75196#endif
75197
75198/* Current size is about 152 bytes. */
75199typedef struct {
75201 duk_uint32_t v[DUK__BI_MAX_PARTS]; /* low to high */
75202} duk__bigint;
75203
75204#ifdef DUK_USE_DDDPRINT
75205DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
75206 /* Overestimate required size; debug code so not critical to be tight. */
75207 char buf[DUK__BI_MAX_PARTS * 9 + 64];
75208 char *p = buf;
75210
75211 /* No NUL term checks in this debug code. */
75212 p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
75213 if (x->n == 0) {
75214 p += DUK_SPRINTF(p, " 0");
75216 for (i = x->n - 1; i >= 0; i--) {
75217 p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
75218 }
75219
75220 DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
75221}
75222#endif
75223
75224#ifdef DUK_USE_ASSERTIONS
75225DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
75226 return (duk_small_int_t)
75227 ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
75228 ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
75229}
75230#endif
75231
75234
75235 for (i = x->n - 1; i >= 0; i--) {
75236 if (x->v[i] != 0) {
75237 break;
75238 }
75239 }
75240
75241 /* Note: if 'x' is zero, x->n becomes 0 here */
75242 x->n = i + 1;
75243 DUK_ASSERT(duk__bi_is_valid(x));
75244}
75245
75246/* x <- y */
75249
75250 n = y->n;
75251 x->n = n;
75252 if (n == 0) {
75253 return;
75254 }
75255 DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
75256}
75257
75258DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
75259 if (v == 0U) {
75260 x->n = 0;
75261 } else {
75262 x->n = 1;
75263 x->v[0] = v;
75264 }
75265 DUK_ASSERT(duk__bi_is_valid(x));
75266}
75267
75268/* Return value: <0 <=> x < y
75269 * 0 <=> x == y
75270 * >0 <=> x > y
75271 */
75273 duk_small_int_t i, nx, ny;
75274 duk_uint32_t tx, ty;
75275
75276 DUK_ASSERT(duk__bi_is_valid(x));
75277 DUK_ASSERT(duk__bi_is_valid(y));
75278
75279 nx = x->n;
75280 ny = y->n;
75281 if (nx > ny) {
75282 goto ret_gt;
75283 }
75284 if (nx < ny) {
75285 goto ret_lt;
75286 }
75287 for (i = nx - 1; i >= 0; i--) {
75288 tx = x->v[i];
75289 ty = y->v[i];
75290
75291 if (tx > ty) {
75292 goto ret_gt;
75293 }
75294 if (tx < ty) {
75295 goto ret_lt;
75296 }
75297 }
75298
75299 return 0;
75300
75301 ret_gt:
75302 return 1;
75303
75304 ret_lt:
75305 return -1;
75306}
75307
75308/* x <- y + z */
75309#ifdef DUK_USE_64BIT_OPS
75311 duk_uint64_t tmp;
75312 duk_small_int_t i, ny, nz;
75313
75314 DUK_ASSERT(duk__bi_is_valid(y));
75315 DUK_ASSERT(duk__bi_is_valid(z));
75316
75317 if (z->n > y->n) {
75318 duk__bigint *t;
75319 t = y; y = z; z = t;
75320 }
75321 DUK_ASSERT(y->n >= z->n);
75322
75323 ny = y->n; nz = z->n;
75324 tmp = 0U;
75325 for (i = 0; i < ny; i++) {
75327 tmp += y->v[i];
75328 if (i < nz) {
75329 tmp += z->v[i];
75330 }
75331 x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
75332 tmp = tmp >> 32;
75333 }
75334 if (tmp != 0U) {
75336 x->v[i++] = (duk_uint32_t) tmp;
75337 }
75338 x->n = i;
75340
75341 /* no need to normalize */
75342 DUK_ASSERT(duk__bi_is_valid(x));
75343}
75344#else /* DUK_USE_64BIT_OPS */
75346 duk_uint32_t carry, tmp1, tmp2;
75347 duk_small_int_t i, ny, nz;
75348
75349 DUK_ASSERT(duk__bi_is_valid(y));
75350 DUK_ASSERT(duk__bi_is_valid(z));
75351
75352 if (z->n > y->n) {
75353 duk__bigint *t;
75354 t = y; y = z; z = t;
75355 }
75356 DUK_ASSERT(y->n >= z->n);
75357
75358 ny = y->n; nz = z->n;
75359 carry = 0U;
75360 for (i = 0; i < ny; i++) {
75361 /* Carry is detected based on wrapping which relies on exact 32-bit
75362 * types.
75363 */
75365 tmp1 = y->v[i];
75366 tmp2 = tmp1;
75367 if (i < nz) {
75368 tmp2 += z->v[i];
75369 }
75370
75371 /* Careful with carry condition:
75372 * - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
75373 * - If carry added: 0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
75374 */
75375 if (carry) {
75376 tmp2++;
75377 carry = (tmp2 <= tmp1 ? 1U : 0U);
75378 } else {
75379 carry = (tmp2 < tmp1 ? 1U : 0U);
75380 }
75382 x->v[i] = tmp2;
75383 }
75384 if (carry) {
75386 DUK_ASSERT(carry == 1U);
75387 x->v[i++] = carry;
75388 }
75389 x->n = i;
75391
75392 /* no need to normalize */
75393 DUK_ASSERT(duk__bi_is_valid(x));
75394}
75395#endif /* DUK_USE_64BIT_OPS */
75396
75397/* x <- y + z */
75398DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75399 duk__bigint tmp;
75400
75401 DUK_ASSERT(duk__bi_is_valid(y));
75402
75403 /* XXX: this could be optimized; there is only one call site now though */
75404 duk__bi_set_small(&tmp, z);
75405 duk__bi_add(x, y, &tmp);
75406
75407 DUK_ASSERT(duk__bi_is_valid(x));
75408}
75409
75410#if 0 /* unused */
75411/* x <- x + y, use t as temp */
75412DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
75413 duk__bi_add(t, x, y);
75414 duk__bi_copy(x, t);
75415}
75416#endif
75417
75418/* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
75419#ifdef DUK_USE_64BIT_OPS
75421 duk_small_int_t i, ny, nz;
75422 duk_uint32_t ty, tz;
75423 duk_int64_t tmp;
75424
75425 DUK_ASSERT(duk__bi_is_valid(y));
75426 DUK_ASSERT(duk__bi_is_valid(z));
75427 DUK_ASSERT(duk__bi_compare(y, z) >= 0);
75428 DUK_ASSERT(y->n >= z->n);
75429
75430 ny = y->n; nz = z->n;
75431 tmp = 0;
75432 for (i = 0; i < ny; i++) {
75433 ty = y->v[i];
75434 if (i < nz) {
75435 tz = z->v[i];
75436 } else {
75437 tz = 0;
75438 }
75439 tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
75440 x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
75441 tmp = tmp >> 32; /* 0 or -1 */
75442 }
75443 DUK_ASSERT(tmp == 0);
75444
75445 x->n = i;
75446 duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
75447 DUK_ASSERT(duk__bi_is_valid(x));
75448}
75449#else
75451 duk_small_int_t i, ny, nz;
75452 duk_uint32_t tmp1, tmp2, borrow;
75453
75454 DUK_ASSERT(duk__bi_is_valid(y));
75455 DUK_ASSERT(duk__bi_is_valid(z));
75456 DUK_ASSERT(duk__bi_compare(y, z) >= 0);
75457 DUK_ASSERT(y->n >= z->n);
75458
75459 ny = y->n; nz = z->n;
75460 borrow = 0U;
75461 for (i = 0; i < ny; i++) {
75462 /* Borrow is detected based on wrapping which relies on exact 32-bit
75463 * types.
75464 */
75465 tmp1 = y->v[i];
75466 tmp2 = tmp1;
75467 if (i < nz) {
75468 tmp2 -= z->v[i];
75469 }
75470
75471 /* Careful with borrow condition:
75472 * - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
75473 * - If borrow subtracted: 0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
75474 */
75475 if (borrow) {
75476 tmp2--;
75477 borrow = (tmp2 >= tmp1 ? 1U : 0U);
75478 } else {
75479 borrow = (tmp2 > tmp1 ? 1U : 0U);
75480 }
75481
75482 x->v[i] = tmp2;
75483 }
75484 DUK_ASSERT(borrow == 0U);
75485
75486 x->n = i;
75487 duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
75488 DUK_ASSERT(duk__bi_is_valid(x));
75489}
75490#endif
75492#if 0 /* unused */
75493/* x <- y - z */
75494DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75495 duk__bigint tmp;
75496
75497 DUK_ASSERT(duk__bi_is_valid(y));
75498
75499 /* XXX: this could be optimized */
75500 duk__bi_set_small(&tmp, z);
75501 duk__bi_sub(x, y, &tmp);
75502
75503 DUK_ASSERT(duk__bi_is_valid(x));
75504}
75505#endif
75506
75507/* x <- x - y, use t as temp */
75509 duk__bi_sub(t, x, y);
75510 duk__bi_copy(x, t);
75511}
75512
75513/* x <- y * z */
75515 duk_small_int_t i, j, nx, nz;
75516
75517 DUK_ASSERT(duk__bi_is_valid(y));
75518 DUK_ASSERT(duk__bi_is_valid(z));
75519
75520 nx = y->n + z->n; /* max possible */
75522
75523 if (nx == 0) {
75524 /* Both inputs are zero; cases where only one is zero can go
75525 * through main algorithm.
75526 */
75527 x->n = 0;
75528 return;
75529 }
75530
75531 DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * nx));
75532 x->n = nx;
75533
75534 nz = z->n;
75535 for (i = 0; i < y->n; i++) {
75536#ifdef DUK_USE_64BIT_OPS
75537 duk_uint64_t tmp = 0U;
75538 for (j = 0; j < nz; j++) {
75539 tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
75540 x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
75541 tmp = tmp >> 32;
75542 }
75543 if (tmp > 0) {
75544 DUK_ASSERT(i + j < nx);
75546 DUK_ASSERT(x->v[i+j] == 0U);
75547 x->v[i+j] = (duk_uint32_t) tmp;
75548 }
75549#else
75550 /*
75551 * Multiply + add + carry for 32-bit components using only 16x16->32
75552 * multiplies and carry detection based on unsigned overflow.
75553 *
75554 * 1st mult, 32-bit: (A*2^16 + B)
75555 * 2nd mult, 32-bit: (C*2^16 + D)
75556 * 3rd add, 32-bit: E
75557 * 4th add, 32-bit: F
75558 *
75559 * (AC*2^16 + B) * (C*2^16 + D) + E + F
75560 * = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
75561 * = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
75562 * = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
75563 */
75564 duk_uint32_t a, b, c, d, e, f;
75565 duk_uint32_t r, s, t;
75566
75567 a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
75568
75569 f = 0;
75570 for (j = 0; j < nz; j++) {
75571 c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
75572 e = x->v[i+j];
75573
75574 /* build result as: (r << 32) + s: start with (BD + E + F) */
75575 r = 0;
75576 s = b * d;
75577
75578 /* add E */
75579 t = s + e;
75580 if (t < s) { r++; } /* carry */
75581 s = t;
75582
75583 /* add F */
75584 t = s + f;
75585 if (t < s) { r++; } /* carry */
75586 s = t;
75587
75588 /* add BC*2^16 */
75589 t = b * c;
75590 r += (t >> 16);
75591 t = s + ((t & 0xffffUL) << 16);
75592 if (t < s) { r++; } /* carry */
75593 s = t;
75594
75595 /* add AD*2^16 */
75596 t = a * d;
75597 r += (t >> 16);
75598 t = s + ((t & 0xffffUL) << 16);
75599 if (t < s) { r++; } /* carry */
75600 s = t;
75601
75602 /* add AC*2^32 */
75603 t = a * c;
75604 r += t;
75605
75606 DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
75607 (unsigned long) y->v[i], (unsigned long) z->v[j],
75608 (unsigned long) x->v[i+j], (unsigned long) r,
75609 (unsigned long) s));
75610
75611 x->v[i+j] = s;
75612 f = r;
75613 }
75614 if (f > 0U) {
75615 DUK_ASSERT(i + j < nx);
75617 DUK_ASSERT(x->v[i+j] == 0U);
75618 x->v[i+j] = (duk_uint32_t) f;
75619 }
75620#endif /* DUK_USE_64BIT_OPS */
75621 }
75622
75624 DUK_ASSERT(duk__bi_is_valid(x));
75625}
75626
75627/* x <- y * z */
75628DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75629 duk__bigint tmp;
75631 DUK_ASSERT(duk__bi_is_valid(y));
75632
75633 /* XXX: this could be optimized */
75634 duk__bi_set_small(&tmp, z);
75635 duk__bi_mul(x, y, &tmp);
75636
75637 DUK_ASSERT(duk__bi_is_valid(x));
75638}
75639
75640/* x <- x * y, use t as temp */
75642 duk__bi_mul(t, x, y);
75643 duk__bi_copy(x, t);
75644}
75645
75646/* x <- x * y, use t as temp */
75647DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
75648 duk__bi_mul_small(t, x, y);
75649 duk__bi_copy(x, t);
75650}
75653 DUK_ASSERT(duk__bi_is_valid(x));
75654 return (x->n == 0) || ((x->v[0] & 0x01) == 0);
75655}
75656
75658 DUK_ASSERT(duk__bi_is_valid(x));
75659 return (x->n == 0); /* this is the case for normalized numbers */
75660}
75661
75662/* Bigint is 2^52. Used to detect normalized IEEE double mantissa values
75663 * which are at the lowest edge (next floating point value downwards has
75664 * a different exponent). The lowest mantissa has the form:
75665 *
75666 * 1000........000 (52 zeroes; only "hidden bit" is set)
75667 */
75669 DUK_ASSERT(duk__bi_is_valid(x));
75671 (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
75672}
75673
75674/* x <- (1<<y) */
75676 duk_small_int_t n, r;
75677
75678 n = (y / 32) + 1;
75679 DUK_ASSERT(n > 0);
75680 r = y % 32;
75681 DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * n);
75682 x->n = n;
75683 x->v[n - 1] = (((duk_uint32_t) 1) << r);
75684}
75685
75686/* x <- b^y; use t1 and t2 as temps */
75688 /* Fast path the binary case */
75689
75690 DUK_ASSERT(x != t1 && x != t2 && t1 != t2); /* distinct bignums, easy mistake to make */
75691 DUK_ASSERT(b >= 0);
75692 DUK_ASSERT(y >= 0);
75693
75694 if (b == 2) {
75695 duk__bi_twoexp(x, y);
75696 return;
75697 }
75698
75699 /* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
75700
75701 DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
75702
75703 duk__bi_set_small(x, 1);
75704 duk__bi_set_small(t1, b);
75705 for (;;) {
75706 /* Loop structure ensures that we don't compute t1^2 unnecessarily
75707 * on the final round, as that might create a bignum exceeding the
75708 * current DUK__BI_MAX_PARTS limit.
75709 */
75710 if (y & 0x01) {
75711 duk__bi_mul_copy(x, t1, t2);
75712 }
75713 y = y >> 1;
75714 if (y == 0) {
75715 break;
75716 }
75717 duk__bi_mul_copy(t1, t1, t2);
75718 }
75719
75720 DUK__BI_PRINT("exp_small result", x);
75721}
75722
75723/*
75724 * A Dragon4 number-to-string variant, based on:
75725 *
75726 * Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
75727 * Accurately"
75729 * Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
75730 * Quickly and Accurately"
75732 * The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
75733 * i.e. the base implementation without logarithm estimation speedups
75734 * (these would increase code footprint considerably). Fixed-format output
75735 * does not follow the suggestions in the paper; instead, we generate an
75736 * extra digit and round-with-carry.
75737 *
75738 * The same algorithm is used for number parsing (with b=10 and B=2)
75739 * by generating one extra digit and doing rounding manually.
75740 *
75741 * See doc/number-conversion.rst for limitations.
75742 */
75743
75744/* Maximum number of digits generated. */
75745#define DUK__MAX_OUTPUT_DIGITS 1040 /* (Number.MAX_VALUE).toString(2).length == 1024, + spare */
75746
75747/* Maximum number of characters in formatted value. */
75748#define DUK__MAX_FORMATTED_LENGTH 1040 /* (-Number.MAX_VALUE).toString(2).length == 1025, + spare */
75749
75750/* Number and (minimum) size of bigints in the nc_ctx structure. */
75751#define DUK__NUMCONV_CTX_NUM_BIGINTS 7
75752#define DUK__NUMCONV_CTX_BIGINTS_SIZE (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
75753
75754typedef struct {
75755 /* Currently about 7*152 = 1064 bytes. The space for these
75756 * duk__bigints is used also as a temporary buffer for generating
75757 * the final string. This is a bit awkard; a union would be
75758 * more correct.
75759 */
75760 duk__bigint f, r, s, mp, mm, t1, t2;
75761
75762 duk_small_int_t is_s2n; /* if 1, doing a string-to-number; else doing a number-to-string */
75763 duk_small_int_t is_fixed; /* if 1, doing a fixed format output (not free format) */
75764 duk_small_int_t req_digits; /* requested number of output digits; 0 = free-format */
75765 duk_small_int_t abs_pos; /* digit position is absolute, not relative */
75766 duk_small_int_t e; /* exponent for 'f' */
75767 duk_small_int_t b; /* input radix */
75768 duk_small_int_t B; /* output radix */
75769 duk_small_int_t k; /* see algorithm */
75770 duk_small_int_t low_ok; /* see algorithm */
75771 duk_small_int_t high_ok; /* see algorithm */
75772 duk_small_int_t unequal_gaps; /* m+ != m- (very rarely) */
75773
75774 /* Buffer used for generated digits, values are in the range [0,B-1]. */
75775 duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
75776 duk_small_int_t count; /* digit count */
75778
75779/* Note: computes with 'idx' in assertions, so caller beware.
75780 * 'idx' is preincremented, i.e. '1' on first call, because it
75781 * is more convenient for the caller.
75782 */
75783#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x) do { \
75784 DUK_ASSERT((preinc_idx) - 1 >= 0); \
75785 DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
75786 ((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
75787 } while (0)
75788
75789DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
75790 duk_uint8_t *p;
75791 duk_size_t len;
75792 duk_small_int_t dig;
75794
75795 DUK_ASSERT(radix >= 2 && radix <= 36);
75796
75797 /* A 32-bit unsigned integer formats to at most 32 digits (the
75798 * worst case happens with radix == 2). Output the digits backwards,
75799 * and use a memmove() to get them in the right place.
75800 */
75801
75802 p = buf + 32;
75803 for (;;) {
75804 t = x / radix;
75805 dig = x - t * radix;
75806 x = t;
75807
75808 DUK_ASSERT(dig >= 0 && dig < 36);
75809 *(--p) = DUK__DIGITCHAR(dig);
75810
75811 if (x == 0) {
75812 break;
75813 }
75814 }
75815 len = (duk_size_t) ((buf + 32) - p);
75816
75817 DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);
75818
75819 return len;
75820}
75821
75823 duk_small_int_t lowest_mantissa;
75824
75825#if 1
75826 /* Assume IEEE round-to-even, so that shorter encoding can be used
75827 * when round-to-even would produce correct result. By removing
75828 * this check (and having low_ok == high_ok == 0) the results would
75829 * still be accurate but in some cases longer than necessary.
75830 */
75831 if (duk__bi_is_even(&nc_ctx->f)) {
75832 DUK_DDD(DUK_DDDPRINT("f is even"));
75833 nc_ctx->low_ok = 1;
75834 nc_ctx->high_ok = 1;
75835 } else {
75836 DUK_DDD(DUK_DDDPRINT("f is odd"));
75837 nc_ctx->low_ok = 0;
75838 nc_ctx->high_ok = 0;
75839 }
75840#else
75841 /* Note: not honoring round-to-even should work but now generates incorrect
75842 * results. For instance, 1e23 serializes to "a000...", i.e. the first digit
75843 * equals the radix (10). Scaling stops one step too early in this case.
75844 * Don't know why this is the case, but since this code path is unused, it
75845 * doesn't matter.
75846 */
75847 nc_ctx->low_ok = 0;
75848 nc_ctx->high_ok = 0;
75849#endif
75850
75851 /* For string-to-number, pretend we never have the lowest mantissa as there
75852 * is no natural "precision" for inputs. Having lowest_mantissa == 0, we'll
75853 * fall into the base cases for both e >= 0 and e < 0.
75854 */
75855 if (nc_ctx->is_s2n) {
75856 lowest_mantissa = 0;
75857 } else {
75858 lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
75859 }
75860
75861 nc_ctx->unequal_gaps = 0;
75862 if (nc_ctx->e >= 0) {
75863 /* exponent non-negative (and thus not minimum exponent) */
75864
75865 if (lowest_mantissa) {
75866 /* (>= e 0) AND (= f (expt b (- p 1)))
75867 *
75868 * be <- (expt b e) == b^e
75869 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
75870 * r <- (* f be1 2) == 2 * f * b^(e+1) [if b==2 -> f * b^(e+2)]
75871 * s <- (* b 2) [if b==2 -> 4]
75872 * m+ <- be1 == b^(e+1)
75873 * m- <- be == b^e
75874 * k <- 0
75875 * B <- B
75876 * low_ok <- round
75877 * high_ok <- round
75878 */
75879
75880 DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
75881 "lowest mantissa value for this exponent -> "
75882 "unequal gaps"));
75883
75884 duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
75885 duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, nc_ctx->b); /* mp <- b^(e+1) */
75886 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
75887 duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^(e+1) */
75888 duk__bi_set_small(&nc_ctx->s, nc_ctx->b * 2); /* s <- 2 * b */
75889 nc_ctx->unequal_gaps = 1;
75890 } else {
75891 /* (>= e 0) AND (not (= f (expt b (- p 1))))
75892 *
75893 * be <- (expt b e) == b^e
75894 * r <- (* f be 2) == 2 * f * b^e [if b==2 -> f * b^(e+1)]
75895 * s <- 2
75896 * m+ <- be == b^e
75897 * m- <- be == b^e
75898 * k <- 0
75899 * B <- B
75900 * low_ok <- round
75901 * high_ok <- round
75902 */
75903
75904 DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
75905 "not lowest mantissa for this exponent -> "
75906 "equal gaps"));
75907
75908 duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
75909 duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm); /* mp <- b^e */
75910 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
75911 duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^e */
75912 duk__bi_set_small(&nc_ctx->s, 2); /* s <- 2 */
75913 }
75914 } else {
75915 /* When doing string-to-number, lowest_mantissa is always 0 so
75916 * the exponent check, while incorrect, won't matter.
75917 */
75918 if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
75919 lowest_mantissa /* lowest mantissa for this exponent*/) {
75920 /* r <- (* f b 2) [if b==2 -> (* f 4)]
75921 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2 [if b==2 -> b^(2-e)]
75922 * m+ <- b == 2
75923 * m- <- 1
75924 * k <- 0
75925 * B <- B
75926 * low_ok <- round
75927 * high_ok <- round
75928 */
75929
75930 DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
75931 "lowest mantissa for this exponent -> "
75932 "unequal gaps"));
75933
75934 duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, nc_ctx->b * 2); /* r <- (2 * b) * f */
75935 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 */
75936 duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(1-e) * 2 */
75937 duk__bi_set_small(&nc_ctx->mp, 2);
75938 duk__bi_set_small(&nc_ctx->mm, 1);
75939 nc_ctx->unequal_gaps = 1;
75940 } else {
75941 /* r <- (* f 2)
75942 * s <- (* (expt b (- e)) 2) == b^(-e) * 2 [if b==2 -> b^(1-e)]
75943 * m+ <- 1
75944 * m- <- 1
75945 * k <- 0
75946 * B <- B
75947 * low_ok <- round
75948 * high_ok <- round
75949 */
75950
75951 DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
75952 "lowest mantissa for this exponent -> "
75953 "equal gaps"));
75954
75955 duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2); /* r <- 2 * f */
75956 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 */
75957 duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(-e) * 2 */
75958 duk__bi_set_small(&nc_ctx->mp, 1);
75959 duk__bi_set_small(&nc_ctx->mm, 1);
75960 }
75961 }
75962}
75963
75965 duk_small_int_t k = 0;
75966
75967 /* This is essentially the 'scale' algorithm, with recursion removed.
75968 * Note that 'k' is either correct immediately, or will move in one
75969 * direction in the loop. There's no need to do the low/high checks
75970 * on every round (like the Scheme algorithm does).
75971 *
75972 * The scheme algorithm finds 'k' and updates 's' simultaneously,
75973 * while the logical algorithm finds 'k' with 's' having its initial
75974 * value, after which 's' is updated separately (see the Burger-Dybvig
75975 * paper, Section 3.1, steps 2 and 3).
75976 *
75977 * The case where m+ == m- (almost always) is optimized for, because
75978 * it reduces the bigint operations considerably and almost always
75979 * applies. The scale loop only needs to work with m+, so this works.
75980 */
75981
75982 /* XXX: this algorithm could be optimized quite a lot by using e.g.
75983 * a logarithm based estimator for 'k' and performing B^n multiplication
75984 * using a lookup table or using some bit-representation based exp
75985 * algorithm. Currently we just loop, with significant performance
75986 * impact for very large and very small numbers.
75987 */
75988
75989 DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
75990 (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
75991 DUK__BI_PRINT("r(init)", &nc_ctx->r);
75992 DUK__BI_PRINT("s(init)", &nc_ctx->s);
75993 DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
75994 DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
75995
75996 for (;;) {
75997 DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
75998 DUK__BI_PRINT("r", &nc_ctx->r);
75999 DUK__BI_PRINT("s", &nc_ctx->s);
76000 DUK__BI_PRINT("m+", &nc_ctx->mp);
76001 DUK__BI_PRINT("m-", &nc_ctx->mm);
76002
76003 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
76004 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
76005 DUK_DDD(DUK_DDDPRINT("k is too low"));
76006 /* r <- r
76007 * s <- (* s B)
76008 * m+ <- m+
76009 * m- <- m-
76010 * k <- (+ k 1)
76011 */
76012
76013 duk__bi_mul_small_copy(&nc_ctx->s, nc_ctx->B, &nc_ctx->t1);
76014 k++;
76015 } else {
76016 break;
76017 }
76018 }
76019
76020 /* k > 0 -> k was too low, and cannot be too high */
76021 if (k > 0) {
76022 goto skip_dec_k;
76023 }
76024
76025 for (;;) {
76026 DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
76027 DUK__BI_PRINT("r", &nc_ctx->r);
76028 DUK__BI_PRINT("s", &nc_ctx->s);
76029 DUK__BI_PRINT("m+", &nc_ctx->mp);
76030 DUK__BI_PRINT("m-", &nc_ctx->mm);
76031
76032 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
76033 duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, nc_ctx->B); /* t2 = (* (+ r m+) B) */
76034 if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
76035 DUK_DDD(DUK_DDDPRINT("k is too high"));
76036 /* r <- (* r B)
76037 * s <- s
76038 * m+ <- (* m+ B)
76039 * m- <- (* m- B)
76040 * k <- (- k 1)
76041 */
76042 duk__bi_mul_small_copy(&nc_ctx->r, nc_ctx->B, &nc_ctx->t1);
76043 duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t1);
76044 if (nc_ctx->unequal_gaps) {
76045 DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
76046 duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t1);
76047 }
76048 k--;
76049 } else {
76050 break;
76051 }
76053
76054 skip_dec_k:
76055
76056 if (!nc_ctx->unequal_gaps) {
76057 DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
76058 duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp); /* mm <- mp */
76059 }
76060 nc_ctx->k = k;
76061
76062 DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
76063 DUK__BI_PRINT("r(final)", &nc_ctx->r);
76064 DUK__BI_PRINT("s(final)", &nc_ctx->s);
76065 DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
76066 DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
76067}
76068
76070 duk_small_int_t tc1, tc2; /* terminating conditions */
76071 duk_small_int_t d; /* current digit */
76072 duk_small_int_t count = 0; /* digit count */
76073
76074 /*
76075 * Digit generation loop.
76076 *
76077 * Different termination conditions:
76078 *
76079 * 1. Free format output. Terminate when shortest accurate
76080 * representation found.
76081 *
76082 * 2. Fixed format output, with specific number of digits.
76083 * Ignore termination conditions, terminate when digits
76084 * generated. Caller requests an extra digit and rounds.
76085 *
76086 * 3. Fixed format output, with a specific absolute cut-off
76087 * position (e.g. 10 digits after decimal point). Note
76088 * that we always generate at least one digit, even if
76089 * the digit is below the cut-off point already.
76090 */
76091
76092 for (;;) {
76093 DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
76094 (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
76095 (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
76096 DUK__BI_PRINT("r", &nc_ctx->r);
76097 DUK__BI_PRINT("s", &nc_ctx->s);
76098 DUK__BI_PRINT("m+", &nc_ctx->mp);
76099 DUK__BI_PRINT("m-", &nc_ctx->mm);
76100
76101 /* (quotient-remainder (* r B) s) using a dummy subtraction loop */
76102 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, nc_ctx->B); /* t1 <- (* r B) */
76103 d = 0;
76104 for (;;) {
76105 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
76106 break;
76107 }
76108 duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2); /* t1 <- t1 - s */
76109 d++;
76110 }
76111 duk__bi_copy(&nc_ctx->r, &nc_ctx->t1); /* r <- (remainder (* r B) s) */
76112 /* d <- (quotient (* r B) s) (in range 0...B-1) */
76113 DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
76114 DUK__BI_PRINT("r(rem)", &nc_ctx->r);
76115
76116 duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
76117 duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
76118 DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
76119 DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
76120
76121 /* Terminating conditions. For fixed width output, we just ignore the
76122 * terminating conditions (and pretend that tc1 == tc2 == false). The
76123 * the current shortcut for fixed-format output is to generate a few
76124 * extra digits and use rounding (with carry) to finish the output.
76125 */
76126
76127 if (nc_ctx->is_fixed == 0) {
76128 /* free-form */
76129 tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
76130
76131 duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 <- (+ r m+) */
76132 tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
76133
76134 DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
76135 } else {
76136 /* fixed-format */
76137 tc1 = 0;
76138 tc2 = 0;
76139 }
76140
76141 /* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
76142 * on purpose, which is taken into account by the macro.
76143 */
76144 count++;
76145
76146 if (tc1) {
76147 if (tc2) {
76148 /* tc1 = true, tc2 = true */
76149 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
76150 if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) { /* (< (* r 2) s) */
76151 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
76152 (long) d, (long) nc_ctx->k));
76153 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76154 } else {
76155 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
76156 (long) (d + 1), (long) nc_ctx->k));
76157 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
76158 }
76159 break;
76160 } else {
76161 /* tc1 = true, tc2 = false */
76162 DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
76163 (long) d, (long) nc_ctx->k));
76164 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76165 break;
76166 }
76167 } else {
76168 if (tc2) {
76169 /* tc1 = false, tc2 = true */
76170 DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
76171 (long) (d + 1), (long) nc_ctx->k));
76172 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
76173 break;
76174 } else {
76175 /* tc1 = false, tc2 = false */
76176 DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
76177 (long) d, (long) nc_ctx->k));
76178 DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76179
76180 /* r <- r (updated above: r <- (remainder (* r B) s)
76181 * s <- s
76182 * m+ <- m+ (updated above: m+ <- (* m+ B)
76183 * m- <- m- (updated above: m- <- (* m- B)
76184 * B, low_ok, high_ok are fixed
76185 */
76186
76187 /* fall through and continue for-loop */
76188 }
76189 }
76190
76191 /* fixed-format termination conditions */
76192 if (nc_ctx->is_fixed) {
76193 if (nc_ctx->abs_pos) {
76194 int pos = nc_ctx->k - count + 1; /* count is already incremented, take into account */
76195 DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
76196 (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
76197 if (pos <= nc_ctx->req_digits) {
76198 DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
76199 break;
76200 }
76201 } else {
76202 DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
76203 (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
76204 if (count >= nc_ctx->req_digits) {
76205 DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
76206 break;
76207 }
76208 }
76209 }
76210 } /* for */
76211
76212 nc_ctx->count = count;
76213
76214 DUK_DDD(DUK_DDDPRINT("generate finished"));
76215
76216#ifdef DUK_USE_DDDPRINT
76217 {
76218 duk_uint8_t buf[2048];
76219 duk_small_int_t i, t;
76220 DUK_MEMZERO(buf, sizeof(buf));
76221 for (i = 0; i < nc_ctx->count; i++) {
76222 t = nc_ctx->digits[i];
76223 if (t < 0 || t > 36) {
76224 buf[i] = (duk_uint8_t) '?';
76225 } else {
76226 buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
76228 }
76229 DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
76230 (long) nc_ctx->k, (const char *) buf));
76231 }
76232#endif
76233}
76234
76235/* Round up digits to a given position. If position is out-of-bounds,
76236 * does nothing. If carry propagates over the first digit, a '1' is
76237 * prepended to digits and 'k' will be updated. Return value indicates
76238 * whether carry propagated over the first digit.
76239 *
76240 * Note that nc_ctx->count is NOT updated based on the rounding position
76241 * (it is updated only if carry overflows over the first digit and an
76242 * extra digit is prepended).
76243 */
76246 duk_uint8_t *p;
76247 duk_uint8_t roundup_limit;
76248 duk_small_int_t ret = 0;
76249
76250 /*
76251 * round_idx points to the digit which is considered for rounding; the
76252 * digit to its left is the final digit of the rounded value. If round_idx
76253 * is zero, rounding will be performed; the result will either be an empty
76254 * rounded value or if carry happens a '1' digit is generated.
76255 */
76256
76257 if (round_idx >= nc_ctx->count) {
76258 DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
76259 (long) round_idx, (long) nc_ctx->count));
76260 return 0;
76261 } else if (round_idx < 0) {
76262 DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
76263 (long) round_idx));
76264 return 0;
76265 }
76266
76267 /*
76268 * Round-up limit.
76269 *
76270 * For even values, divides evenly, e.g. 10 -> roundup_limit=5.
76271 *
76272 * For odd values, rounds up, e.g. 3 -> roundup_limit=2.
76273 * If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
76274 */
76275 roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
76276
76277 p = &nc_ctx->digits[round_idx];
76278 if (*p >= roundup_limit) {
76279 DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
76280 /* carry */
76281 for (;;) {
76282 *p = 0;
76283 if (p == &nc_ctx->digits[0]) {
76284 DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
76285 DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
76286 (const void *) (&nc_ctx->digits[0]),
76287 (size_t) (sizeof(char) * nc_ctx->count));
76288 nc_ctx->digits[0] = 1; /* don't increase 'count' */
76289 nc_ctx->k++; /* position of highest digit changed */
76290 nc_ctx->count++; /* number of digits changed */
76291 ret = 1;
76292 break;
76293 }
76294
76295 DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
76296 (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
76297 p--;
76298 t = *p;
76299 DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
76300 if (++t < nc_ctx->B) {
76301 DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
76302 *p = (duk_uint8_t) t;
76303 break;
76304 }
76305
76306 DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
76307 }
76308 }
76309
76310 return ret;
76311}
76312
76313#define DUK__NO_EXP (65536) /* arbitrary marker, outside valid exp range */
76314
76316 duk_context *ctx,
76317 duk_small_int_t radix,
76318 duk_small_int_t digits,
76319 duk_small_uint_t flags,
76320 duk_small_int_t neg) {
76322 duk_small_int_t pos, pos_end;
76323 duk_small_int_t expt;
76324 duk_small_int_t dig;
76325 duk_uint8_t *q;
76326 duk_uint8_t *buf;
76327
76328 /*
76329 * The string conversion here incorporates all the necessary Ecmascript
76330 * semantics without attempting to be generic. nc_ctx->digits contains
76331 * nc_ctx->count digits (>= 1), with the topmost digit's 'position'
76332 * indicated by nc_ctx->k as follows:
76333 *
76334 * digits="123" count=3 k=0 --> 0.123
76335 * digits="123" count=3 k=1 --> 1.23
76336 * digits="123" count=3 k=5 --> 12300
76337 * digits="123" count=3 k=-1 --> 0.0123
76338 *
76339 * Note that the identifier names used for format selection are different
76340 * in Burger-Dybvig paper and Ecmascript specification (quite confusingly
76341 * so, because e.g. 'k' has a totally different meaning in each). See
76342 * documentation for discussion.
76343 *
76344 * Ecmascript doesn't specify any specific behavior for format selection
76345 * (e.g. when to use exponent notation) for non-base-10 numbers.
76346 *
76347 * The bigint space in the context is reused for string output, as there
76348 * is more than enough space for that (>1kB at the moment), and we avoid
76349 * allocating even more stack.
76350 */
76351
76353 DUK_ASSERT(nc_ctx->count >= 1);
76354
76355 k = nc_ctx->k;
76356 buf = (duk_uint8_t *) &nc_ctx->f; /* XXX: union would be more correct */
76357 q = buf;
76358
76359 /* Exponent handling: if exponent format is used, record exponent value and
76360 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
76361 *
76362 * toFixed() prevents exponent use; otherwise apply a set of criteria to
76363 * match the other API calls (toString(), toPrecision, etc).
76364 */
76365
76366 expt = DUK__NO_EXP;
76367 if (!nc_ctx->abs_pos /* toFixed() */) {
76368 if ((flags & DUK_N2S_FLAG_FORCE_EXP) || /* exponential notation forced */
76369 ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) && /* fixed precision and zero padding would be required */
76370 (k - digits >= 1)) || /* (e.g. k=3, digits=2 -> "12X") */
76371 ((k > 21 || k <= -6) && (radix == 10))) { /* toString() conditions */
76372 DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
76373 (long) k, (long) (k - 1)));
76374 expt = k - 1; /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
76375 k = 1; /* generate mantissa with a single leading whole number digit */
76376 }
76377 }
76378
76379 if (neg) {
76380 *q++ = '-';
76381 }
76382
76383 /* Start position (inclusive) and end position (exclusive) */
76384 pos = (k >= 1 ? k : 1);
76385 if (nc_ctx->is_fixed) {
76386 if (nc_ctx->abs_pos) {
76387 /* toFixed() */
76388 pos_end = -digits;
76389 } else {
76390 pos_end = k - digits;
76391 }
76392 } else {
76393 pos_end = k - nc_ctx->count;
76394 }
76395 if (pos_end > 0) {
76396 pos_end = 0;
76397 }
76398
76399 DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
76400 "digits=%ld, abs_pos=%ld",
76401 (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
76402 (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
76403
76404 /* Digit generation */
76405 while (pos > pos_end) {
76406 DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
76407 (long) pos, (long) pos_end));
76408 if (pos == 0) {
76409 *q++ = (duk_uint8_t) '.';
76410 }
76411 if (pos > k) {
76412 *q++ = (duk_uint8_t) '0';
76413 } else if (pos <= k - nc_ctx->count) {
76414 *q++ = (duk_uint8_t) '0';
76415 } else {
76416 dig = nc_ctx->digits[k - pos];
76417 DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
76418 *q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
76419 }
76420
76421 pos--;
76422 }
76423 DUK_ASSERT(pos <= 1);
76424
76425 /* Exponent */
76426 if (expt != DUK__NO_EXP) {
76427 /*
76428 * Exponent notation for non-base-10 numbers isn't specified in Ecmascript
76429 * specification, as it never explicitly turns up: non-decimal numbers can
76430 * only be formatted with Number.prototype.toString([radix]) and for that,
76431 * behavior is not explicitly specified.
76432 *
76433 * Logical choices include formatting the exponent as decimal (e.g. binary
76434 * 100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
76435 * The Dragon4 algorithm (in the original paper) prints the exponent value
76436 * in the target radix B. However, for radix values 15 and above, the
76437 * exponent separator 'e' is no longer easily parseable. Consider, for
76438 * instance, the number "1.faecee+1c".
76439 */
76440
76441 duk_size_t len;
76442 char expt_sign;
76443
76444 *q++ = 'e';
76445 if (expt >= 0) {
76446 expt_sign = '+';
76447 } else {
76448 expt_sign = '-';
76449 expt = -expt;
76450 }
76451 *q++ = (duk_uint8_t) expt_sign;
76452 len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
76453 q += len;
76454 }
76455
76456 duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
76457}
76458
76459/*
76460 * Conversion helpers
76461 */
76462
76465 duk_uint32_t tmp;
76466 duk_small_int_t expt;
76467
76468 /*
76469 * seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
76470 * A B C D E F G H
76471 *
76472 * s sign bit
76473 * eee... exponent field
76474 * fff... fraction
76475 *
76476 * ieee value = 1.ffff... * 2^(e - 1023) (normal)
76477 * = 0.ffff... * 2^(-1022) (denormal)
76478 *
76479 * algorithm v = f * b^e
76480 */
76481
76483
76484 nc_ctx->f.n = 2;
76485
76486 tmp = DUK_DBLUNION_GET_LOW32(&u);
76487 nc_ctx->f.v[0] = tmp;
76488 tmp = DUK_DBLUNION_GET_HIGH32(&u);
76489 nc_ctx->f.v[1] = tmp & 0x000fffffUL;
76490 expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
76492 if (expt == 0) {
76493 /* denormal */
76494 expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
76495 duk__bi_normalize(&nc_ctx->f);
76496 } else {
76497 /* normal: implicit leading 1-bit */
76498 nc_ctx->f.v[1] |= 0x00100000UL;
76499 expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
76500 DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f)); /* true, because v[1] has at least one bit set */
76501 }
76502
76503 DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
76504
76505 nc_ctx->e = expt;
76506}
76507
76510 duk_small_int_t expt;
76512 duk_small_int_t bitstart;
76513 duk_small_int_t bitround;
76514 duk_small_int_t bitidx;
76515 duk_small_int_t skip_round;
76516 duk_uint32_t t, v;
76517
76518 DUK_ASSERT(nc_ctx->count == 53 + 1);
76519
76520 /* Sometimes this assert is not true right now; it will be true after
76521 * rounding. See: test-bug-numconv-mantissa-assert.js.
76522 */
76523 DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1); /* zero handled by caller */
76524
76525 /* Should not be required because the code below always sets both high
76526 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
76527 * (perhaps because the low part is set (seemingly) conditionally in a
76528 * loop), so this is here to avoid the bogus warning.
76529 */
76530 DUK_MEMZERO((void *) &u, sizeof(u));
76531
76532 /*
76533 * Figure out how generated digits match up with the mantissa,
76534 * and then perform rounding. If mantissa overflows, need to
76535 * recompute the exponent (it is bumped and may overflow to
76536 * infinity).
76537 *
76538 * For normal numbers the leading '1' is hidden and ignored,
76539 * and the last bit is used for rounding:
76540 *
76541 * rounding pt
76542 * <--------52------->|
76543 * 1 x x x x ... x x x x|y ==> x x x x ... x x x x
76544 *
76545 * For denormals, the leading '1' is included in the number,
76546 * and the rounding point is different:
76547 *
76548 * rounding pt
76549 * <--52 or less--->|
76550 * 1 x x x x ... x x|x x y ==> 0 0 ... 1 x x ... x x
76551 *
76552 * The largest denormals will have a mantissa beginning with
76553 * a '1' (the explicit leading bit); smaller denormals will
76554 * have leading zero bits.
76555 *
76556 * If the exponent would become too high, the result becomes
76557 * Infinity. If the exponent is so small that the entire
76558 * mantissa becomes zero, the result becomes zero.
76559 *
76560 * Note: the Dragon4 'k' is off-by-one with respect to the IEEE
76561 * exponent. For instance, k==0 indicates that the leading '1'
76562 * digit is at the first binary fraction position (0.1xxx...);
76563 * the corresponding IEEE exponent would be -1.
76564 */
76565
76566 skip_round = 0;
76567
76568 recheck_exp:
76569
76570 expt = nc_ctx->k - 1; /* IEEE exp without bias */
76571 if (expt > 1023) {
76572 /* Infinity */
76573 bitstart = -255; /* needed for inf: causes mantissa to become zero,
76574 * and rounding to be skipped.
76575 */
76576 expt = 2047;
76577 } else if (expt >= -1022) {
76578 /* normal */
76579 bitstart = 1; /* skip leading digit */
76581 DUK_ASSERT(expt >= 1 && expt <= 2046);
76582 } else {
76583 /* denormal or zero */
76584 bitstart = 1023 + expt; /* expt==-1023 -> bitstart=0 (leading 1);
76585 * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
76586 */
76587 expt = 0;
76588 }
76589 bitround = bitstart + 52;
76590
76591 DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
76592 (long) expt, (long) bitstart, (long) bitround));
76593
76594 if (!skip_round) {
76595 if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
76596 /* Corner case: see test-numconv-parse-mant-carry.js. We could
76597 * just bump the exponent and update bitstart, but it's more robust
76598 * to recompute (but avoid rounding twice).
76599 */
76600 DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
76601 skip_round = 1;
76602 goto recheck_exp;
76603 }
76604 }
76605
76606 /*
76607 * Create mantissa
76608 */
76609
76610 t = 0;
76611 for (i = 0; i < 52; i++) {
76612 bitidx = bitstart + 52 - 1 - i;
76613 if (bitidx >= nc_ctx->count) {
76614 v = 0;
76615 } else if (bitidx < 0) {
76616 v = 0;
76617 } else {
76618 v = nc_ctx->digits[bitidx];
76619 }
76620 DUK_ASSERT(v == 0 || v == 1);
76621 t += v << (i % 32);
76622 if (i == 31) {
76623 /* low 32 bits is complete */
76625 t = 0;
76626 }
76627 }
76628 /* t has high mantissa */
76629
76630 DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
76631 (unsigned long) t,
76632 (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
76633
76634 DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
76635 t += expt << 20;
76636#if 0 /* caller handles sign change */
76637 if (negative) {
76638 t |= 0x80000000U;
76639 }
76640#endif
76642
76643 DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
76644 (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
76645 (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
76646
76647 *x = DUK_DBLUNION_GET_DOUBLE(&u);
76648}
76649
76650/*
76651 * Exposed number-to-string API
76652 *
76653 * Input: [ number ]
76654 * Output: [ string ]
76655 */
76656
76658 duk_double_t x;
76660 duk_small_int_t neg;
76661 duk_uint32_t uval;
76662 duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
76663 duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
76664
76665 x = (duk_double_t) duk_require_number(ctx, -1);
76666 duk_pop(ctx);
76667
76668 /*
76669 * Handle special cases (NaN, infinity, zero).
76670 */
76671
76673 if (DUK_SIGNBIT((double) x)) {
76674 x = -x;
76675 neg = 1;
76676 } else {
76677 neg = 0;
76678 }
76679
76680 /* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
76681 DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
76682
76683 if (c == DUK_FP_NAN) {
76685 return;
76686 } else if (c == DUK_FP_INFINITE) {
76687 if (neg) {
76688 /* -Infinity */
76690 } else {
76691 /* Infinity */
76693 }
76694 return;
76695 } else if (c == DUK_FP_ZERO) {
76696 /* We can't shortcut zero here if it goes through special formatting
76697 * (such as forced exponential notation).
76698 */
76699 ;
76700 }
76701
76702 /*
76703 * Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
76704 * specially, as they're very likely for embedded programs. This
76705 * is now done for all radix values. We must be careful not to use
76706 * the fast path when special formatting (e.g. forced exponential)
76707 * is in force.
76708 *
76709 * XXX: could save space by supporting radix 10 only and using
76710 * sprintf "%lu" for the fast path and for exponent formatting.
76711 */
76712
76713 uval = (unsigned int) x;
76714 if (((double) uval) == x && /* integer number in range */
76715 flags == 0) { /* no special formatting */
76716 /* use bigint area as a temp */
76717 duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
76718 duk_uint8_t *p = buf;
76719
76720 DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1); /* max size: radix=2 + sign */
76721 if (neg && uval != 0) {
76722 /* no negative sign for zero */
76723 *p++ = (duk_uint8_t) '-';
76724 }
76725 p += duk__dragon4_format_uint32(p, uval, radix);
76726 duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (p - buf));
76727 return;
76728 }
76729
76730 /*
76731 * Dragon4 setup.
76732 *
76733 * Convert double from IEEE representation for conversion;
76734 * normal finite values have an implicit leading 1-bit. The
76735 * slow path algorithm doesn't handle zero, so zero is special
76736 * cased here but still creates a valid nc_ctx, and goes
76737 * through normal formatting in case special formatting has
76738 * been requested (e.g. forced exponential format: 0 -> "0e+0").
76739 */
76740
76741 /* Would be nice to bulk clear the allocation, but the context
76742 * is 1-2 kilobytes and nothing should rely on it being zeroed.
76743 */
76744#if 0
76745 DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */
76746#endif
76747
76748 nc_ctx->is_s2n = 0;
76749 nc_ctx->b = 2;
76750 nc_ctx->B = radix;
76751 nc_ctx->abs_pos = 0;
76752 if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
76753 nc_ctx->is_fixed = 1;
76754 if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
76755 /* absolute req_digits; e.g. digits = 1 -> last digit is 0,
76756 * but add an extra digit for rounding.
76757 */
76758 nc_ctx->abs_pos = 1;
76759 nc_ctx->req_digits = (-digits + 1) - 1;
76760 } else {
76761 nc_ctx->req_digits = digits + 1;
76762 }
76763 } else {
76764 nc_ctx->is_fixed = 0;
76765 nc_ctx->req_digits = 0;
76766 }
76767
76768 if (c == DUK_FP_ZERO) {
76769 /* Zero special case: fake requested number of zero digits; ensure
76770 * no sign bit is printed. Relative and absolute fixed format
76771 * require separate handling.
76772 */
76773 duk_small_int_t count;
76774 if (nc_ctx->is_fixed) {
76775 if (nc_ctx->abs_pos) {
76776 count = digits + 2; /* lead zero + 'digits' fractions + 1 for rounding */
76777 } else {
76778 count = digits + 1; /* + 1 for rounding */
76779 }
76780 } else {
76781 count = 1;
76782 }
76783 DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
76784 DUK_ASSERT(count >= 1);
76785 DUK_MEMZERO((void *) nc_ctx->digits, count);
76786 nc_ctx->count = count;
76787 nc_ctx->k = 1; /* 0.000... */
76788 neg = 0;
76789 goto zero_skip;
76790 }
76791
76792 duk__dragon4_double_to_ctx(nc_ctx, x); /* -> sets 'f' and 'e' */
76793 DUK__BI_PRINT("f", &nc_ctx->f);
76794 DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
76795
76796 /*
76797 * Dragon4 slow path digit generation.
76798 */
76799
76800 duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
76801
76802 DUK_DDD(DUK_DDDPRINT("after prepare:"));
76803 DUK__BI_PRINT("r", &nc_ctx->r);
76804 DUK__BI_PRINT("s", &nc_ctx->s);
76805 DUK__BI_PRINT("mp", &nc_ctx->mp);
76806 DUK__BI_PRINT("mm", &nc_ctx->mm);
76807
76808 duk__dragon4_scale(nc_ctx);
76809
76810 DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
76811 DUK__BI_PRINT("r", &nc_ctx->r);
76812 DUK__BI_PRINT("s", &nc_ctx->s);
76813 DUK__BI_PRINT("mp", &nc_ctx->mp);
76814 DUK__BI_PRINT("mm", &nc_ctx->mm);
76815
76816 duk__dragon4_generate(nc_ctx);
76817
76818 /*
76819 * Convert and push final string.
76820 */
76821
76822 zero_skip:
76823
76824 if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
76825 /* Perform fixed-format rounding. */
76826 duk_small_int_t roundpos;
76827 if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
76828 /* 'roundpos' is relative to nc_ctx->k and increases to the right
76829 * (opposite of how 'k' changes).
76830 */
76831 roundpos = -digits; /* absolute position for digit considered for rounding */
76832 roundpos = nc_ctx->k - roundpos;
76833 } else {
76834 roundpos = digits;
76835 }
76836 DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
76837 (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
76838 (void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
76839
76840 /* Note: 'count' is currently not adjusted by rounding (i.e. the
76841 * digits are not "chopped off". That shouldn't matter because
76842 * the digit position (absolute or relative) is passed on to the
76843 * convert-and-push function.
76844 */
76845 }
76846
76847 duk__dragon4_convert_and_push(nc_ctx, ctx, radix, digits, flags, neg);
76848}
76849
76850/*
76851 * Exposed string-to-number API
76852 *
76853 * Input: [ string ]
76854 * Output: [ number ]
76855 *
76856 * If number parsing fails, a NaN is pushed as the result. If number parsing
76857 * fails due to an internal error, an InternalError is thrown.
76858 */
76859
76861 duk_hthread *thr = (duk_hthread *) ctx;
76862 duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
76863 duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
76864 duk_double_t res;
76865 duk_hstring *h_str;
76866 duk_small_int_t expt;
76867 duk_small_int_t expt_neg;
76868 duk_small_int_t expt_adj;
76869 duk_small_int_t neg;
76870 duk_small_int_t dig;
76871 duk_small_int_t dig_whole;
76872 duk_small_int_t dig_lzero;
76873 duk_small_int_t dig_frac;
76874 duk_small_int_t dig_expt;
76875 duk_small_int_t dig_prec;
76876 const duk__exp_limits *explim;
76877 const duk_uint8_t *p;
76878 duk_small_int_t ch;
76879
76880 /* This seems to waste a lot of stack frame entries, but good compilers
76881 * will compute these as needed below. Some of these initial flags are
76882 * also modified in the code below, so they can't all be removed.
76883 */
76884 duk_small_int_t trim_white = (flags & DUK_S2N_FLAG_TRIM_WHITE);
76885 duk_small_int_t allow_expt = (flags & DUK_S2N_FLAG_ALLOW_EXP);
76886 duk_small_int_t allow_garbage = (flags & DUK_S2N_FLAG_ALLOW_GARBAGE);
76887 duk_small_int_t allow_plus = (flags & DUK_S2N_FLAG_ALLOW_PLUS);
76888 duk_small_int_t allow_minus = (flags & DUK_S2N_FLAG_ALLOW_MINUS);
76889 duk_small_int_t allow_infinity = (flags & DUK_S2N_FLAG_ALLOW_INF);
76890 duk_small_int_t allow_frac = (flags & DUK_S2N_FLAG_ALLOW_FRAC);
76891 duk_small_int_t allow_naked_frac = (flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC);
76892 duk_small_int_t allow_empty_frac = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC);
76893 duk_small_int_t allow_empty = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
76894 duk_small_int_t allow_leading_zero = (flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO);
76895 duk_small_int_t allow_auto_hex_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT);
76896 duk_small_int_t allow_auto_oct_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT);
76897
76898 DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
76899 (duk_tval *) duk_get_tval(ctx, -1),
76900 (long) radix, (unsigned long) flags));
76901
76902 DUK_ASSERT(radix >= 2 && radix <= 36);
76904
76905 /*
76906 * Preliminaries: trim, sign, Infinity check
76907 *
76908 * We rely on the interned string having a NUL terminator, which will
76909 * cause a parse failure wherever it is encountered. As a result, we
76910 * don't need separate pointer checks.
76911 *
76912 * There is no special parsing for 'NaN' in the specification although
76913 * 'Infinity' (with an optional sign) is allowed in some contexts.
76914 * Some contexts allow plus/minus sign, while others only allow the
76915 * minus sign (like JSON.parse()).
76916 *
76917 * Automatic hex number detection (leading '0x' or '0X') and octal
76918 * number detection (leading '0' followed by at least one octal digit)
76919 * is done here too.
76920 */
76921
76922 if (trim_white) {
76923 /* Leading / trailing whitespace is sometimes accepted and
76924 * sometimes not. After white space trimming, all valid input
76925 * characters are pure ASCII.
76926 */
76927 duk_trim(ctx, -1);
76928 }
76929 h_str = duk_require_hstring(ctx, -1);
76930 DUK_ASSERT(h_str != NULL);
76931 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
76932
76933 neg = 0;
76934 ch = *p;
76935 if (ch == (duk_small_int_t) '+') {
76936 if (!allow_plus) {
76937 DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
76938 goto parse_fail;
76939 }
76940 p++;
76941 } else if (ch == (duk_small_int_t) '-') {
76942 if (!allow_minus) {
76943 DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
76944 goto parse_fail;
76945 }
76946 p++;
76947 neg = 1;
76948 }
76949
76950 ch = *p;
76951 if (allow_infinity && ch == (duk_small_int_t) 'I') {
76952 /* Don't check for Infinity unless the context allows it.
76953 * 'Infinity' is a valid integer literal in e.g. base-36:
76954 *
76955 * parseInt('Infinity', 36)
76956 * 1461559270678
76957 */
76958
76959 const duk_uint8_t *q;
76960
76961 /* borrow literal Infinity from builtin string */
76962 q = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(DUK_HTHREAD_STRING_INFINITY(thr));
76963 if (DUK_STRNCMP((const char *) p, (const char *) q, 8) == 0) {
76964 if (!allow_garbage && (p[8] != (duk_uint8_t) 0)) {
76965 DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
76966 goto parse_fail;
76967 } else {
76968 res = DUK_DOUBLE_INFINITY;
76969 goto negcheck_and_ret;
76970 }
76971 }
76972 }
76973 if (ch == (duk_small_int_t) '0') {
76974 duk_small_int_t detect_radix = 0;
76975 ch = p[1];
76976 if (allow_auto_hex_int && (ch == (duk_small_int_t) 'x' || ch == (duk_small_int_t) 'X')) {
76977 DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
76978 detect_radix = 16;
76979 allow_empty = 0; /* interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
76980 p += 2;
76981 } else if (allow_auto_oct_int && (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
76982 DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
76983 detect_radix = 8;
76984 allow_empty = 1; /* interpret e.g. '09' as '0', not NaN */
76985 p += 1;
76986 }
76987 if (detect_radix > 0) {
76988 radix = detect_radix;
76989 allow_expt = 0;
76990 allow_frac = 0;
76991 allow_naked_frac = 0;
76992 allow_empty_frac = 0;
76993 allow_leading_zero = 1; /* allow e.g. '0x0009' and '00077' */
76994 }
76995 }
76996
76997 /*
76998 * Scan number and setup for Dragon4.
76999 *
77000 * The fast path case is detected during setup: an integer which
77001 * can be converted without rounding, no net exponent. The fast
77002 * path could be implemented as a separate scan, but may not really
77003 * be worth it: the multiplications for building 'f' are not
77004 * expensive when 'f' is small.
77005 *
77006 * The significand ('f') must contain enough bits of (apparent)
77007 * accuracy, so that Dragon4 will generate enough binary output digits.
77008 * For decimal numbers, this means generating a 20-digit significand,
77009 * which should yield enough practical accuracy to parse IEEE doubles.
77010 * In fact, the Ecmascript specification explicitly allows an
77011 * implementation to treat digits beyond 20 as zeroes (and even
77012 * to round the 20th digit upwards). For non-decimal numbers, the
77013 * appropriate number of digits has been precomputed for comparable
77014 * accuracy.
77015 *
77016 * Digit counts:
77017 *
77018 * [ dig_lzero ]
77019 * |
77020 * .+-..---[ dig_prec ]----.
77021 * | || |
77022 * 0000123.456789012345678901234567890e+123456
77023 * | | | | | |
77024 * `--+--' `------[ dig_frac ]-------' `-+--'
77025 * | |
77026 * [ dig_whole ] [ dig_expt ]
77027 *
77028 * dig_frac and dig_expt are -1 if not present
77029 * dig_lzero is only computed for whole number part
77030 *
77031 * Parsing state
77032 *
77033 * Parsing whole part dig_frac < 0 AND dig_expt < 0
77034 * Parsing fraction part dig_frac >= 0 AND dig_expt < 0
77035 * Parsing exponent part dig_expt >= 0 (dig_frac may be < 0 or >= 0)
77036 *
77037 * Note: in case we hit an implementation limit (like exponent range),
77038 * we should throw an error, NOT return NaN or Infinity. Even with
77039 * very large exponent (or significand) values the final result may be
77040 * finite, so NaN/Infinity would be incorrect.
77041 */
77042
77043 duk__bi_set_small(&nc_ctx->f, 0);
77044 dig_prec = 0;
77045 dig_lzero = 0;
77046 dig_whole = 0;
77047 dig_frac = -1;
77048 dig_expt = -1;
77049 expt = 0;
77050 expt_adj = 0; /* essentially tracks digit position of lowest 'f' digit */
77051 expt_neg = 0;
77052 for (;;) {
77053 ch = *p++;
77054
77055 DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
77056 "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
77057 (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
77058 (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
77059 (long) dig_expt, (long) dig_lzero, (long) dig_prec));
77060 DUK__BI_PRINT("f", &nc_ctx->f);
77061
77062 /* Most common cases first. */
77063 if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
77064 dig = (int) ch - '0' + 0;
77065 } else if (ch == (duk_small_int_t) '.') {
77066 /* A leading digit is not required in some cases, e.g. accept ".123".
77067 * In other cases (JSON.parse()) a leading digit is required. This
77068 * is checked for after the loop.
77069 */
77070 if (dig_frac >= 0 || dig_expt >= 0) {
77071 if (allow_garbage) {
77072 DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
77073 break;
77074 } else {
77075 DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
77076 goto parse_fail;
77077 }
77078 }
77079
77080 if (!allow_frac) {
77081 /* Some contexts don't allow fractions at all; this can't be a
77082 * post-check because the state ('f' and expt) would be incorrect.
77083 */
77084 if (allow_garbage) {
77085 DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
77086 break;
77087 } else {
77088 DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
77089 }
77090 }
77091
77092 DUK_DDD(DUK_DDDPRINT("start fraction part"));
77093 dig_frac = 0;
77094 continue;
77095 } else if (ch == (duk_small_int_t) 0) {
77096 DUK_DDD(DUK_DDDPRINT("NUL termination"));
77097 break;
77098 } else if (allow_expt && dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
77099 /* Note: we don't parse back exponent notation for anything else
77100 * than radix 10, so this is not an ambiguous check (e.g. hex
77101 * exponent values may have 'e' either as a significand digit
77102 * or as an exponent separator).
77103 *
77104 * If the exponent separator occurs twice, 'e' will be interpreted
77105 * as a digit (= 14) and will be rejected as an invalid decimal
77106 * digit.
77107 */
77108
77109 DUK_DDD(DUK_DDDPRINT("start exponent part"));
77110
77111 /* Exponent without a sign or with a +/- sign is accepted
77112 * by all call sites (even JSON.parse()).
77113 */
77114 ch = *p;
77115 if (ch == (duk_small_int_t) '-') {
77116 expt_neg = 1;
77117 p++;
77118 } else if (ch == (duk_small_int_t) '+') {
77119 p++;
77120 }
77121 dig_expt = 0;
77122 continue;
77123 } else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
77124 dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
77125 } else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
77126 dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
77127 } else {
77128 dig = 255; /* triggers garbage digit check below */
77129 }
77130 DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
77131
77132 if (dig >= radix) {
77133 if (allow_garbage) {
77134 DUK_DDD(DUK_DDDPRINT("garbage termination"));
77135 break;
77136 } else {
77137 DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
77138 goto parse_fail;
77139 }
77140 }
77141
77142 if (dig_expt < 0) {
77143 /* whole or fraction digit */
77144
77145 if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
77146 /* significant from precision perspective */
77147
77148 duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
77149 if (f_zero && dig == 0) {
77150 /* Leading zero is not counted towards precision digits; not
77151 * in the integer part, nor in the fraction part.
77152 */
77153 if (dig_frac < 0) {
77154 dig_lzero++;
77155 }
77156 } else {
77157 /* XXX: join these ops (multiply-accumulate), but only if
77158 * code footprint decreases.
77159 */
77160 duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, radix);
77161 duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, dig);
77162 dig_prec++;
77163 }
77164 } else {
77165 /* Ignore digits beyond a radix-specific limit, but note them
77166 * in expt_adj.
77167 */
77168 expt_adj++;
77169 }
77170
77171 if (dig_frac >= 0) {
77172 dig_frac++;
77173 expt_adj--;
77174 } else {
77175 dig_whole++;
77176 }
77177 } else {
77178 /* exponent digit */
77179
77180 expt = expt * radix + dig;
77181 if (expt > DUK_S2N_MAX_EXPONENT) {
77182 /* impose a reasonable exponent limit, so that exp
77183 * doesn't need to get tracked using a bigint.
77184 */
77185 DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
77186 goto parse_explimit_error;
77187 }
77188 dig_expt++;
77189 }
77190 }
77191
77192 /* Leading zero. */
77193
77194 if (dig_lzero > 0 && dig_whole > 1) {
77195 if (!allow_leading_zero) {
77196 DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
77197 goto parse_fail;
77198 }
77199 }
77200
77201 /* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
77202
77203 if (dig_whole == 0) {
77204 if (dig_frac == 0) {
77205 /* "." is not accepted in any format */
77206 DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
77207 goto parse_fail;
77208 } else if (dig_frac > 0) {
77209 /* ".123" */
77210 if (!allow_naked_frac) {
77211 DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
77212 "leading integer digit(s)"));
77213 goto parse_fail;
77214 }
77215 } else {
77216 /* empty ("") is allowed in some formats (e.g. Number(''), as zero */
77217 if (!allow_empty) {
77218 DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
77219 goto parse_fail;
77220 }
77221 }
77222 } else {
77223 if (dig_frac == 0) {
77224 /* "123." is allowed in some formats */
77225 if (!allow_empty_frac) {
77226 DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
77227 goto parse_fail;
77228 }
77229 } else if (dig_frac > 0) {
77230 /* "123.456" */
77231 ;
77232 } else {
77233 /* "123" */
77234 ;
77235 }
77236 }
77237
77238 /* Exponent without digits (e.g. "1e" or "1e+"). If trailing garbage is
77239 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
77240 */
77241
77242 if (dig_expt == 0) {
77243 if (!allow_garbage) {
77244 DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
77245 goto parse_fail;
77246 }
77247 DUK_ASSERT(expt == 0);
77248 }
77249
77250 if (expt_neg) {
77251 expt = -expt;
77252 }
77253 DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
77254 (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
77255 expt += expt_adj;
77256
77257 /* Fast path check. */
77258
77259 if (nc_ctx->f.n <= 1 && /* 32-bit value */
77260 expt == 0 /* no net exponent */) {
77261 /* Fast path is triggered for no exponent and also for balanced exponent
77262 * and fraction parts, e.g. for "1.23e2" == "123". Remember to respect
77263 * zero sign.
77264 */
77265
77266 /* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
77267 DUK_DDD(DUK_DDDPRINT("fast path number parse"));
77268 if (nc_ctx->f.n == 1) {
77269 res = (double) nc_ctx->f.v[0];
77270 } else {
77271 res = 0.0;
77272 }
77273 goto negcheck_and_ret;
77274 }
77275
77276 /* Significand ('f') padding. */
77277
77278 while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
77279 /* Pad significand with "virtual" zero digits so that Dragon4 will
77280 * have enough (apparent) precision to work with.
77281 */
77282 DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
77283 duk__bi_mul_small_copy(&nc_ctx->f, radix, &nc_ctx->t1);
77284 DUK__BI_PRINT("f", &nc_ctx->f);
77285 expt--;
77286 dig_prec++;
77287 }
77288
77289 DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
77290
77291 /* Detect zero special case. */
77292
77293 if (nc_ctx->f.n == 0) {
77294 /* This may happen even after the fast path check, if exponent is
77295 * not balanced (e.g. "0e1"). Remember to respect zero sign.
77296 */
77297 DUK_DDD(DUK_DDDPRINT("significand is zero"));
77298 res = 0.0;
77299 goto negcheck_and_ret;
77300 }
77301
77302
77303 /* Quick reject of too large or too small exponents. This check
77304 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
77305 * so zero check must be above.
77306 */
77307
77308 explim = &duk__str2num_exp_limits[radix - 2];
77309 if (expt > explim->upper) {
77310 DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
77312 goto negcheck_and_ret;
77313 } else if (expt < explim->lower) {
77314 DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
77315 res = (duk_double_t) 0.0;
77316 goto negcheck_and_ret;
77317 }
77318
77319 nc_ctx->is_s2n = 1;
77320 nc_ctx->e = expt;
77321 nc_ctx->b = radix;
77322 nc_ctx->B = 2;
77323 nc_ctx->is_fixed = 1;
77324 nc_ctx->abs_pos = 0;
77325 nc_ctx->req_digits = 53 + 1;
77326
77327 DUK__BI_PRINT("f", &nc_ctx->f);
77328 DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
77329
77330 /*
77331 * Dragon4 slow path (binary) digit generation.
77332 * An extra digit is generated for rounding.
77333 */
77334
77335 duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
77336
77337 DUK_DDD(DUK_DDDPRINT("after prepare:"));
77338 DUK__BI_PRINT("r", &nc_ctx->r);
77339 DUK__BI_PRINT("s", &nc_ctx->s);
77340 DUK__BI_PRINT("mp", &nc_ctx->mp);
77341 DUK__BI_PRINT("mm", &nc_ctx->mm);
77342
77343 duk__dragon4_scale(nc_ctx);
77344
77345 DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
77346 DUK__BI_PRINT("r", &nc_ctx->r);
77347 DUK__BI_PRINT("s", &nc_ctx->s);
77348 DUK__BI_PRINT("mp", &nc_ctx->mp);
77349 DUK__BI_PRINT("mm", &nc_ctx->mm);
77350
77351 duk__dragon4_generate(nc_ctx);
77352
77353 DUK_ASSERT(nc_ctx->count == 53 + 1);
77354
77355 /*
77356 * Convert binary digits into an IEEE double. Need to handle
77357 * denormals and rounding correctly.
77358 */
77359
77360 duk__dragon4_ctx_to_double(nc_ctx, &res);
77361 goto negcheck_and_ret;
77362
77363 negcheck_and_ret:
77364 if (neg) {
77365 res = -res;
77366 }
77367 duk_pop(ctx);
77368 duk_push_number(ctx, (double) res);
77369 DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
77370 return;
77371
77372 parse_fail:
77373 DUK_DDD(DUK_DDDPRINT("parse failed"));
77374 duk_pop(ctx);
77375 duk_push_nan(ctx);
77376 return;
77377
77378 parse_explimit_error:
77379 DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
77380 DUK_ERROR_RANGE(thr, "exponent too large");
77381 return;
77382}
77383#line 1 "duk_regexp_compiler.c"
77384/*
77385 * Regexp compilation.
77386 *
77387 * See doc/regexp.rst for a discussion of the compilation approach and
77388 * current limitations.
77389 *
77390 * Regexp bytecode assumes jumps can be expressed with signed 32-bit
77391 * integers. Consequently the bytecode size must not exceed 0x7fffffffL.
77392 * The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
77393 * in many places. Although this could be changed, the bytecode format
77394 * limit would still prevent regexps exceeding the signed 32-bit limit
77395 * from working.
77396 *
77397 * XXX: The implementation does not prevent bytecode from exceeding the
77398 * maximum supported size. This could be done by limiting the maximum
77399 * input string size (assuming an upper bound can be computed for number
77400 * of bytecode bytes emitted per input byte) or checking buffer maximum
77401 * size when emitting bytecode (slower).
77402 */
77403
77404/* include removed: duk_internal.h */
77405
77406#ifdef DUK_USE_REGEXP_SUPPORT
77407
77408/*
77409 * Helper macros
77410 */
77411
77412#define DUK__RE_INITIAL_BUFSIZE 64
77413
77414#undef DUK__RE_BUFLEN
77415#define DUK__RE_BUFLEN(re_ctx) \
77416 DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
77417
77418/*
77419 * Disjunction struct: result of parsing a disjunction
77420 */
77421
77422typedef struct {
77423 /* Number of characters that the atom matches (e.g. 3 for 'abc'),
77424 * -1 if atom is complex and number of matched characters either
77425 * varies or is not known.
77426 */
77427 duk_int32_t charlen;
77428
77429#if 0
77430 /* These are not needed to implement quantifier capture handling,
77431 * but might be needed at some point.
77432 */
77433
77434 /* re_ctx->captures at start and end of atom parsing.
77435 * Since 'captures' indicates highest capture number emitted
77436 * so far in a DUK_REOP_SAVE, the captures numbers saved by
77437 * the atom are: ]start_captures,end_captures].
77438 */
77439 duk_uint32_t start_captures;
77440 duk_uint32_t end_captures;
77441#endif
77443
77444/*
77445 * Encoding helpers
77446 *
77447 * Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
77448 * even though the buffer operations will use duk_size_t.
77449 */
77450
77451/* XXX: the insert helpers should ensure that the bytecode result is not
77452 * larger than expected (or at least assert for it). Many things in the
77453 * bytecode, like skip offsets, won't work correctly if the bytecode is
77454 * larger than say 2G.
77455 */
77456
77457DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
77458 if (x < 0) {
77459 return ((duk_uint32_t) (-x)) * 2 + 1;
77460 } else {
77461 return ((duk_uint32_t) x) * 2;
77462 }
77463}
77464
77465/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
77466 * maximum size.
77467 */
77468DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
77470 duk_small_int_t len;
77471
77473 DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len);
77474 return (duk_uint32_t) len;
77475}
77476
77477DUK_LOCAL duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
77478 duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
77479 duk_small_int_t len;
77482 DUK_BW_WRITE_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, buf, len);
77483 return (duk_uint32_t) len;
77484}
77485
77486DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
77487 return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
77489
77490#if 0 /* unused */
77491DUK_LOCAL duk_uint32_t duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
77493}
77494#endif
77495
77496/* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
77497DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
77498 /* Call sites don't need the result length so it's not accumulated. */
77499 while (count > 0) {
77500 (void) duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
77501 count--;
77502 }
77503}
77504
77505DUK_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) {
77506 DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
77507}
77508
77509DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
77510 DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
77511}
77512
77513DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
77514 DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
77515}
77516
77517/*
77518 * Insert a jump offset at 'offset' to complete an instruction
77519 * (the jump offset is always the last component of an instruction).
77520 * The 'skip' argument must be computed relative to 'offset',
77521 * -without- taking into account the skip field being inserted.
77522 *
77523 * ... A B C ins X Y Z ... (ins may be a JUMP, SPLIT1/SPLIT2, etc)
77524 * => ... A B C ins SKIP X Y Z
77525 *
77526 * Computing the final (adjusted) skip value, which is relative to the
77527 * first byte of the next instruction, is a bit tricky because of the
77528 * variable length UTF-8 encoding. See doc/regexp.rst for discussion.
77529 */
77530DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
77531 duk_small_int_t len;
77532
77533 /* XXX: solve into closed form (smaller code) */
77534
77535 if (skip < 0) {
77536 /* two encoding attempts suffices */
77538 len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
77539 DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len); /* no change */
77540 skip -= (duk_int32_t) len;
77541 }
77542 return duk__insert_i32(re_ctx, offset, skip);
77543}
77544
77545DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
77546 return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
77547}
77548
77549/*
77550 * duk_re_range_callback for generating character class ranges.
77552 * When ignoreCase is false, the range is simply emitted as is.
77553 * We don't, for instance, eliminate duplicates or overlapping
77554 * ranges in a character class.
77555 *
77556 * When ignoreCase is true, the range needs to be normalized through
77557 * canonicalization. Unfortunately a canonicalized version of a
77558 * continuous range is not necessarily continuous (e.g. [x-{] is
77559 * continuous but [X-{] is not). The current algorithm creates the
77560 * canonicalized range(s) space efficiently at the cost of compile
77561 * time execution time (see doc/regexp.rst for discussion).
77562 *
77563 * Note that the ctx->nranges is a context-wide temporary value
77564 * (this is OK because there cannot be multiple character classes
77565 * being parsed simultaneously).
77566 */
77567
77568DUK_LOCAL void duk__generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
77569 duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
77570
77571 DUK_DD(DUK_DDPRINT("duk__generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
77572 (void *) re_ctx, (long) r1, (long) r2, (long) direct));
77573
77574 if (!direct && (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE)) {
77575 /*
77576 * Canonicalize a range, generating result ranges as necessary.
77577 * Needs to exhaustively scan the entire range (at most 65536
77578 * code points). If 'direct' is set, caller (lexer) has ensured
77579 * that the range is already canonicalization compatible (this
77580 * is used to avoid unnecessary canonicalization of built-in
77581 * ranges like \W, which are not affected by canonicalization).
77582 *
77583 * NOTE: here is one place where we don't want to support chars
77584 * outside the BMP, because the exhaustive search would be
77585 * massively larger.
77586 */
77587
77590 duk_codepoint_t r_start, r_end;
77591
77592 r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
77593 r_end = r_start;
77594 for (i = r1 + 1; i <= r2; i++) {
77595 t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
77596 if (t == r_end + 1) {
77597 r_end = t;
77598 } else {
77599 DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
77600 duk__append_u32(re_ctx, (duk_uint32_t) r_start);
77601 duk__append_u32(re_ctx, (duk_uint32_t) r_end);
77602 re_ctx->nranges++;
77603 r_start = t;
77604 r_end = t;
77605 }
77606 }
77607 DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
77608 duk__append_u32(re_ctx, (duk_uint32_t) r_start);
77609 duk__append_u32(re_ctx, (duk_uint32_t) r_end);
77610 re_ctx->nranges++;
77611 } else {
77612 DUK_DD(DUK_DDPRINT("direct, emit range: [%ld,%ld]", (long) r1, (long) r2));
77613 duk__append_u32(re_ctx, (duk_uint32_t) r1);
77614 duk__append_u32(re_ctx, (duk_uint32_t) r2);
77615 re_ctx->nranges++;
77616 }
77617}
77618
77619/*
77620 * Parse regexp Disjunction. Most of regexp compilation happens here.
77621 *
77622 * Handles Disjunction, Alternative, and Term productions directly without
77623 * recursion. The only constructs requiring recursion are positive/negative
77624 * lookaheads, capturing parentheses, and non-capturing parentheses.
77625 *
77626 * The function determines whether the entire disjunction is a 'simple atom'
77627 * (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
77628 * returns the atom character length which is needed by the caller to keep
77629 * track of its own atom character length. A disjunction with more than one
77630 * alternative is never considered a simple atom (although in some cases
77631 * that might be the case).
77632 *
77633 * Return value: simple atom character length or < 0 if not a simple atom.
77634 * Appends the bytecode for the disjunction matcher to the end of the temp
77635 * buffer.
77636 *
77637 * Regexp top level structure is:
77638 *
77639 * Disjunction = Term*
77640 * | Term* | Disjunction
77641 *
77642 * Term = Assertion
77643 * | Atom
77644 * | Atom Quantifier
77645 *
77646 * An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
77647 *
77648 * Notes:
77649 *
77650 * * Tracking of the 'simple-ness' of the current atom vs. the entire
77651 * disjunction are separate matters. For instance, the disjunction
77652 * may be complex, but individual atoms may be simple. Furthermore,
77653 * simple quantifiers are used whenever possible, even if the
77654 * disjunction as a whole is complex.
77655 *
77656 * * The estimate of whether an atom is simple is conservative now,
77657 * and it would be possible to expand it. For instance, captures
77658 * cause the disjunction to be marked complex, even though captures
77659 * -can- be handled by simple quantifiers with some minor modifications.
77660 *
77661 * * Disjunction 'tainting' as 'complex' is handled at the end of the
77662 * main for loop collectively for atoms. Assertions, quantifiers,
77663 * and '|' tokens need to taint the result manually if necessary.
77664 * Assertions cannot add to result char length, only atoms (and
77665 * quantifiers) can; currently quantifiers will taint the result
77666 * as complex though.
77667 */
77668
77670 duk_int32_t atom_start_offset = -1; /* negative -> no atom matched on previous round */
77671 duk_int32_t atom_char_length = 0; /* negative -> complex atom */
77672 duk_uint32_t atom_start_captures = re_ctx->captures; /* value of re_ctx->captures at start of atom */
77673 duk_int32_t unpatched_disjunction_split = -1;
77674 duk_int32_t unpatched_disjunction_jump = -1;
77675 duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
77676 duk_int32_t res_charlen = 0; /* -1 if disjunction is complex, char length if simple */
77677 duk__re_disjunction_info tmp_disj;
77678
77679 DUK_ASSERT(out_atom_info != NULL);
77680
77681 if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
77683 }
77684 re_ctx->recursion_depth++;
77685
77686#if 0
77687 out_atom_info->start_captures = re_ctx->captures;
77688#endif
77689
77690 for (;;) {
77691 /* atom_char_length, atom_start_offset, atom_start_offset reflect the
77692 * atom matched on the previous loop. If a quantifier is encountered
77693 * on this loop, these are needed to handle the quantifier correctly.
77694 * new_atom_char_length etc are for the atom parsed on this round;
77695 * they're written to atom_char_length etc at the end of the round.
77696 */
77697 duk_int32_t new_atom_char_length; /* char length of the atom parsed in this loop */
77698 duk_int32_t new_atom_start_offset; /* bytecode start offset of the atom parsed in this loop
77699 * (allows quantifiers to copy the atom bytecode)
77700 */
77701 duk_uint32_t new_atom_start_captures; /* re_ctx->captures at the start of the atom parsed in this loop */
77702
77703 duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
77704
77705 DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
77706 (long) re_ctx->curr_token.t,
77707 (long) re_ctx->curr_token.num,
77708 (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
77709 (int) re_ctx->curr_token.num : (int) '?'));
77710
77711 /* set by atom case clauses */
77712 new_atom_start_offset = -1;
77713 new_atom_char_length = -1;
77714 new_atom_start_captures = re_ctx->captures;
77715
77716 switch (re_ctx->curr_token.t) {
77717 case DUK_RETOK_DISJUNCTION: {
77718 /*
77719 * The handling here is a bit tricky. If a previous '|' has been processed,
77720 * we have a pending split1 and a pending jump (for a previous match). These
77721 * need to be back-patched carefully. See docs for a detailed example.
77722 */
77723
77724 /* patch pending jump and split */
77725 if (unpatched_disjunction_jump >= 0) {
77726 duk_uint32_t offset;
77727
77728 DUK_ASSERT(unpatched_disjunction_split >= 0);
77729 offset = unpatched_disjunction_jump;
77730 offset += duk__insert_jump_offset(re_ctx,
77731 offset,
77732 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
77733 /* offset is now target of the pending split (right after jump) */
77735 unpatched_disjunction_split,
77736 offset - unpatched_disjunction_split);
77737 }
77738
77739 /* add a new pending split to the beginning of the entire disjunction */
77740 (void) duk__insert_u32(re_ctx,
77741 entry_offset,
77742 DUK_REOP_SPLIT1); /* prefer direct execution */
77743 unpatched_disjunction_split = entry_offset + 1; /* +1 for opcode */
77744
77745 /* add a new pending match jump for latest finished alternative */
77747 unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77748
77749 /* 'taint' result as complex */
77750 res_charlen = -1;
77751 break;
77752 }
77753 case DUK_RETOK_QUANTIFIER: {
77754 if (atom_start_offset < 0) {
77756 }
77757 if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
77759 }
77760 if (atom_char_length >= 0) {
77761 /*
77762 * Simple atom
77763 *
77764 * If atom_char_length is zero, we'll have unbounded execution time for e.g.
77765 * /()*x/.exec('x'). We can't just skip the match because it might have some
77766 * side effects (for instance, if we allowed captures in simple atoms, the
77767 * capture needs to happen). The simple solution below is to force the
77768 * quantifier to match at most once, since the additional matches have no effect.
77769 *
77770 * With a simple atom there can be no capture groups, so no captures need
77771 * to be reset.
77772 */
77773 duk_int32_t atom_code_length;
77774 duk_uint32_t offset;
77775 duk_uint32_t qmin, qmax;
77776
77777 qmin = re_ctx->curr_token.qmin;
77778 qmax = re_ctx->curr_token.qmax;
77779 if (atom_char_length == 0) {
77780 /* qmin and qmax will be 0 or 1 */
77781 if (qmin > 1) {
77782 qmin = 1;
77783 }
77784 if (qmax > 1) {
77785 qmax = 1;
77786 }
77787 }
77788
77789 duk__append_u32(re_ctx, DUK_REOP_MATCH); /* complete 'sub atom' */
77790 atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - atom_start_offset);
77791
77792 offset = atom_start_offset;
77793 if (re_ctx->curr_token.greedy) {
77794 offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
77795 offset += duk__insert_u32(re_ctx, offset, qmin);
77796 offset += duk__insert_u32(re_ctx, offset, qmax);
77797 offset += duk__insert_u32(re_ctx, offset, atom_char_length);
77798 offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
77799 } else {
77800 offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
77801 offset += duk__insert_u32(re_ctx, offset, qmin);
77802 offset += duk__insert_u32(re_ctx, offset, qmax);
77803 offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
77804 }
77805 DUK_UNREF(offset); /* silence scan-build warning */
77806 } else {
77807 /*
77808 * Complex atom
77809 *
77810 * The original code is used as a template, and removed at the end
77811 * (this differs from the handling of simple quantifiers).
77812 *
77813 * NOTE: there is no current solution for empty atoms in complex
77814 * quantifiers. This would need some sort of a 'progress' instruction.
77815 *
77816 * XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
77817 */
77818 duk_int32_t atom_code_length;
77819 duk_uint32_t atom_copies;
77820 duk_uint32_t tmp_qmin, tmp_qmax;
77821
77822 /* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
77823 atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
77824 re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
77825 if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
77827 }
77828
77829 /* wipe the capture range made by the atom (if any) */
77830 DUK_ASSERT(atom_start_captures <= re_ctx->captures);
77831 if (atom_start_captures != re_ctx->captures) {
77832 DUK_ASSERT(atom_start_captures < re_ctx->captures);
77833 DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
77834 (long) atom_start_captures, (long) re_ctx->captures));
77835
77836 /* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
77837 duk__insert_u32(re_ctx, atom_start_offset, (re_ctx->captures - atom_start_captures) * 2);
77838 duk__insert_u32(re_ctx, atom_start_offset, (atom_start_captures + 1) * 2);
77839 duk__insert_u32(re_ctx, atom_start_offset, DUK_REOP_WIPERANGE);
77840 } else {
77841 DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
77842 (long) atom_start_captures));
77843 }
77844
77845 atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
77846
77847 /* insert the required matches (qmin) by copying the atom */
77848 tmp_qmin = re_ctx->curr_token.qmin;
77849 tmp_qmax = re_ctx->curr_token.qmax;
77850 while (tmp_qmin > 0) {
77851 duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
77852 tmp_qmin--;
77853 if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
77854 tmp_qmax--;
77855 }
77856 }
77857 DUK_ASSERT(tmp_qmin == 0);
77858
77859 /* insert code for matching the remainder - infinite or finite */
77860 if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
77861 /* reuse last emitted atom for remaining 'infinite' quantifier */
77862
77863 if (re_ctx->curr_token.qmin == 0) {
77864 /* Special case: original qmin was zero so there is nothing
77865 * to repeat. Emit an atom copy but jump over it here.
77866 */
77868 duk__append_jump_offset(re_ctx, atom_code_length);
77869 duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
77870 }
77871 if (re_ctx->curr_token.greedy) {
77872 duk__append_u32(re_ctx, DUK_REOP_SPLIT2); /* prefer jump */
77873 } else {
77874 duk__append_u32(re_ctx, DUK_REOP_SPLIT1); /* prefer direct */
77875 }
77876 duk__append_jump_offset(re_ctx, -atom_code_length - 1); /* -1 for opcode */
77877 } else {
77878 /*
77879 * The remaining matches are emitted as sequence of SPLITs and atom
77880 * copies; the SPLITs skip the remaining copies and match the sequel.
77881 * This sequence needs to be emitted starting from the last copy
77882 * because the SPLITs are variable length due to the variable length
77883 * skip offset. This causes a lot of memory copying now.
77884 *
77885 * Example structure (greedy, match maximum # atoms):
77886 *
77887 * SPLIT1 LSEQ
77888 * (atom)
77889 * SPLIT1 LSEQ ; <- the byte length of this instruction is needed
77890 * (atom) ; to encode the above SPLIT1 correctly
77891 * ...
77892 * LSEQ:
77893 */
77894 duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
77895 while (tmp_qmax > 0) {
77896 duk__insert_slice(re_ctx, offset, atom_start_offset, atom_code_length);
77897 if (re_ctx->curr_token.greedy) {
77898 duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1); /* prefer direct */
77899 } else {
77900 duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2); /* prefer jump */
77901 }
77903 offset + 1, /* +1 for opcode */
77904 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
77905 tmp_qmax--;
77906 }
77907 }
77908
77909 /* remove the original 'template' atom */
77910 duk__remove_slice(re_ctx, atom_start_offset, atom_code_length);
77911 }
77912
77913 /* 'taint' result as complex */
77914 res_charlen = -1;
77915 break;
77916 }
77919 break;
77920 }
77921 case DUK_RETOK_ASSERT_END: {
77923 break;
77924 }
77927 break;
77928 }
77931 break;
77932 }
77935 duk_uint32_t offset;
77936 duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
77938
77939 offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
77940 duk__parse_disjunction(re_ctx, 0, &tmp_disj);
77942
77943 (void) duk__insert_u32(re_ctx, offset, opcode);
77944 (void) duk__insert_jump_offset(re_ctx,
77945 offset + 1, /* +1 for opcode */
77946 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
77947
77948 /* 'taint' result as complex -- this is conservative,
77949 * as lookaheads do not backtrack.
77950 */
77951 res_charlen = -1;
77952 break;
77953 }
77954 case DUK_RETOK_ATOM_PERIOD: {
77955 new_atom_char_length = 1;
77956 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77958 break;
77959 }
77960 case DUK_RETOK_ATOM_CHAR: {
77961 /* Note: successive characters could be joined into string matches
77962 * but this is not trivial (consider e.g. '/xyz+/); see docs for
77963 * more discussion.
77964 */
77965 duk_uint32_t ch;
77966
77967 new_atom_char_length = 1;
77968 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77970 ch = re_ctx->curr_token.num;
77971 if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
77972 ch = duk_unicode_re_canonicalize_char(re_ctx->thr, ch);
77973 }
77974 duk__append_u32(re_ctx, ch);
77975 break;
77976 }
77979 new_atom_char_length = 1;
77980 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77981 duk__append_u32(re_ctx,
77982 (re_ctx->curr_token.t == DUK_RETOK_ATOM_DIGIT) ?
77984 duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)));
77985 duk__append_u16_list(re_ctx, duk_unicode_re_ranges_digit, sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
77986 break;
77987 }
77990 new_atom_char_length = 1;
77991 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77992 duk__append_u32(re_ctx,
77993 (re_ctx->curr_token.t == DUK_RETOK_ATOM_WHITE) ?
77995 duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)));
77996 duk__append_u16_list(re_ctx, duk_unicode_re_ranges_white, sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
77997 break;
77998 }
78001 new_atom_char_length = 1;
78002 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78003 duk__append_u32(re_ctx,
78006 duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t)));
78008 break;
78009 }
78011 duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
78012 if (backref > re_ctx->highest_backref) {
78013 re_ctx->highest_backref = backref;
78014 }
78015 new_atom_char_length = -1; /* mark as complex */
78016 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78018 duk__append_u32(re_ctx, backref);
78019 break;
78020 }
78022 duk_uint32_t cap;
78023
78024 new_atom_char_length = -1; /* mark as complex (capture handling) */
78025 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78026 cap = ++re_ctx->captures;
78028 duk__append_u32(re_ctx, cap * 2);
78029 duk__parse_disjunction(re_ctx, 0, &tmp_disj); /* retval (sub-atom char length) unused, tainted as complex above */
78031 duk__append_u32(re_ctx, cap * 2 + 1);
78032 break;
78033 }
78035 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78036 duk__parse_disjunction(re_ctx, 0, &tmp_disj);
78037 new_atom_char_length = tmp_disj.charlen;
78038 break;
78039 }
78042 /*
78043 * Range parsing is done with a special lexer function which calls
78044 * us for every range parsed. This is different from how rest of
78045 * the parsing works, but avoids a heavy, arbitrary size intermediate
78046 * value type to hold the ranges.
78047 *
78048 * Another complication is the handling of character ranges when
78049 * case insensitive matching is used (see docs for discussion).
78050 * The range handler callback given to the lexer takes care of this
78051 * as well.
78052 *
78053 * Note that duplicate ranges are not eliminated when parsing character
78054 * classes, so that canonicalization of
78055 *
78056 * [0-9a-fA-Fx-{]
78057 *
78058 * creates the result (note the duplicate ranges):
78059 *
78060 * [0-9A-FA-FX-Z{-{]
78061 *
78062 * where [x-{] is split as a result of canonicalization. The duplicate
78063 * ranges are not a semantics issue: they work correctly.
78064 */
78065
78066 duk_uint32_t offset;
78067
78068 DUK_DD(DUK_DDPRINT("character class"));
78069
78070 /* insert ranges instruction, range count patched in later */
78071 new_atom_char_length = 1;
78072 new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78073 duk__append_u32(re_ctx,
78076 offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); /* patch in range count later */
78077
78078 /* parse ranges until character class ends */
78079 re_ctx->nranges = 0; /* note: ctx-wide temporary */
78080 duk_lexer_parse_re_ranges(&re_ctx->lex, duk__generate_ranges, (void *) re_ctx);
78081
78082 /* insert range count */
78083 duk__insert_u32(re_ctx, offset, re_ctx->nranges);
78084 break;
78085 }
78087 if (expect_eof) {
78089 }
78090 goto done;
78091 }
78092 case DUK_RETOK_EOF: {
78093 if (!expect_eof) {
78095 }
78096 goto done;
78097 }
78098 default: {
78100 }
78101 }
78102
78103 /* a complex (new) atom taints the result */
78104 if (new_atom_start_offset >= 0) {
78105 if (new_atom_char_length < 0) {
78106 res_charlen = -1;
78107 } else if (res_charlen >= 0) {
78108 /* only advance if not tainted */
78109 res_charlen += new_atom_char_length;
78110 }
78111 }
78112
78113 /* record previous atom info in case next token is a quantifier */
78114 atom_start_offset = new_atom_start_offset;
78115 atom_char_length = new_atom_char_length;
78116 atom_start_captures = new_atom_start_captures;
78117 }
78118
78119 done:
78120
78121 /* finish up pending jump and split for last alternative */
78122 if (unpatched_disjunction_jump >= 0) {
78123 duk_uint32_t offset;
78124
78125 DUK_ASSERT(unpatched_disjunction_split >= 0);
78126 offset = unpatched_disjunction_jump;
78127 offset += duk__insert_jump_offset(re_ctx,
78128 offset,
78129 (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
78130 /* offset is now target of the pending split (right after jump) */
78132 unpatched_disjunction_split,
78133 offset - unpatched_disjunction_split);
78134 }
78135
78136#if 0
78137 out_atom_info->end_captures = re_ctx->captures;
78138#endif
78139 out_atom_info->charlen = res_charlen;
78140 DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
78141 (long) out_atom_info->charlen));
78142
78143 re_ctx->recursion_depth--;
78144}
78145
78146/*
78147 * Flags parsing (see E5 Section 15.10.4.1).
78148 */
78149
78151 const duk_uint8_t *p;
78152 const duk_uint8_t *p_end;
78153 duk_uint32_t flags = 0;
78154
78155 p = DUK_HSTRING_GET_DATA(h);
78156 p_end = p + DUK_HSTRING_GET_BYTELEN(h);
78157
78158 /* Note: can be safely scanned as bytes (undecoded) */
78159
78160 while (p < p_end) {
78161 duk_uint8_t c = *p++;
78162 switch ((int) c) {
78163 case (int) 'g': {
78164 if (flags & DUK_RE_FLAG_GLOBAL) {
78165 goto error;
78166 }
78167 flags |= DUK_RE_FLAG_GLOBAL;
78168 break;
78169 }
78170 case (int) 'i': {
78171 if (flags & DUK_RE_FLAG_IGNORE_CASE) {
78172 goto error;
78173 }
78174 flags |= DUK_RE_FLAG_IGNORE_CASE;
78175 break;
78176 }
78177 case (int) 'm': {
78178 if (flags & DUK_RE_FLAG_MULTILINE) {
78179 goto error;
78180 }
78181 flags |= DUK_RE_FLAG_MULTILINE;
78182 break;
78183 }
78184 default: {
78185 goto error;
78186 }
78187 }
78188 }
78189
78190 return flags;
78191
78192 error:
78194 return 0; /* never here */
78195}
78196
78197/*
78198 * Create escaped RegExp source (E5 Section 15.10.3).
78199 *
78200 * The current approach is to special case the empty RegExp
78201 * ('' -> '(?:)') and otherwise replace unescaped '/' characters
78202 * with '\/' regardless of where they occur in the regexp.
78203 *
78204 * Note that normalization does not seem to be necessary for
78205 * RegExp literals (e.g. '/foo/') because to be acceptable as
78206 * a RegExp literal, the text between forward slashes must
78207 * already match the escaping requirements (e.g. must not contain
78208 * unescaped forward slashes or be empty). Escaping IS needed
78209 * for expressions like 'new Regexp("...", "")' however.
78210 * Currently, we re-escape in either case.
78211 *
78212 * Also note that we process the source here in UTF-8 encoded
78213 * form. This is correct, because any non-ASCII characters are
78214 * passed through without change.
78215 */
78216
78217DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
78218 duk_context *ctx = (duk_context *) thr;
78219 duk_hstring *h;
78220 const duk_uint8_t *p;
78221 duk_bufwriter_ctx bw_alloc;
78223 duk_uint8_t *q;
78224 duk_size_t i, n;
78225 duk_uint_fast8_t c_prev, c;
78226
78227 h = duk_get_hstring(ctx, idx_pattern);
78228 DUK_ASSERT(h != NULL);
78229 p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
78231
78232 if (n == 0) {
78233 /* return '(?:)' */
78235 return;
78236 }
78237
78238 bw = &bw_alloc;
78239 DUK_BW_INIT_PUSHBUF(thr, bw, n);
78240 q = DUK_BW_GET_PTR(thr, bw);
78241
78242 c_prev = (duk_uint_fast8_t) 0;
78243
78244 for (i = 0; i < n; i++) {
78245 c = p[i];
78246
78247 q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
78248
78249 if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
78250 /* Unescaped '/' ANYWHERE in the regexp (in disjunction,
78251 * inside a character class, ...) => same escape works.
78252 */
78253 *q++ = DUK_ASC_BACKSLASH;
78254 }
78255 *q++ = (duk_uint8_t) c;
78256
78257 c_prev = c;
78258 }
78259
78260 DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
78261 duk_to_string(ctx, -1); /* -> [ ... escaped_source ] */
78263
78264/*
78265 * Exposed regexp compilation primitive.
78266 *
78267 * Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
78268 * actual parsing. Handles generation of the compiled regexp header and the
78269 * "boilerplate" capture of the matching substring (save 0 and 1). Also does some
78270 * global level regexp checks after recursive compilation has finished.
78271 *
78272 * An escaped version of the regexp source, suitable for use as a RegExp instance
78273 * 'source' property (see E5 Section 15.10.3), is also left on the stack.
78274 *
78275 * Input stack: [ pattern flags ]
78276 * Output stack: [ bytecode escaped_source ] (both as strings)
78277 */
78278
78280 duk_context *ctx = (duk_context *) thr;
78281 duk_re_compiler_ctx re_ctx;
78282 duk_lexer_point lex_point;
78283 duk_hstring *h_pattern;
78284 duk_hstring *h_flags;
78285 duk__re_disjunction_info ign_disj;
78286
78287 DUK_ASSERT(thr != NULL);
78288 DUK_ASSERT(ctx != NULL);
78289
78290 /*
78291 * Args validation
78292 */
78293
78294 /* TypeError if fails */
78295 h_pattern = duk_require_hstring(ctx, -2);
78296 h_flags = duk_require_hstring(ctx, -1);
78297
78298 /*
78299 * Create normalized 'source' property (E5 Section 15.10.3).
78300 */
78301
78302 /* [ ... pattern flags ] */
78303
78305
78306 /* [ ... pattern flags escaped_source ] */
78307
78308 /*
78309 * Init compilation context
78310 */
78311
78312 /* [ ... pattern flags escaped_source buffer ] */
78313
78314 DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
78315 DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */
78316 re_ctx.thr = thr;
78317 re_ctx.lex.thr = thr;
78318 re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
78319 re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
78322 re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
78323
78325
78326 DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
78327 (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
78328
78329 /*
78330 * Init lexer
78331 */
78332
78333 lex_point.offset = 0; /* expensive init, just want to fill window */
78334 lex_point.line = 1;
78335 DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
78336
78337 /*
78338 * Compilation
78339 */
78340
78341 DUK_DD(DUK_DDPRINT("starting regexp compilation"));
78342
78344 duk__append_u32(&re_ctx, 0);
78345 duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
78347 duk__append_u32(&re_ctx, 1);
78349
78350 /*
78351 * Check for invalid backreferences; note that it is NOT an error
78352 * to back-reference a capture group which has not yet been introduced
78353 * in the pattern (as in /\1(foo)/); in fact, the backreference will
78354 * always match! It IS an error to back-reference a capture group
78355 * which will never be introduced in the pattern. Thus, we can check
78356 * for such references only after parsing is complete.
78357 */
78358
78359 if (re_ctx.highest_backref > re_ctx.captures) {
78361 }
78362
78363 /*
78364 * Emit compiled regexp header: flags, ncaptures
78365 * (insertion order inverted on purpose)
78366 */
78367
78368 duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
78369 duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
78370
78371 /* [ ... pattern flags escaped_source buffer ] */
78372
78373 DUK_BW_COMPACT(thr, &re_ctx.bw);
78374 duk_to_string(ctx, -1); /* coerce to string */
78375
78376 /* [ ... pattern flags escaped_source bytecode ] */
78377
78378 /*
78379 * Finalize stack
78380 */
78381
78382 duk_remove(ctx, -4); /* -> [ ... flags escaped_source bytecode ] */
78383 duk_remove(ctx, -3); /* -> [ ... escaped_source bytecode ] */
78384
78385 DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
78386 (duk_tval *) duk_get_tval(ctx, -1), (duk_tval *) duk_get_tval(ctx, -2)));
78387}
78388
78389/*
78390 * Create a RegExp instance (E5 Section 15.10.7).
78391 *
78392 * Note: the output stack left by duk_regexp_compile() is directly compatible
78393 * with the input here.
78394 *
78395 * Input stack: [ escaped_source bytecode ] (both as strings)
78396 * Output stack: [ RegExp ]
78397 */
78398
78400 duk_context *ctx = (duk_context *) thr;
78401 duk_hobject *h;
78402 duk_hstring *h_bc;
78403 duk_small_int_t re_flags;
78404
78405 /* [ ... escape_source bytecode ] */
78406
78407 h_bc = duk_get_hstring(ctx, -1);
78408 DUK_ASSERT(h_bc != NULL);
78409 DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1); /* always at least the header */
78411 DUK_ASSERT((duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80); /* flags always encodes to 1 byte */
78412 re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
78413
78414 /* [ ... escaped_source bytecode ] */
78415
78416 duk_push_object(ctx);
78417 h = duk_get_hobject(ctx, -1);
78418 DUK_ASSERT(h != NULL);
78419 duk_insert(ctx, -3);
78420
78421 /* [ ... regexp_object escaped_source bytecode ] */
78422
78425
78427
78428 /* [ ... regexp_object escaped_source ] */
78429
78431
78432 /* [ ... regexp_object ] */
78433
78434 duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_GLOBAL));
78436
78437 duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
78439
78440 duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_MULTILINE));
78442
78443 duk_push_int(ctx, 0);
78445
78446 /* [ ... regexp_object ] */
78447}
78448
78449#undef DUK__RE_BUFLEN
78450
78451#else /* DUK_USE_REGEXP_SUPPORT */
78452
78453/* regexp support disabled */
78454
78455#endif /* DUK_USE_REGEXP_SUPPORT */
78456#line 1 "duk_regexp_executor.c"
78457/*
78458 * Regexp executor.
78459 *
78460 * Safety: the Ecmascript executor should prevent user from reading and
78461 * replacing regexp bytecode. Even so, the executor must validate all
78462 * memory accesses etc. When an invalid access is detected (e.g. a 'save'
78463 * opcode to invalid, unallocated index) it should fail with an internal
78464 * error but not cause a segmentation fault.
78465 *
78466 * Notes:
78468 * - Backtrack counts are limited to unsigned 32 bits but should
78469 * technically be duk_size_t for strings longer than 4G chars.
78470 * This also requires a regexp bytecode change.
78472
78473/* include removed: duk_internal.h */
78474
78475#ifdef DUK_USE_REGEXP_SUPPORT
78476
78477/*
78478 * Helpers for UTF-8 handling
78479 *
78480 * For bytecode readers the duk_uint32_t and duk_int32_t types are correct
78481 * because they're used for more than just codepoints.
78482 */
78484DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
78485 return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
78486}
78487
78488DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
78489 duk_uint32_t t;
78490
78491 /* signed integer encoding needed to work with UTF-8 */
78492 t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
78493 if (t & 1) {
78494 return -((duk_int32_t) (t >> 1));
78495 } else {
78496 return (duk_int32_t) (t >> 1);
78497 }
78498}
78499
78500DUK_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) {
78501 const duk_uint8_t *p;
78502
78503 /* Note: allow backtracking from p == ptr_end */
78504 p = *ptr;
78505 if (p < ptr_start || p > ptr_end) {
78506 goto fail;
78507 }
78508
78509 while (count > 0) {
78510 for (;;) {
78511 p--;
78512 if (p < ptr_start) {
78513 goto fail;
78514 }
78515 if ((*p & 0xc0) != 0x80) {
78516 /* utf-8 continuation bytes have the form 10xx xxxx */
78517 break;
78518 }
78519 }
78520 count--;
78521 }
78522 *ptr = p;
78523 return p;
78524
78525 fail:
78527 return NULL; /* never here */
78528}
78529
78530DUK_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) {
78531 const duk_uint8_t *p;
78532
78533 p = *ptr;
78534 if (p < ptr_start || p >= ptr_end) {
78535 goto fail;
78536 }
78537
78538 while (count > 0) {
78539 for (;;) {
78540 p++;
78541
78542 /* Note: if encoding ends by hitting end of input, we don't check that
78543 * the encoding is valid, we just assume it is.
78544 */
78545 if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
78546 /* utf-8 continuation bytes have the form 10xx xxxx */
78547 break;
78548 }
78549 }
78550 count--;
78551 }
78553 *ptr = p;
78554 return p;
78555
78556 fail:
78558 return NULL; /* never here */
78559}
78561/*
78562 * Helpers for dealing with the input string
78563 */
78564
78565/* Get a (possibly canonicalized) input character from current sp. The input
78566 * itself is never modified, and captures always record non-canonicalized
78567 * characters even in case-insensitive matching.
78568 */
78569DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
78571 if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
78572 res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
78573 }
78574 return res;
78575}
78576
78577DUK_LOCAL const duk_uint8_t *duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count) {
78578 return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
78579}
78580
78581/* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
78583 /* note: caller 'sp' is intentionally not updated here */
78584 (void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
78585 return duk__inp_get_cp(re_ctx, &sp);
78586}
78587
78588/*
78589 * Regexp recursive matching function.
78590 *
78591 * Returns 'sp' on successful match (points to character after last matched one),
78592 * NULL otherwise.
78593 *
78594 * The C recursion depth limit check is only performed in this function, this
78595 * suffices because the function is present in all true recursion required by
78596 * regexp execution.
78597 */
78598
78599DUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) {
78600 if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
78602 }
78603 re_ctx->recursion_depth++;
78604
78605 for (;;) {
78606 duk_small_int_t op;
78607
78608 if (re_ctx->steps_count >= re_ctx->steps_limit) {
78610 }
78611 re_ctx->steps_count++;
78612
78613 op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
78614
78615 DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
78616 (long) re_ctx->recursion_depth,
78617 (long) re_ctx->steps_count,
78618 (long) (pc - re_ctx->bytecode),
78619 (long) (sp - re_ctx->input),
78620 (long) op));
78621
78622 switch (op) {
78623 case DUK_REOP_MATCH: {
78624 goto match;
78625 }
78626 case DUK_REOP_CHAR: {
78627 /*
78628 * Byte-based matching would be possible for case-sensitive
78629 * matching but not for case-insensitive matching. So, we
78630 * match by decoding the input and bytecode character normally.
78631 *
78632 * Bytecode characters are assumed to be already canonicalized.
78633 * Input characters are canonicalized automatically by
78634 * duk__inp_get_cp() if necessary.
78635 *
78636 * There is no opcode for matching multiple characters. The
78637 * regexp compiler has trouble joining strings efficiently
78638 * during compilation. See doc/regexp.rst for more discussion.
78639 */
78640 duk_codepoint_t c1, c2;
78641
78642 c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78644 c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1)); /* canonicalized by compiler */
78645 if (sp >= re_ctx->input_end) {
78646 goto fail;
78647 }
78648 c2 = duk__inp_get_cp(re_ctx, &sp);
78649 DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
78650 if (c1 != c2) {
78651 goto fail;
78652 }
78653 break;
78654 }
78655 case DUK_REOP_PERIOD: {
78657
78658 if (sp >= re_ctx->input_end) {
78659 goto fail;
78660 }
78661 c = duk__inp_get_cp(re_ctx, &sp);
78663 /* E5 Sections 15.10.2.8, 7.3 */
78664 goto fail;
78665 }
78666 break;
78667 }
78668 case DUK_REOP_RANGES:
78669 case DUK_REOP_INVRANGES: {
78670 duk_uint32_t n;
78673
78674 n = duk__bc_get_u32(re_ctx, &pc);
78675 if (sp >= re_ctx->input_end) {
78676 goto fail;
78677 }
78678 c = duk__inp_get_cp(re_ctx, &sp);
78679
78680 match = 0;
78681 while (n) {
78682 duk_codepoint_t r1, r2;
78683 r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78684 r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78685 DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
78686 (long) n, (long) r1, (long) r2, (long) c));
78687 if (c >= r1 && c <= r2) {
78688 /* Note: don't bail out early, we must read all the ranges from
78689 * bytecode. Another option is to skip them efficiently after
78690 * breaking out of here. Prefer smallest code.
78691 */
78692 match = 1;
78693 }
78694 n--;
78695 }
78696
78697 if (op == DUK_REOP_RANGES) {
78698 if (!match) {
78699 goto fail;
78700 }
78701 } else {
78703 if (match) {
78704 goto fail;
78705 }
78706 }
78707 break;
78708 }
78709 case DUK_REOP_ASSERT_START: {
78711
78712 if (sp <= re_ctx->input) {
78713 break;
78714 }
78715 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
78716 goto fail;
78717 }
78718 c = duk__inp_get_prev_cp(re_ctx, sp);
78720 /* E5 Sections 15.10.2.8, 7.3 */
78721 break;
78722 }
78723 goto fail;
78724 }
78725 case DUK_REOP_ASSERT_END: {
78727 const duk_uint8_t *tmp_sp;
78728
78729 if (sp >= re_ctx->input_end) {
78730 break;
78731 }
78732 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
78733 goto fail;
78734 }
78735 tmp_sp = sp;
78736 c = duk__inp_get_cp(re_ctx, &tmp_sp);
78738 /* E5 Sections 15.10.2.8, 7.3 */
78739 break;
78740 }
78741 goto fail;
78742 }
78745 /*
78746 * E5 Section 15.10.2.6. The previous and current character
78747 * should -not- be canonicalized as they are now. However,
78748 * canonicalization does not affect the result of IsWordChar()
78749 * (which depends on Unicode characters never canonicalizing
78750 * into ASCII characters) so this does not matter.
78751 */
78752 duk_small_int_t w1, w2;
78753
78754 if (sp <= re_ctx->input) {
78755 w1 = 0; /* not a wordchar */
78756 } else {
78758 c = duk__inp_get_prev_cp(re_ctx, sp);
78760 }
78761 if (sp >= re_ctx->input_end) {
78762 w2 = 0; /* not a wordchar */
78763 } else {
78764 const duk_uint8_t *tmp_sp = sp; /* dummy so sp won't get updated */
78766 c = duk__inp_get_cp(re_ctx, &tmp_sp);
78768 }
78769
78771 if (w1 == w2) {
78772 goto fail;
78773 }
78774 } else {
78776 if (w1 != w2) {
78777 goto fail;
78778 }
78779 }
78780 break;
78781 }
78782 case DUK_REOP_JUMP: {
78783 duk_int32_t skip;
78784
78785 skip = duk__bc_get_i32(re_ctx, &pc);
78786 pc += skip;
78787 break;
78788 }
78789 case DUK_REOP_SPLIT1: {
78790 /* split1: prefer direct execution (no jump) */
78791 const duk_uint8_t *sub_sp;
78792 duk_int32_t skip;
78793
78794 skip = duk__bc_get_i32(re_ctx, &pc);
78795 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78796 if (sub_sp) {
78797 sp = sub_sp;
78798 goto match;
78799 }
78800 pc += skip;
78801 break;
78802 }
78803 case DUK_REOP_SPLIT2: {
78804 /* split2: prefer jump execution (not direct) */
78805 const duk_uint8_t *sub_sp;
78806 duk_int32_t skip;
78807
78808 skip = duk__bc_get_i32(re_ctx, &pc);
78809 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78810 if (sub_sp) {
78811 sp = sub_sp;
78812 goto match;
78813 }
78814 break;
78815 }
78816 case DUK_REOP_SQMINIMAL: {
78817 duk_uint32_t q, qmin, qmax;
78818 duk_int32_t skip;
78819 const duk_uint8_t *sub_sp;
78820
78821 qmin = duk__bc_get_u32(re_ctx, &pc);
78822 qmax = duk__bc_get_u32(re_ctx, &pc);
78823 skip = duk__bc_get_i32(re_ctx, &pc);
78824 DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
78825 (unsigned long) qmin, (unsigned long) qmax, (long) skip));
78826
78827 q = 0;
78828 while (q <= qmax) {
78829 if (q >= qmin) {
78830 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78831 if (sub_sp) {
78832 sp = sub_sp;
78833 goto match;
78834 }
78835 }
78836 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78837 if (!sub_sp) {
78838 break;
78839 }
78840 sp = sub_sp;
78841 q++;
78842 }
78843 goto fail;
78844 }
78845 case DUK_REOP_SQGREEDY: {
78846 duk_uint32_t q, qmin, qmax, atomlen;
78847 duk_int32_t skip;
78848 const duk_uint8_t *sub_sp;
78849
78850 qmin = duk__bc_get_u32(re_ctx, &pc);
78851 qmax = duk__bc_get_u32(re_ctx, &pc);
78852 atomlen = duk__bc_get_u32(re_ctx, &pc);
78853 skip = duk__bc_get_i32(re_ctx, &pc);
78854 DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
78855 (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
78856
78857 q = 0;
78858 while (q < qmax) {
78859 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78860 if (!sub_sp) {
78861 break;
78862 }
78863 sp = sub_sp;
78864 q++;
78865 }
78866 while (q >= qmin) {
78867 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78868 if (sub_sp) {
78869 sp = sub_sp;
78870 goto match;
78871 }
78872 if (q == qmin) {
78873 break;
78874 }
78875
78876 /* Note: if atom were to contain e.g. captures, we would need to
78877 * re-match the atom to get correct captures. Simply quantifiers
78878 * do not allow captures in their atom now, so this is not an issue.
78879 */
78880
78881 DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
78882 (long) atomlen));
78883 sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
78884 q--;
78885 }
78886 goto fail;
78887 }
78888 case DUK_REOP_SAVE: {
78889 duk_uint32_t idx;
78890 const duk_uint8_t *old;
78891 const duk_uint8_t *sub_sp;
78892
78893 idx = duk__bc_get_u32(re_ctx, &pc);
78894 if (idx >= re_ctx->nsaved) {
78895 /* idx is unsigned, < 0 check is not necessary */
78896 DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
78897 goto internal_error;
78898 }
78899 old = re_ctx->saved[idx];
78900 re_ctx->saved[idx] = sp;
78901 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78902 if (sub_sp) {
78903 sp = sub_sp;
78904 goto match;
78905 }
78906 re_ctx->saved[idx] = old;
78907 goto fail;
78908 }
78909 case DUK_REOP_WIPERANGE: {
78910 /* Wipe capture range and save old values for backtracking.
78911 *
78912 * XXX: this typically happens with a relatively small idx_count.
78913 * It might be useful to handle cases where the count is small
78914 * (say <= 8) by saving the values in stack instead. This would
78915 * reduce memory churn and improve performance, at the cost of a
78916 * slightly higher code footprint.
78917 */
78918 duk_uint32_t idx_start, idx_count;
78919#ifdef DUK_USE_EXPLICIT_NULL_INIT
78920 duk_uint32_t idx_end, idx;
78921#endif
78922 duk_uint8_t **range_save;
78923 const duk_uint8_t *sub_sp;
78924
78925 idx_start = duk__bc_get_u32(re_ctx, &pc);
78926 idx_count = duk__bc_get_u32(re_ctx, &pc);
78927 DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
78928 (long) idx_start, (long) idx_count,
78929 (long) idx_start, (long) (idx_start + idx_count - 1),
78930 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
78931 if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
78932 /* idx is unsigned, < 0 check is not necessary */
78933 DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
78934 (long) idx_start, (long) idx_count));
78935 goto internal_error;
78936 }
78937 DUK_ASSERT(idx_count > 0);
78938
78939 duk_require_stack((duk_context *) re_ctx->thr, 1);
78940 range_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
78941 sizeof(duk_uint8_t *) * idx_count);
78942 DUK_ASSERT(range_save != NULL);
78943 DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
78944#ifdef DUK_USE_EXPLICIT_NULL_INIT
78945 idx_end = idx_start + idx_count;
78946 for (idx = idx_start; idx < idx_end; idx++) {
78947 re_ctx->saved[idx] = NULL;
78948 }
78949#else
78950 DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
78951#endif
78952
78953 sub_sp = duk__match_regexp(re_ctx, pc, sp);
78954 if (sub_sp) {
78955 /* match: keep wiped/resaved values */
78956 DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
78957 (long) idx_start, (long) (idx_start + idx_count - 1),
78958 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
78959 duk_pop((duk_context *) re_ctx->thr);
78960 sp = sub_sp;
78961 goto match;
78962 }
78963
78964 /* fail: restore saves */
78965 DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
78966 (long) idx_start, (long) (idx_start + idx_count - 1),
78967 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
78968 DUK_MEMCPY((void *) (re_ctx->saved + idx_start),
78969 (const void *) range_save,
78970 sizeof(duk_uint8_t *) * idx_count);
78971 duk_pop((duk_context *) re_ctx->thr);
78972 goto fail;
78973 }
78974 case DUK_REOP_LOOKPOS:
78975 case DUK_REOP_LOOKNEG: {
78976 /*
78977 * Needs a save of multiple saved[] entries depending on what range
78978 * may be overwritten. Because the regexp parser does no such analysis,
78979 * we currently save the entire saved array here. Lookaheads are thus
78980 * a bit expensive. Note that the saved array is not needed for just
78981 * the lookahead sub-match, but for the matching of the entire sequel.
78982 *
78983 * The temporary save buffer is pushed on to the valstack to handle
78984 * errors correctly. Each lookahead causes a C recursion and pushes
78985 * more stuff on the value stack. If the C recursion limit is less
78986 * than the value stack spare, there is no need to check the stack.
78987 * We do so regardless, just in case.
78988 */
78989
78990 duk_int32_t skip;
78991 duk_uint8_t **full_save;
78992 const duk_uint8_t *sub_sp;
78993
78994 DUK_ASSERT(re_ctx->nsaved > 0);
78995
78996 duk_require_stack((duk_context *) re_ctx->thr, 1);
78997 full_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
78998 sizeof(duk_uint8_t *) * re_ctx->nsaved);
78999 DUK_ASSERT(full_save != NULL);
79000 DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
79001
79002 skip = duk__bc_get_i32(re_ctx, &pc);
79003 sub_sp = duk__match_regexp(re_ctx, pc, sp);
79004 if (op == DUK_REOP_LOOKPOS) {
79005 if (!sub_sp) {
79006 goto lookahead_fail;
79007 }
79008 } else {
79009 if (sub_sp) {
79010 goto lookahead_fail;
79011 }
79012 }
79013 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
79014 if (sub_sp) {
79015 /* match: keep saves */
79016 duk_pop((duk_context *) re_ctx->thr);
79017 sp = sub_sp;
79018 goto match;
79019 }
79020
79021 /* fall through */
79022
79023 lookahead_fail:
79024 /* fail: restore saves */
79025 DUK_MEMCPY((void *) re_ctx->saved,
79026 (const void *) full_save,
79027 sizeof(duk_uint8_t *) * re_ctx->nsaved);
79028 duk_pop((duk_context *) re_ctx->thr);
79029 goto fail;
79030 }
79032 /*
79033 * Byte matching for back-references would be OK in case-
79034 * sensitive matching. In case-insensitive matching we need
79035 * to canonicalize characters, so back-reference matching needs
79036 * to be done with codepoints instead. So, we just decode
79037 * everything normally here, too.
79038 *
79039 * Note: back-reference index which is 0 or higher than
79040 * NCapturingParens (= number of capturing parens in the
79041 * -entire- regexp) is a compile time error. However, a
79042 * backreference referring to a valid capture which has
79043 * not matched anything always succeeds! See E5 Section
79044 * 15.10.2.9, step 5, sub-step 3.
79045 */
79046 duk_uint32_t idx;
79047 const duk_uint8_t *p;
79048
79049 idx = duk__bc_get_u32(re_ctx, &pc);
79050 idx = idx << 1; /* backref n -> saved indices [n*2, n*2+1] */
79051 if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
79052 /* regexp compiler should catch these */
79053 DUK_D(DUK_DPRINT("internal error, backreference index insane"));
79054 goto internal_error;
79055 }
79056 if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
79057 /* capture is 'undefined', always matches! */
79058 DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
79059 (long) idx, (long) (idx + 1)));
79060 break;
79061 }
79062 DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
79063
79064 p = re_ctx->saved[idx];
79065 while (p < re_ctx->saved[idx+1]) {
79066 duk_codepoint_t c1, c2;
79067
79068 /* Note: not necessary to check p against re_ctx->input_end:
79069 * the memory access is checked by duk__inp_get_cp(), while
79070 * valid compiled regexps cannot write a saved[] entry
79071 * which points to outside the string.
79072 */
79073 if (sp >= re_ctx->input_end) {
79074 goto fail;
79075 }
79076 c1 = duk__inp_get_cp(re_ctx, &p);
79077 c2 = duk__inp_get_cp(re_ctx, &sp);
79078 if (c1 != c2) {
79079 goto fail;
79080 }
79081 }
79082 break;
79083 }
79084 default: {
79085 DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
79086 goto internal_error;
79087 }
79088 }
79089 }
79090
79091 match:
79092 re_ctx->recursion_depth--;
79093 return sp;
79094
79095 fail:
79096 re_ctx->recursion_depth--;
79097 return NULL;
79098
79099 internal_error:
79101 return NULL; /* never here */
79102}
79103
79104/*
79105 * Exposed matcher function which provides the semantics of RegExp.prototype.exec().
79106 *
79107 * RegExp.prototype.test() has the same semantics as exec() but does not return the
79108 * result object (which contains the matching string and capture groups). Currently
79109 * there is no separate test() helper, so a temporary result object is created and
79110 * discarded if test() is needed. This is intentional, to save code space.
79111 *
79112 * Input stack: [ ... re_obj input ]
79113 * Output stack: [ ... result ]
79114 */
79115
79117 duk_context *ctx = (duk_context *) thr;
79118 duk_re_matcher_ctx re_ctx;
79119 duk_hobject *h_regexp;
79120 duk_hstring *h_bytecode;
79121 duk_hstring *h_input;
79122 duk_uint8_t *p_buf;
79123 const duk_uint8_t *pc;
79124 const duk_uint8_t *sp;
79126 duk_small_int_t global;
79128 double d;
79129 duk_uint32_t char_offset;
79130
79131 DUK_ASSERT(thr != NULL);
79132 DUK_ASSERT(ctx != NULL);
79133
79134 DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
79135 (duk_tval *) duk_get_tval(ctx, -2),
79136 (duk_tval *) duk_get_tval(ctx, -1)));
79137
79138 /*
79139 * Regexp instance check, bytecode check, input coercion.
79140 *
79141 * See E5 Section 15.10.6.
79142 */
79143
79144 /* TypeError if wrong; class check, see E5 Section 15.10.6 */
79146 DUK_ASSERT(h_regexp != NULL);
79148 DUK_UNREF(h_regexp);
79149
79150 duk_to_string(ctx, -1);
79151 h_input = duk_get_hstring(ctx, -1);
79152 DUK_ASSERT(h_input != NULL);
79153
79154 duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_BYTECODE); /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
79155 h_bytecode = duk_require_hstring(ctx, -1); /* no regexp instance should exist without a non-configurable bytecode property */
79156 DUK_ASSERT(h_bytecode != NULL);
79157
79158 /*
79159 * Basic context initialization.
79160 *
79161 * Some init values are read from the bytecode header
79162 * whose format is (UTF-8 codepoints):
79163 *
79164 * uint flags
79165 * uint nsaved (even, 2n+2 where n = num captures)
79166 */
79167
79168 /* [ ... re_obj input bc ] */
79169
79170 DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
79171
79172 re_ctx.thr = thr;
79173 re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
79174 re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
79175 re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
79176 re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
79177 re_ctx.saved = NULL;
79180
79181 /* read header */
79182 pc = re_ctx.bytecode;
79183 re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
79184 re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
79185 re_ctx.bytecode = pc;
79186
79187 DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL); /* must fit into duk_small_int_t */
79188 global = (duk_small_int_t) (force_global | (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
79189
79190 DUK_ASSERT(re_ctx.nsaved >= 2);
79191 DUK_ASSERT((re_ctx.nsaved % 2) == 0);
79192
79193 p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sizeof(duk_uint8_t *) * re_ctx.nsaved);
79194 DUK_UNREF(p_buf);
79195 re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(ctx, -1, NULL);
79196 DUK_ASSERT(re_ctx.saved != NULL);
79197
79198 /* [ ... re_obj input bc saved_buf ] */
79199
79200#if defined(DUK_USE_EXPLICIT_NULL_INIT)
79201 for (i = 0; i < re_ctx.nsaved; i++) {
79202 re_ctx.saved[i] = (duk_uint8_t *) NULL;
79203 }
79204#elif defined(DUK_USE_ZERO_BUFFER_DATA)
79205 /* buffer is automatically zeroed */
79206#else
79207 DUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
79208#endif
79209
79210 DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
79211 (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
79212 (long) re_ctx.steps_limit));
79213
79214 /*
79215 * Get starting character offset for match, and initialize 'sp' based on it.
79216 *
79217 * Note: lastIndex is non-configurable so it must be present (we check the
79218 * internal class of the object above, so we know it is). User code can set
79219 * its value to an arbitrary (garbage) value though; E5 requires that lastIndex
79220 * be coerced to a number before using. The code below works even if the
79221 * property is missing: the value will then be coerced to zero.
79222 *
79223 * Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
79224 * For instance, ToInteger(+Infinity) = +Infinity. We track the match offset
79225 * as an integer, but pre-check it to be inside the 32-bit range before the loop.
79226 * If not, the check in E5 Section 15.10.6.2, step 9.a applies.
79227 */
79228
79229 /* XXX: lastIndex handling produces a lot of asm */
79230
79231 /* [ ... re_obj input bc saved_buf ] */
79232
79233 duk_get_prop_stridx(ctx, -4, DUK_STRIDX_LAST_INDEX); /* -> [ ... re_obj input bc saved_buf lastIndex ] */
79234 (void) duk_to_int(ctx, -1); /* ToInteger(lastIndex) */
79235 d = duk_get_number(ctx, -1); /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
79236 duk_pop(ctx);
79237
79238 if (global) {
79239 if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
79240 /* match fail */
79241 char_offset = 0; /* not really necessary */
79242 DUK_ASSERT(match == 0);
79243 goto match_over;
79244 }
79245 char_offset = (duk_uint32_t) d;
79246 } else {
79247 /* lastIndex must be ignored for non-global regexps, but get the
79248 * value for (theoretical) side effects. No side effects can
79249 * really occur, because lastIndex is a normal property and is
79250 * always non-configurable for RegExp instances.
79251 */
79252 char_offset = (duk_uint32_t) 0;
79253 }
79254
79255 sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
79256
79257 /*
79258 * Match loop.
79259 *
79260 * Try matching at different offsets until match found or input exhausted.
79261 */
79262
79263 /* [ ... re_obj input bc saved_buf ] */
79264
79265 DUK_ASSERT(match == 0);
79266
79267 for (;;) {
79268 /* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
79269 DUK_ASSERT_DISABLE(char_offset >= 0);
79270 DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
79271
79272 /* Note: ctx.steps is intentionally not reset, it applies to the entire unanchored match */
79273 DUK_ASSERT(re_ctx.recursion_depth == 0);
79274
79275 DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
79276 (long) char_offset, (const void *) sp,
79277 (const void *) re_ctx.input, (const void *) re_ctx.input_end));
79278
79279 /*
79280 * Note:
79281 *
79282 * - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
79283 * conditions; a longjmp() will terminate the entire matching process.
79284 *
79285 * - Clearing saved[] is not necessary because backtracking does it
79286 *
79287 * - Backtracking also rewinds ctx.recursion back to zero, unless an
79288 * internal/limit error occurs (which causes a longjmp())
79289 *
79290 * - If we supported anchored matches, we would break out here
79291 * unconditionally; however, Ecmascript regexps don't have anchored
79292 * matches. It might make sense to implement a fast bail-out if
79293 * the regexp begins with '^' and sp is not 0: currently we'll just
79294 * run through the entire input string, trivially failing the match
79295 * at every non-zero offset.
79296 */
79297
79298 if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
79299 DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
79300 match = 1;
79301 break;
79302 }
79303
79304 /* advance by one character (code point) and one char_offset */
79305 char_offset++;
79306 if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
79307 /*
79308 * Note:
79309 *
79310 * - Intentionally attempt (empty) match at char_offset == k_input->clen
79311 *
79312 * - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
79313 * -> no need or use for a negative check
79314 */
79315
79316 DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
79317 break;
79318 }
79319
79320 /* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
79321 (void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
79322 }
79323
79324 match_over:
79325
79326 /*
79327 * Matching complete, create result array or return a 'null'. Update lastIndex
79328 * if necessary. See E5 Section 15.10.6.2.
79329 *
79330 * Because lastIndex is a character (not byte) offset, we need the character
79331 * length of the match which we conveniently get as a side effect of interning
79332 * the matching substring (0th index of result array).
79333 *
79334 * saved[0] start pointer (~ byte offset) of current match
79335 * saved[1] end pointer (~ byte offset) of current match (exclusive)
79336 * char_offset start character offset of current match (-> .index of result)
79337 * char_end_offset end character offset (computed below)
79338 */
79339
79340 /* [ ... re_obj input bc saved_buf ] */
79341
79342 if (match) {
79343#ifdef DUK_USE_ASSERTIONS
79344 duk_hobject *h_res;
79345#endif
79346 duk_uint32_t char_end_offset = 0;
79347
79348 DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
79349
79350 DUK_ASSERT(re_ctx.nsaved >= 2); /* must have start and end */
79351 DUK_ASSERT((re_ctx.nsaved % 2) == 0); /* and even number */
79352
79353 /* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
79354 * advantage of now. The array is not compacted either, as regexp match
79355 * objects are usually short lived.
79356 */
79357
79358 duk_push_array(ctx);
79359
79360#ifdef DUK_USE_ASSERTIONS
79361 h_res = duk_require_hobject(ctx, -1);
79365#endif
79366
79367 /* [ ... re_obj input bc saved_buf res_obj ] */
79368
79369 duk_push_u32(ctx, char_offset);
79371
79372 duk_dup(ctx, -4);
79374
79375 for (i = 0; i < re_ctx.nsaved; i += 2) {
79376 /* Captures which are undefined have NULL pointers and are returned
79377 * as 'undefined'. The same is done when saved[] pointers are insane
79378 * (this should, of course, never happen in practice).
79379 */
79380 if (re_ctx.saved[i] && re_ctx.saved[i+1] && re_ctx.saved[i+1] >= re_ctx.saved[i]) {
79381 duk_hstring *h_saved;
79382
79383 duk_push_lstring(ctx,
79384 (const char *) re_ctx.saved[i],
79385 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
79386 h_saved = duk_get_hstring(ctx, -1);
79387 DUK_ASSERT(h_saved != NULL);
79388
79389 if (i == 0) {
79390 /* Assumes that saved[0] and saved[1] are always
79391 * set by regexp bytecode (if not, char_end_offset
79392 * will be zero). Also assumes clen reflects the
79393 * correct char length.
79394 */
79395 char_end_offset = char_offset + DUK_HSTRING_GET_CHARLEN(h_saved);
79396 }
79397 } else {
79398 duk_push_undefined(ctx);
79399 }
79400
79401 /* [ ... re_obj input bc saved_buf res_obj val ] */
79402 duk_put_prop_index(ctx, -2, i / 2);
79403 }
79404
79405 /* [ ... re_obj input bc saved_buf res_obj ] */
79406
79407 /* NB: 'length' property is automatically updated by the array setup loop */
79408
79409 if (global) {
79410 /* global regexp: lastIndex updated on match */
79411 duk_push_u32(ctx, char_end_offset);
79413 } else {
79414 /* non-global regexp: lastIndex never updated on match */
79415 ;
79416 }
79417 } else {
79418 /*
79419 * No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
79420 * of 'global' flag of the RegExp. In particular, if lastIndex is invalid
79421 * initially, it is reset to zero.
79422 */
79423
79424 DUK_DDD(DUK_DDDPRINT("regexp does not match"));
79425
79426 duk_push_null(ctx);
79427
79428 /* [ ... re_obj input bc saved_buf res_obj ] */
79429
79430 duk_push_int(ctx, 0);
79433
79434 /* [ ... re_obj input bc saved_buf res_obj ] */
79435
79436 duk_insert(ctx, -5);
79437
79438 /* [ ... res_obj re_obj input bc saved_buf ] */
79440 duk_pop_n(ctx, 4);
79441
79442 /* [ ... res_obj ] */
79443
79444 /* XXX: these last tricks are unnecessary if the function is made
79445 * a genuine native function.
79446 */
79447}
79448
79450 duk__regexp_match_helper(thr, 0 /*force_global*/);
79451}
79452
79453/* This variant is needed by String.prototype.split(); it needs to perform
79454 * global-style matching on a cloned RegExp which is potentially non-global.
79455 */
79457 duk__regexp_match_helper(thr, 1 /*force_global*/);
79458}
79459
79460#else /* DUK_USE_REGEXP_SUPPORT */
79461
79462/* regexp support disabled */
79463
79464#endif /* DUK_USE_REGEXP_SUPPORT */
79465#line 1 "duk_selftest.c"
79466/*
79467 * Self tests to ensure execution environment is sane. Intended to catch
79468 * compiler/platform problems which cannot be detected at compile time.
79469 */
79470
79471/* include removed: duk_internal.h */
79472
79473#if defined(DUK_USE_SELF_TESTS)
79474
79475/*
79476 * Unions and structs for self tests
79477 */
79478
79479typedef union {
79480 double d;
79481 duk_uint8_t c[8];
79482} duk__test_double_union;
79483
79484#define DUK__DBLUNION_CMP_TRUE(a,b) do { \
79485 if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
79486 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares false (expected true)"); \
79487 } \
79488 } while (0)
79489
79490#define DUK__DBLUNION_CMP_FALSE(a,b) do { \
79491 if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
79492 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares true (expected false)"); \
79493 } \
79494 } while (0)
79495
79496typedef union {
79497 duk_uint32_t i;
79498 duk_uint8_t c[8];
79499} duk__test_u32_union;
79500
79501/*
79502 * Various sanity checks for typing
79503 */
79504
79505DUK_LOCAL void duk__selftest_types(void) {
79506 if (!(sizeof(duk_int8_t) == 1 &&
79507 sizeof(duk_uint8_t) == 1 &&
79508 sizeof(duk_int16_t) == 2 &&
79509 sizeof(duk_uint16_t) == 2 &&
79510 sizeof(duk_int32_t) == 4 &&
79511 sizeof(duk_uint32_t) == 4)) {
79512 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int{8,16,32}_t size");
79513 }
79514#if defined(DUK_USE_64BIT_OPS)
79515 if (!(sizeof(duk_int64_t) == 8 &&
79516 sizeof(duk_uint64_t) == 8)) {
79517 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int64_t size");
79518 }
79519#endif
79520
79521 if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
79522 /* Some internal code now assumes that all duk_uint_t values
79523 * can be expressed with a duk_size_t.
79524 */
79525 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_size_t is smaller than duk_uint_t");
79526 }
79527 if (!(sizeof(duk_int_t) >= 4)) {
79528 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_int_t is not 32 bits");
79529 }
79530}
79531
79532/*
79533 * Packed tval sanity
79534 */
79535
79536DUK_LOCAL void duk__selftest_packed_tval(void) {
79537#if defined(DUK_USE_PACKED_TVAL)
79538 if (sizeof(void *) > 4) {
79539 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: packed duk_tval in use but sizeof(void *) > 4");
79540 }
79541#endif
79542}
79543
79544/*
79545 * Two's complement arithmetic.
79546 */
79547
79548DUK_LOCAL void duk__selftest_twos_complement(void) {
79549 volatile int test;
79550 test = -1;
79551
79552 /* Note that byte order doesn't affect this test: all bytes in
79553 * 'test' will be 0xFF for two's complement.
79554 */
79555 if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
79556 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic");
79557 }
79558}
79559
79560/*
79561 * Byte order. Important to self check, because on some exotic platforms
79562 * there is no actual detection but rather assumption based on platform
79563 * defines.
79564 */
79565
79566DUK_LOCAL void duk__selftest_byte_order(void) {
79567 duk__test_u32_union u1;
79568 duk__test_double_union u2;
79569
79570 /*
79571 * >>> struct.pack('>d', 102030405060).encode('hex')
79572 * '4237c17c6dc40000'
79573 */
79574#if defined(DUK_USE_INTEGER_LE)
79575 u1.c[0] = 0xef; u1.c[1] = 0xbe; u1.c[2] = 0xad; u1.c[3] = 0xde;
79576#elif defined(DUK_USE_INTEGER_ME)
79577#error integer mixed endian not supported now
79578#elif defined(DUK_USE_INTEGER_BE)
79579 u1.c[0] = 0xde; u1.c[1] = 0xad; u1.c[2] = 0xbe; u1.c[3] = 0xef;
79580#else
79581#error unknown integer endianness
79582#endif
79583
79584#if defined(DUK_USE_DOUBLE_LE)
79585 u2.c[0] = 0x00; u2.c[1] = 0x00; u2.c[2] = 0xc4; u2.c[3] = 0x6d;
79586 u2.c[4] = 0x7c; u2.c[5] = 0xc1; u2.c[6] = 0x37; u2.c[7] = 0x42;
79587#elif defined(DUK_USE_DOUBLE_ME)
79588 u2.c[0] = 0x7c; u2.c[1] = 0xc1; u2.c[2] = 0x37; u2.c[3] = 0x42;
79589 u2.c[4] = 0x00; u2.c[5] = 0x00; u2.c[6] = 0xc4; u2.c[7] = 0x6d;
79590#elif defined(DUK_USE_DOUBLE_BE)
79591 u2.c[0] = 0x42; u2.c[1] = 0x37; u2.c[2] = 0xc1; u2.c[3] = 0x7c;
79592 u2.c[4] = 0x6d; u2.c[5] = 0xc4; u2.c[6] = 0x00; u2.c[7] = 0x00;
79593#else
79594#error unknown double endianness
79595#endif
79596
79597 if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
79598 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_uint32_t byte order");
79599 }
79600
79601 if (u2.d != (double) 102030405060.0) {
79602 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double byte order");
79603 }
79604}
79605
79606/*
79607 * DUK_BSWAP macros
79608 */
79609
79610DUK_LOCAL void duk__selftest_bswap_macros(void) {
79611 duk_uint32_t x32;
79612 duk_uint16_t x16;
79614 duk_double_t du_diff;
79615
79616 x16 = 0xbeefUL;
79617 x16 = DUK_BSWAP16(x16);
79618 if (x16 != (duk_uint16_t) 0xefbeUL) {
79619 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP16");
79620 }
79621
79622 x32 = 0xdeadbeefUL;
79623 x32 = DUK_BSWAP32(x32);
79624 if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
79625 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP32");
79626 }
79627
79628 /* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
79629 * (2.008366013071895,)
79630 */
79631
79632 du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
79633 du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
79635 du_diff = du.d - 2.008366013071895;
79636#if 0
79637 DUK_FPRINTF(DUK_STDERR, "du_diff: %lg\n", (double) du_diff);
79638#endif
79639 if (du_diff > 1e-15) {
79640 /* Allow very small lenience because some compilers won't parse
79641 * exact IEEE double constants (happened in matrix testing with
79642 * Linux gcc-4.8 -m32 at least).
79643 */
79644#if 0
79645 DUK_FPRINTF(DUK_STDERR, "Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
79646 (unsigned int) du.uc[0], (unsigned int) du.uc[1],
79647 (unsigned int) du.uc[2], (unsigned int) du.uc[3],
79648 (unsigned int) du.uc[4], (unsigned int) du.uc[5],
79649 (unsigned int) du.uc[6], (unsigned int) du.uc[7]);
79650#endif
79651 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_DBLUNION_DOUBLE_NTOH");
79652 }
79653}
79654
79655/*
79656 * Basic double / byte union memory layout.
79657 */
79658
79659DUK_LOCAL void duk__selftest_double_union_size(void) {
79660 if (sizeof(duk__test_double_union) != 8) {
79661 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: invalid union size");
79662 }
79663}
79664
79665/*
79666 * Union aliasing, see misc/clang_aliasing.c.
79667 */
79668
79669DUK_LOCAL void duk__selftest_double_aliasing(void) {
79670 duk__test_double_union a, b;
79671
79672 /* This testcase fails when Emscripten-generated code runs on Firefox.
79673 * It's not an issue because the failure should only affect packed
79674 * duk_tval representation, which is not used with Emscripten.
79675 */
79676#if !defined(DUK_USE_PACKED_TVAL)
79677 DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
79678 return;
79679#endif
79680
79681 /* Test signaling NaN and alias assignment in all endianness combinations.
79682 */
79683
79684 /* little endian */
79685 a.c[0] = 0x11; a.c[1] = 0x22; a.c[2] = 0x33; a.c[3] = 0x44;
79686 a.c[4] = 0x00; a.c[5] = 0x00; a.c[6] = 0xf1; a.c[7] = 0xff;
79687 b = a;
79688 DUK__DBLUNION_CMP_TRUE(&a, &b);
79689
79690 /* big endian */
79691 a.c[0] = 0xff; a.c[1] = 0xf1; a.c[2] = 0x00; a.c[3] = 0x00;
79692 a.c[4] = 0x44; a.c[5] = 0x33; a.c[6] = 0x22; a.c[7] = 0x11;
79693 b = a;
79694 DUK__DBLUNION_CMP_TRUE(&a, &b);
79695
79696 /* mixed endian */
79697 a.c[0] = 0x00; a.c[1] = 0x00; a.c[2] = 0xf1; a.c[3] = 0xff;
79698 a.c[4] = 0x11; a.c[5] = 0x22; a.c[6] = 0x33; a.c[7] = 0x44;
79699 b = a;
79700 DUK__DBLUNION_CMP_TRUE(&a, &b);
79701}
79702
79703/*
79704 * Zero sign, see misc/tcc_zerosign2.c.
79705 */
79706
79707DUK_LOCAL void duk__selftest_double_zero_sign(void) {
79708 duk__test_double_union a, b;
79709
79710 a.d = 0.0;
79711 b.d = -a.d;
79712 DUK__DBLUNION_CMP_FALSE(&a, &b);
79713}
79714
79715/*
79716 * Struct size/alignment if platform requires it
79717 *
79718 * There are some compiler specific struct padding pragmas etc in use, this
79719 * selftest ensures they're correctly detected and used.
79720 */
79721
79722DUK_LOCAL void duk__selftest_struct_align(void) {
79723#if (DUK_USE_ALIGN_BY == 4)
79724 if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
79725 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 4");
79726 }
79727#elif (DUK_USE_ALIGN_BY == 8)
79728 if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
79729 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 8");
79730 }
79731#elif (DUK_USE_ALIGN_BY == 1)
79732 /* no check */
79733#else
79734#error invalid DUK_USE_ALIGN_BY
79735#endif
79736}
79737
79738/*
79739 * 64-bit arithmetic
79740 *
79741 * There are some platforms/compilers where 64-bit types are available
79742 * but don't work correctly. Test for known cases.
79743 */
79744
79745DUK_LOCAL void duk__selftest_64bit_arithmetic(void) {
79746#if defined(DUK_USE_64BIT_OPS)
79747 volatile duk_int64_t i;
79748 volatile duk_double_t d;
79749
79750 /* Catch a double-to-int64 cast issue encountered in practice. */
79751 d = 2147483648.0;
79752 i = (duk_int64_t) d;
79753 if (i != 0x80000000LL) {
79754 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: casting 2147483648.0 to duk_int64_t failed");
79755 }
79756#else
79757 /* nop */
79758#endif
79759}
79760
79761/*
79762 * Casting
79763 */
79764
79765DUK_LOCAL void duk__selftest_cast_double_to_small_uint(void) {
79766 /*
79767 * https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
79768 */
79769
79770 duk_double_t d1, d2;
79772
79773 duk_double_t d1v, d2v;
79775
79776 /* Test without volatiles */
79777
79778 d1 = 1.0;
79779 u = (duk_small_uint_t) d1;
79780 d2 = (duk_double_t) u;
79781
79782 if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
79783 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
79784 }
79785
79786 /* Same test with volatiles */
79787
79788 d1v = 1.0;
79789 uv = (duk_small_uint_t) d1v;
79790 d2v = (duk_double_t) uv;
79791
79792 if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
79793 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
79794 }
79795}
79796
79797DUK_LOCAL void duk__selftest_cast_double_to_uint32(void) {
79798 /*
79799 * This test fails on an exotic ARM target; double-to-uint
79800 * cast is incorrectly clamped to -signed- int highest value.
79801 *
79802 * https://github.com/svaarala/duktape/issues/336
79803 */
79804
79805 duk_double_t dv;
79806 duk_uint32_t uv;
79807
79808 dv = 3735928559.0; /* 0xdeadbeef in decimal */
79809 uv = (duk_uint32_t) dv;
79810
79811 if (uv != 0xdeadbeefUL) {
79812 DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_uint32_t cast failed");
79813 }
79814}
79815
79816/*
79817 * Self test main
79818 */
79819
79820DUK_INTERNAL void duk_selftest_run_tests(void) {
79821 duk__selftest_types();
79822 duk__selftest_packed_tval();
79823 duk__selftest_twos_complement();
79824 duk__selftest_byte_order();
79825 duk__selftest_bswap_macros();
79826 duk__selftest_double_union_size();
79827 duk__selftest_double_aliasing();
79828 duk__selftest_double_zero_sign();
79829 duk__selftest_struct_align();
79830 duk__selftest_64bit_arithmetic();
79831 duk__selftest_cast_double_to_small_uint();
79832 duk__selftest_cast_double_to_uint32();
79833}
79834
79835#undef DUK__DBLUNION_CMP_TRUE
79836#undef DUK__DBLUNION_CMP_FALSE
79837
79838#endif /* DUK_USE_SELF_TESTS */
79839/* include removed: duk_internal.h */
79840#line 2 "duk_tval.c"
79841
79842#if defined(DUK_USE_FASTINT)
79843
79844/*
79845 * Manually optimized double-to-fastint downgrade check.
79846 *
79847 * This check has a large impact on performance, especially for fastint
79848 * slow paths, so must be changed carefully. The code should probably be
79849 * optimized for the case where the result does not fit into a fastint,
79850 * to minimize the penalty for "slow path code" dealing with fractions etc.
79851 *
79852 * At least on one tested soft float ARM platform double-to-int64 coercion
79853 * is very slow (and sometimes produces incorrect results, see self tests).
79854 * This algorithm combines a fastint compatibility check and extracting the
79855 * integer value from an IEEE double for setting the tagged fastint. For
79856 * other platforms a more naive approach might be better.
79857 *
79858 * See doc/fastint.rst for details.
79859 */
79860
79861DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x) {
79863 duk_int64_t i;
79864 duk_small_int_t expt;
79865 duk_small_int_t shift;
79866
79867 /* XXX: optimize for packed duk_tval directly? */
79868
79869 du.d = x;
79870 i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
79871 expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
79872 shift = expt - 1023;
79873
79874 if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */
79875 duk_int64_t t;
79876
79877 if (((0x000fffffffffffffLL >> shift) & i) == 0) {
79878 t = i | 0x0010000000000000LL; /* implicit leading one */
79879 t = t & 0x001fffffffffffffLL;
79880 t = t >> (52 - shift);
79881 if (i < 0) {
79882 t = -t;
79883 }
79884 DUK_TVAL_SET_FASTINT(tv, t);
79885 return;
79886 }
79887 } else if (shift == -1023) { /* exponent 0 */
79888 if (i >= 0 && (i & 0x000fffffffffffffLL) == 0) {
79889 /* Note: reject negative zero. */
79890 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
79891 return;
79892 }
79893 } else if (shift == 47) { /* exponent 1070 */
79894 if (i < 0 && (i & 0x000fffffffffffffLL) == 0) {
79895 DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
79896 return;
79897 }
79898 }
79899
79900 DUK_TVAL_SET_DOUBLE(tv, x);
79901 return;
79902}
79903
79904/*
79905 * Manually optimized number-to-double conversion
79906 */
79907
79908#if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
79909DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
79911 duk_uint64_t t;
79912
79913 t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
79914 if ((t >> 48) != DUK_TAG_FASTINT) {
79915 return tv->d;
79916 } else if (t & 0x0000800000000000ULL) {
79917 t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */
79918 t = t & 0x0000ffffffffffffULL; /* negative */
79919 t |= 0xc330000000000000ULL;
79920 DUK_DBLUNION_SET_UINT64(&du, t);
79921 return du.d + 4503599627370496.0; /* 1 << 52 */
79922 } else if (t != 0) {
79923 t &= 0x0000ffffffffffffULL; /* positive */
79924 t |= 0x4330000000000000ULL;
79925 DUK_DBLUNION_SET_UINT64(&du, t);
79926 return du.d - 4503599627370496.0; /* 1 << 52 */
79927 } else {
79928 return 0.0; /* zero */
79929 }
79930}
79931#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
79932
79933#if 0 /* unused */
79934#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
79935DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
79937 duk_uint64_t t;
79938
79939 DUK_ASSERT(tv->t == DUK__TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
79940
79941 if (tv->t == DUK_TAG_FASTINT) {
79942 if (tv->v.fi >= 0) {
79943 t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
79944 DUK_DBLUNION_SET_UINT64(&du, t);
79945 return du.d - 4503599627370496.0; /* 1 << 52 */
79946 } else {
79947 t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
79948 DUK_DBLUNION_SET_UINT64(&du, t);
79949 return du.d + 4503599627370496.0; /* 1 << 52 */
79950 }
79951 } else {
79952 return tv->v.d;
79953 }
79954}
79955#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
79956#endif /* 0 */
79957
79958#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
79959DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
79961 duk_uint64_t t;
79962
79963 DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
79964
79965 if (tv->v.fi >= 0) {
79966 t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
79967 DUK_DBLUNION_SET_UINT64(&du, t);
79968 return du.d - 4503599627370496.0; /* 1 << 52 */
79969 } else {
79970 t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
79971 DUK_DBLUNION_SET_UINT64(&du, t);
79972 return du.d + 4503599627370496.0; /* 1 << 52 */
79973 }
79974}
79975#endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
79976
79977#endif /* DUK_USE_FASTINT */
79978#line 1 "duk_unicode_tables.c"
79979/*
79980 * Unicode support tables automatically generated during build.
79981 */
79982
79983/* include removed: duk_internal.h */
79984
79985/*
79986 * Unicode tables containing ranges of Unicode characters in a
79987 * packed format. These tables are used to match non-ASCII
79988 * characters of complex productions by resorting to a linear
79989 * range-by-range comparison. This is very slow, but is expected
79990 * to be very rare in practical Ecmascript source code, and thus
79991 * compactness is most important.
79992 *
79993 * The tables are matched using uni_range_match() and the format
79994 * is described in src/extract_chars.py.
79995 */
79996
79997#ifdef DUK_USE_SOURCE_NONBMP
79998/* IdentifierStart production with ASCII excluded */
79999/* duk_unicode_ids_noa[] */
80000/*
80001 * Automatically generated by extract_chars.py, do not edit!
80002 */
80003
80004const duk_uint8_t duk_unicode_ids_noa[791] = {
80005249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
80006240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
8000718,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
80008101,10,4,15,9,240,159,157,242,100,15,4,8,159,1,98,102,115,19,240,98,98,4,
8000952,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,2,130,34,
80010240,98,98,18,68,15,4,15,1,31,21,115,19,240,98,98,18,68,15,16,18,47,1,15,3,
800112,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,146,68,15,12,23,31,21,
80012114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,15,3,31,10,86,
80013240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,34,2,3,18,50,
8001426,3,66,15,7,31,20,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,24,37,
80015205,15,3,241,107,241,178,4,255,224,59,35,54,32,35,63,25,35,63,17,35,54,32,
8001635,62,47,41,35,63,51,241,127,0,240,47,69,223,254,21,227,240,18,240,166,243,
80017180,47,1,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,137,241,
80018146,6,243,107,240,223,37,240,227,76,241,207,7,111,42,240,122,242,95,68,15,
8001979,241,255,3,111,41,240,238,31,2,241,111,12,241,79,27,43,241,79,93,50,63,0,
80020251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,15,63,37,38,32,66,38,67,53,
8002192,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
80022240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
80023122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
8002474,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
80025255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
8002647,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
8002734,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
80028240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
80029240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
8003024,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
80031171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,241,91,47,10,47,3,
8003233,46,61,241,79,107,243,127,37,255,223,13,79,33,242,31,15,240,63,11,242,
80033127,14,63,20,87,36,241,207,142,255,226,86,83,2,241,194,20,3,240,127,156,
80034240,107,240,175,184,15,1,50,34,240,191,30,240,223,117,242,107,240,107,240,
8003563,127,243,159,254,42,239,37,243,223,29,255,238,68,255,226,97,248,63,83,
80036255,234,145,255,227,33,255,240,2,44,95,254,18,191,255,0,52,187,31,255,0,18,
80037242,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,
80038255,224,70,63,9,47,9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,
80039240,1,114,143,255,0,149,201,241,191,254,242,124,252,239,255,0,46,214,255,
80040225,16,0,
80041};
80042#else
80043/* IdentifierStart production with ASCII and non-BMP excluded */
80044/* duk_unicode_ids_noabmp[] */
80045/*
80046 * Automatically generated by extract_chars.py, do not edit!
80047 */
80048
80049const duk_uint8_t duk_unicode_ids_noabmp[611] = {
80050249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
80051240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
8005218,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
80053101,10,4,15,9,240,159,157,242,100,15,4,8,159,1,98,102,115,19,240,98,98,4,
8005452,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,2,130,34,
80055240,98,98,18,68,15,4,15,1,31,21,115,19,240,98,98,18,68,15,16,18,47,1,15,3,
800562,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,146,68,15,12,23,31,21,
80057114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,15,3,31,10,86,
80058240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,34,2,3,18,50,
8005926,3,66,15,7,31,20,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,24,37,
80060205,15,3,241,107,241,178,4,255,224,59,35,54,32,35,63,25,35,63,17,35,54,32,
8006135,62,47,41,35,63,51,241,127,0,240,47,69,223,254,21,227,240,18,240,166,243,
80062180,47,1,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,137,241,
80063146,6,243,107,240,223,37,240,227,76,241,207,7,111,42,240,122,242,95,68,15,
8006479,241,255,3,111,41,240,238,31,2,241,111,12,241,79,27,43,241,79,93,50,63,0,
80065251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,15,63,37,38,32,66,38,67,53,
8006692,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
80067240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
80068122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
8006974,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
80070255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
8007147,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
8007234,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
80073240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
80074240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
8007524,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
80076171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,0,
80077};
80078#endif
80079
80080#ifdef DUK_USE_SOURCE_NONBMP
80081/* IdentifierStart production with Letter and ASCII excluded */
80082/* duk_unicode_ids_m_let_noa[] */
80083/*
80084 * Automatically generated by extract_chars.py, do not edit!
80085 */
80086
80087const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
80088255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
80089249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,48,
80090};
80091#else
80092/* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
80093/* duk_unicode_ids_m_let_noabmp[] */
80095 * Automatically generated by extract_chars.py, do not edit!
80096 */
80097
80098const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
80099255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
80100249,0,
80101};
80102#endif
80103
80104#ifdef DUK_USE_SOURCE_NONBMP
80105/* IdentifierPart production with IdentifierStart and ASCII excluded */
80106/* duk_unicode_idp_m_ids_noa[] */
80107/*
80108 * Automatically generated by extract_chars.py, do not edit!
80109 */
80110
80111const duk_uint8_t duk_unicode_idp_m_ids_noa[397] = {
80112255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
80113245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
8011436,241,210,249,99,242,130,47,2,38,177,57,240,50,242,160,38,49,50,160,177,
8011557,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,97,57,
80116240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,240,50,
80117242,198,34,35,129,193,57,240,65,242,160,38,34,35,129,193,57,240,65,242,198,
8011834,35,160,177,57,240,65,243,128,85,32,39,240,65,242,240,54,215,41,244,144,
8011953,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,111,4,41,
80120211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,241,1,243,
8012179,14,160,57,241,50,57,248,16,246,139,91,185,245,47,1,129,121,242,244,242,
80122185,47,13,58,121,245,132,242,31,1,201,240,56,210,241,9,105,241,237,242,47,
801234,153,121,246,130,47,5,80,80,251,255,23,240,115,255,225,0,31,35,31,5,15,
80124109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,255,0,100,
80125121,159,55,13,31,100,31,254,0,64,64,80,240,148,244,161,242,79,1,201,127,2,
80126240,9,240,231,240,188,241,227,242,29,240,25,244,29,208,145,57,241,48,242,
8012796,34,49,97,32,255,224,21,114,19,159,255,0,62,24,15,254,29,95,0,240,38,209,
80128240,162,251,41,241,112,255,225,177,15,254,25,105,255,228,75,34,22,63,26,37,
8012915,254,75,66,242,126,241,25,240,34,241,250,255,240,10,249,228,69,151,54,
80130241,3,248,98,255,228,125,242,47,255,12,23,244,254,0,
80131};
80132#else
80133/* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
80134/* duk_unicode_idp_m_ids_noabmp[] */
80135/*
80136 * Automatically generated by extract_chars.py, do not edit!
80137 */
80138
80139const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348] = {
80140255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
80141245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
8014236,241,210,249,99,242,130,47,2,38,177,57,240,50,242,160,38,49,50,160,177,
8014357,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,97,57,
80144240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,240,50,
80145242,198,34,35,129,193,57,240,65,242,160,38,34,35,129,193,57,240,65,242,198,
8014634,35,160,177,57,240,65,243,128,85,32,39,240,65,242,240,54,215,41,244,144,
8014753,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,111,4,41,
80148211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,241,1,243,
8014979,14,160,57,241,50,57,248,16,246,139,91,185,245,47,1,129,121,242,244,242,
80150185,47,13,58,121,245,132,242,31,1,201,240,56,210,241,9,105,241,237,242,47,
801514,153,121,246,130,47,5,80,80,251,255,23,240,115,255,225,0,31,35,31,5,15,
80152109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,255,0,100,
80153121,159,55,13,31,100,31,254,0,64,64,80,240,148,244,161,242,79,1,201,127,2,
80154240,9,240,231,240,188,241,227,242,29,240,25,244,29,208,145,57,241,48,242,
8015596,34,49,97,32,255,224,21,114,19,159,255,0,62,24,15,254,29,95,0,240,38,209,
80156240,162,251,41,241,112,0,
80157};
80158#endif
80159
80160/*
80161 * Case conversion tables generated using src/extract_caseconv.py.
80162 */
80163
80164/* duk_unicode_caseconv_uc[] */
80165/* duk_unicode_caseconv_lc[] */
80166
80167/*
80168 * Automatically generated by extract_caseconv.py, do not edit!
80169 */
80170
80171const duk_uint8_t duk_unicode_caseconv_uc[1288] = {
80172132,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
80173128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
80174104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,15,128,15,132,8,31,16,
8017531,24,12,62,64,62,80,32,124,192,124,224,64,250,0,250,64,97,246,1,246,129,3,
80176238,3,247,64,135,220,135,242,2,15,187,15,237,2,31,120,31,248,4,62,244,63,
80177212,8,125,240,127,232,16,253,128,253,192,33,253,1,253,128,67,252,3,253,0,
80178136,92,8,88,8,18,104,18,91,26,44,48,44,0,94,90,0,33,64,155,253,7,252,132,
80179212,0,32,32,32,6,0,76,192,76,129,128,157,0,156,136,1,75,1,74,46,2,244,2,
80180242,12,6,12,6,8,16,13,8,13,0,48,27,64,27,48,64,57,192,57,162,0,119,192,119,
80181132,128,252,128,252,20,2,35,2,34,18,4,142,4,140,20,13,196,13,192,16,30,200,
8018230,192,192,70,16,70,2,32,145,96,145,70,193,48,129,48,67,130,104,130,104,44,
8018330,1,30,0,150,61,66,61,64,192,125,68,125,100,33,99,65,99,56,50,200,18,200,
801846,69,157,133,157,96,169,144,105,144,11,211,64,211,64,12,167,35,167,34,15,
8018578,103,78,100,126,157,234,157,228,21,59,253,59,240,90,122,26,122,0,163,128,
80186214,128,214,2,1,197,1,196,6,3,140,3,136,12,7,200,7,196,16,20,0,13,48,32,63,
80187128,63,112,69,142,101,142,64,130,1,136,1,135,4,3,114,3,112,8,26,120,202,
80188120,176,65,1,30,1,29,130,2,105,1,150,5,255,96,22,160,115,128,31,224,47,0,
8018938,32,9,32,47,224,10,96,48,0,72,96,50,64,50,32,50,160,62,192,51,32,51,0,51,
8019064,71,160,51,192,68,0,53,0,52,224,55,224,62,224,59,160,49,192,62,96,62,32,
8019174,5,141,224,74,37,141,160,74,69,142,0,74,96,48,32,74,128,48,192,75,32,49,
80192224,75,96,50,0,76,0,50,96,76,96,50,128,76,180,241,160,77,0,50,224,77,101,
80193140,64,78,37,141,192,78,64,51,160,78,160,51,224,79,165,140,128,81,0,53,192,
8019481,32,72,128,81,128,72,160,82,64,54,224,104,160,115,32,110,224,110,192,117,
80195128,112,192,120,64,116,96,121,128,113,128,122,0,114,64,122,32,115,0,122,
80196160,116,192,122,192,116,0,122,224,121,224,126,0,115,64,126,32,116,32,126,
8019764,127,32,126,160,114,160,153,224,152,3,175,52,239,163,175,165,140,99,211,
8019899,204,3,247,192,115,35,252,163,253,132,41,196,38,68,48,132,48,101,140,37,
80199140,5,140,160,71,69,140,192,71,217,128,55,224,5,48,5,48,20,152,10,240,1,56,
802007,194,0,74,3,12,3,144,192,230,64,194,0,192,64,236,48,58,80,48,128,48,16,88,
80201120,20,212,21,72,122,90,0,72,3,49,30,151,128,21,0,194,7,166,32,5,112,48,
80202161,233,152,1,100,12,40,122,106,0,65,2,190,31,80,128,233,64,196,199,212,
80203176,58,80,49,48,48,1,245,76,14,148,12,76,12,4,125,91,3,165,3,19,3,66,31,
80204128,135,194,0,230,71,224,97,240,144,57,145,248,40,124,40,14,100,126,14,31,
8020511,3,153,31,132,135,195,0,230,71,225,97,240,208,57,145,248,104,124,56,14,
80206100,126,30,31,15,3,153,31,136,135,194,0,230,71,226,97,240,144,57,145,248,
80207168,124,40,14,100,126,46,31,11,3,153,31,140,135,195,0,230,71,227,97,240,
80208208,57,145,248,232,124,56,14,100,126,62,31,15,3,153,31,144,135,202,0,230,
8020971,228,97,242,144,57,145,249,40,124,168,14,100,126,78,31,43,3,153,31,148,
80210135,203,0,230,71,229,97,242,208,57,145,249,104,124,184,14,100,126,94,31,47,
802113,153,31,152,135,202,0,230,71,230,97,242,144,57,145,249,168,124,168,14,100,
80212126,110,31,43,3,153,31,156,135,203,0,230,71,231,97,242,208,57,145,249,232,
80213124,184,14,100,126,126,31,47,3,153,31,160,135,218,0,230,71,232,97,246,144,
8021457,145,250,40,125,168,14,100,126,142,31,107,3,153,31,164,135,219,0,230,71,
80215233,97,246,208,57,145,250,104,125,184,14,100,126,158,31,111,3,153,31,168,
80216135,218,0,230,71,234,97,246,144,57,145,250,168,125,168,14,100,126,174,31,
80217107,3,153,31,172,135,219,0,230,71,235,97,246,208,57,145,250,232,125,184,14,
80218100,126,190,31,111,3,153,31,178,135,238,128,230,71,236,224,57,16,57,145,
80219251,72,14,24,14,100,126,218,3,145,3,66,31,183,192,228,64,208,128,230,71,
80220239,32,57,16,57,145,252,40,127,40,14,100,127,14,3,151,3,153,31,196,128,226,
8022164,230,71,241,160,57,112,52,33,252,124,14,92,13,8,14,100,127,50,3,151,3,
80222153,31,210,192,230,64,194,0,192,7,244,240,57,144,48,128,48,17,253,104,14,
80223100,13,8,127,95,3,153,3,8,3,66,31,226,192,233,64,194,0,192,7,248,240,58,80,
8022448,128,48,17,254,72,14,132,12,76,127,154,3,165,3,66,31,231,192,233,64,194,
802250,208,135,252,161,255,160,57,145,255,56,14,164,14,100,127,210,3,143,3,153,
8022631,246,128,234,64,208,135,253,240,58,144,52,32,57,145,255,200,14,164,14,
80227103,236,2,0,70,0,70,251,1,128,17,128,18,126,192,160,4,96,4,207,176,60,1,24,
802281,24,1,39,236,19,0,70,0,70,0,76,251,5,128,20,192,21,62,193,160,5,48,5,79,
80229177,56,21,16,21,27,236,82,5,68,5,53,251,21,129,81,1,78,254,197,160,84,224,
8023084,111,177,120,21,16,20,244,
80231};
80232const duk_uint8_t duk_unicode_caseconv_lc[616] = {
80233144,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
80234235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
802350,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,15,132,15,128,8,31,24,
8023631,16,12,62,80,62,64,32,124,224,124,192,64,250,64,250,0,97,246,129,246,1,3,
80237241,3,240,2,7,230,7,228,4,15,212,15,208,8,31,184,31,176,4,63,116,62,224,8,
80238127,32,125,200,32,254,192,254,128,33,253,161,247,96,67,253,3,252,0,135,250,
80239135,222,129,15,252,15,188,2,31,250,31,124,4,66,192,66,224,64,146,216,147,
8024064,209,96,1,97,130,242,199,224,35,240,95,228,63,232,38,161,1,0,1,1,48,2,
80241100,2,102,12,4,228,4,232,64,10,80,10,89,112,23,144,23,160,96,48,64,48,96,
80242128,104,0,104,65,128,217,128,218,2,1,203,1,204,18,3,188,3,190,36,7,200,7,
80243204,16,15,192,15,201,64,34,32,34,49,32,72,192,72,225,64,220,0,220,65,1,236,
802441,236,140,4,96,4,97,34,9,20,9,22,108,19,4,19,8,56,38,128,38,138,193,224,1,
80245224,25,99,212,3,212,44,7,214,71,212,66,22,51,150,52,3,44,128,44,129,100,89,
80246214,89,216,10,153,2,153,4,189,52,5,52,8,202,114,42,114,48,244,230,84,230,
80247103,233,222,105,222,129,83,191,83,191,133,167,160,167,161,10,48,13,48,20,0,
8024832,26,192,26,208,64,56,128,56,192,192,113,64,113,129,1,251,129,252,2,44,
80249114,44,115,4,16,12,56,12,64,32,27,128,27,144,64,211,197,211,198,2,8,6,88,9,
80250164,16,17,216,17,224,47,245,1,120,0,255,1,129,2,83,1,134,2,84,1,142,1,221,
802511,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,
802521,153,1,157,2,114,1,159,2,117,1,167,1,168,1,174,2,136,1,183,2,146,1,241,1,
80253243,1,246,1,149,1,247,1,191,2,32,1,158,2,58,44,101,2,61,1,154,2,62,44,102,
802542,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,
802553,215,3,244,3,184,3,249,3,242,4,192,4,207,30,158,0,223,31,188,31,179,31,
80256204,31,195,31,236,31,229,31,252,31,243,33,38,3,201,33,42,0,107,33,43,0,229,
8025733,50,33,78,33,131,33,132,44,96,44,97,44,98,2,107,44,99,29,125,44,100,2,
80258125,44,109,2,81,44,110,2,113,44,111,2,80,44,112,2,82,167,125,29,121,167,
80259141,2,101,2,2,97,0,52,129,131,128,
80260};
80261
80262#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
80263/*
80264 * Automatically generated by extract_caseconv.py, do not edit!
80265 */
80266
80267const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
802680,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,
8026928,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
8027053,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
8027178,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,
8027271,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
80273126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
80274144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
80275162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
80276180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
80277198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
80278216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
80279202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
80280220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
80281270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
80282288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
80283306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
80284323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
80285342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
80286360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
80287377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
80288395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
80289544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
80290431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
80291450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
80292467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
80293486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
80294504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
80295522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
80296540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
80297558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
8029811391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
8029911373,11376,385,390,597,393,394,600,399,602,400,604,605,606,607,403,609,
80300610,404,612,42893L,614,615,407,406,618,11362,620,621,622,412,624,11374,413,
80301627,628,415,630,631,632,633,634,635,636,11364,638,639,422,641,642,425,644,
80302645,646,647,430,580,433,434,581,653,654,655,656,657,439,659,660,661,662,
80303663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,
80304681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,
80305699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,
80306717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,
80307735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,
80308753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,
80309771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,
80310789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,
80311807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,
80312825,826,827,828,829,830,831,832,833,834,835,836,921,838,839,840,841,842,
80313843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,
80314861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,
80315879,880,880,882,882,884,885,886,886,888,889,890,1021,1022,1023,894,895,896,
80316897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,
80317915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,
80318933,934,935,936,937,938,939,902,904,905,906,944,913,914,915,916,917,918,
80319919,920,921,922,923,924,925,926,927,928,929,931,931,932,933,934,935,936,
80320937,938,939,908,910,911,975,914,920,978,979,980,934,928,975,984,984,986,
80321986,988,988,990,990,992,992,994,994,996,996,998,998,1000,1000,1002,1002,
803221004,1004,1006,1006,922,929,1017,1011,1012,917,1014,1015,1015,1017,1018,
803231018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,
803241034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,
803251049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,
803261064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,1043,1044,1045,1046,
803271047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,
803281062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,1025,1026,1027,1028,
803291029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1120,1120,1122,1122,
803301124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,1134,1136,1136,1138,
803311138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,1150,1150,1152,1152,
803321154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,1164,1166,1166,1168,
803331168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,1180,1180,1182,1182,
803341184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,1194,1196,1196,1198,
803351198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,1210,1210,1212,1212,
803361214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,1225,1225,1227,1227,
803371229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,1240,1240,1242,1242,
803381244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,1254,1256,1256,1258,
803391258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,1270,1270,1272,1272,
803401274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,1284,1286,1286,1288,
803411288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,1300,1300,1302,1302,
803421304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,1314,1316,1316,1318,
803431318,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,
803441334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,
803451349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,
803461364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1329,1330,
803471331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,
803481346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,
803491361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,1420,1421,1422,1423,
803501424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,
803511439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,
803521454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,
803531469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,
803541484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,
803551499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,
803561514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,
803571529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,
803581544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,
803591559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,
803601574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,
803611589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,
803621604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,
803631619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,
803641634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,
803651649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,
803661664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,
803671679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,
803681694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,
803691709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,
803701724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,
803711739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,
803721754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,
803731769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,
803741784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,
803751799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,
803761814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,
803771829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,
803781844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,
803791859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,
803801874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,
803811889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,
803821904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,
803831919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,
803841934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,
803851949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,
803861964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,
803871979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,
803881994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,
803892009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,
803902024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,
803912039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,
803922054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,
803932069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,
803942084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,
803952099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,
803962114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,
803972129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,
803982144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,
803992159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,
804002174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,
804012189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,
804022204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,
804032219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,
804042234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,
804052249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,
804062264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,
804072279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,
804082294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,
804092309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,
804102324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,
804112339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,
804122354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,
804132369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,
804142384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,
804152399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,
804162414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,
804172429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,
804182444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,
804192459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,
804202474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,
804212489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,
804222504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,
804232519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,
804242534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,
804252549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562,2563,
804262564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,
804272579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,
804282594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,
804292609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,
804302624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,
804312639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,
804322654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,
804332669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,
804342684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,
804352699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,
804362714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,
804372729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,
804382744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,
804392759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,
804402774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,
804412789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,
804422804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,
804432819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,
804442834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,
804452849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,
804462864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,
804472879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,
804482894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,
804492909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,
804502924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,
804512939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,
804522954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,
804532969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,
804542984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,
804552999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,
804563014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,
804573029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,
804583044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,
804593059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,
804603074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,
804613089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,
804623104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,
804633119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,
804643134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,
804653149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,
804663164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,
804673179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,
804683194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,
804693209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,
804703224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,
804713239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,
804723254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,
804733269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,
804743284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,
804753299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,
804763314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,
804773329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,
804783344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,
804793359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,
804803374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,
804813389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,
804823404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,
804833419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,
804843434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,
804853449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,
804863464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,
804873479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,
804883494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,
804893509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,
804903524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,
804913539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,
804923554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,
804933569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,
804943584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,
804953599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,
804963614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,
804973629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,
804983644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,
804993659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,
805003674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685,3686,3687,3688,
805013689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,
805023704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,
805033719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,
805043734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,
805053749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,
805063764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,
805073779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,
805083794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,
805093809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,
805103824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,
805113839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852,3853,
805123854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,
805133869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,
805143884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,
805153899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,
805163914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,
805173929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,
805183944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,
805193959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,
805203974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,
805213989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,
805224004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,
805234019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,
805244034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,
805254049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,
805264064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,
805274079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,
805284094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,
805294109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,
805304124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,
805314139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,
805324154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,
805334169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,
805344184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,
805354199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,
805364214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4226,4227,4228,
805374229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,
805384244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,
805394259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,
805404274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,
805414289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,
805424304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,
805434319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,
805444334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,
805454349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,
805464364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,
805474379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,
805484394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,
805494409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,4420,4421,4422,4423,
805504424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,
805514439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,
805524454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,
805534469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,
805544484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,
805554499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,
805564514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,
805574529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,
805584544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,
805594559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,
805604574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,
805614589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,
805624604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,
805634619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,
805644634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,
805654649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,
805664664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,
805674679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,
805684694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,
805694709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,
805704724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,
805714739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,
805724754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,
805734769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,
805744784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796,4797,4798,
805754799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,
805764814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,
805774829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,
805784844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,
805794859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,
805804874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,
805814889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,
805824904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,
805834919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,
805844934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,
805854949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,
805864964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,
805874979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,4992,4993,
805884994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,
805895009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,
805905024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,
805915039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,
805925054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,
805935069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,
805945084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,
805955099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,
805965114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,
805975129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,
805985144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,
805995159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,
806005174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,
806015189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,
806025204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,
806035219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,
806045234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,
806055249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,
806065264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,
806075279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,
806085294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,
806095309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,
806105324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,
806115339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,
806125354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,
806135369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,
806145384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,
806155399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,
806165414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,
806175429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,
806185444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,
806195459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,
806205474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,
806215489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,
806225504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,
806235519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,
806245534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,
806255549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,
806265564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,
806275579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,
806285594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,
806295609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,
806305624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,5635,5636,5637,5638,
806315639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,
806325654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,
806335669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,
806345684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,
806355699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,
806365714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,
806375729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,
806385744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,
806395759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,
806405774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,
806415789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,
806425804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,
806435819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,
806445834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,
806455849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,
806465864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876,5877,5878,
806475879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892,5893,
806485894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908,
806495909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,
806505924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,
806515939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952,5953,
806525954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,
806535969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,
806545984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,
806555999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,
806566014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,
806576029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,
806586044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,
806596059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071,6072,6073,
806606074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,
806616089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102,6103,
806626104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,
806636119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132,6133,
806646134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,6145,6146,6147,6148,
806656149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,
806666164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,
806676179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,
806686194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,
806696209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,
806706224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,
806716239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,
806726254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,6265,6266,6267,6268,
806736269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,
806746284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,
806756299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6313,
806766314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,
806776329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,6340,6341,6342,6343,
806786344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,
806796359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,
806806374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,
806816389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,6400,6401,6402,6403,
806826404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,
806836419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6431,6432,6433,
806846434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,6445,6446,6447,6448,
806856449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6460,6461,6462,6463,
806866464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,6475,6476,6477,6478,
806876479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,
806886494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,
806896509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,6520,6521,6522,6523,
806906524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,
806916539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,
806926554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,
806936569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,6582,6583,
806946584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,6598,
806956599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613,
806966614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,
806976629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,6640,6641,6642,6643,
806986644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,
806996659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,
807006674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,
807016689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,
807026704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,
807036719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,
807046734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,6746,6747,6748,
807056749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,
807066764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,
807076779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,
807086794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,
807096809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,
807106824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,6837,6838,
807116839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,
807126854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,
807136869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,
807146884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,
807156899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,6910,6911,6912,6913,
807166914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,
807176929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,
807186944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,
807196959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,
807206974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,6985,6986,6987,6988,
807216989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7002,7003,
807227004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,7015,7016,7017,7018,
807237019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,7030,7031,7032,7033,
807247034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,7045,7046,7047,7048,
807257049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,
807267064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,7075,7076,7077,7078,
807277079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090,7091,7092,7093,
807287094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105,7106,7107,7108,
807297109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,
807307124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,
807317139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,
807327154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167,7168,
807337169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,
807347184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,
807357199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,
807367214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,
807377229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,
807387244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,
807397259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,
807407274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,
807417289,7290,7291,7292,7293,7294,7295,7296,7297,7298,7299,7300,7301,7302,7303,
807427304,7305,7306,7307,7308,7309,7310,7311,7312,7313,7314,7315,7316,7317,7318,
807437319,7320,7321,7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,
807447334,7335,7336,7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,
807457349,7350,7351,7352,7353,7354,7355,7356,7357,7358,7359,7360,7361,7362,7363,
807467364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375,7376,7377,7378,
807477379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,
807487394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407,7408,
807497409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423,
807507424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,
807517439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,
807527454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,
807537469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,
807547484,7485,7486,7487,7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,
807557499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,
807567514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,
807577529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,
807587544,42877L,7546,7547,7548,11363,7550,7551,7552,7553,7554,7555,7556,7557,
807597558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,
807607573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,
807617588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,
807627603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7616,7617,
807637618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,
807647633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,
807657648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,
807667663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7677,
807677678,7679,7680,7680,7682,7682,7684,7684,7686,7686,7688,7688,7690,7690,7692,
807687692,7694,7694,7696,7696,7698,7698,7700,7700,7702,7702,7704,7704,7706,7706,
807697708,7708,7710,7710,7712,7712,7714,7714,7716,7716,7718,7718,7720,7720,7722,
807707722,7724,7724,7726,7726,7728,7728,7730,7730,7732,7732,7734,7734,7736,7736,
807717738,7738,7740,7740,7742,7742,7744,7744,7746,7746,7748,7748,7750,7750,7752,
807727752,7754,7754,7756,7756,7758,7758,7760,7760,7762,7762,7764,7764,7766,7766,
807737768,7768,7770,7770,7772,7772,7774,7774,7776,7776,7778,7778,7780,7780,7782,
807747782,7784,7784,7786,7786,7788,7788,7790,7790,7792,7792,7794,7794,7796,7796,
807757798,7798,7800,7800,7802,7802,7804,7804,7806,7806,7808,7808,7810,7810,7812,
807767812,7814,7814,7816,7816,7818,7818,7820,7820,7822,7822,7824,7824,7826,7826,
807777828,7828,7830,7831,7832,7833,7834,7776,7836,7837,7838,7839,7840,7840,7842,
807787842,7844,7844,7846,7846,7848,7848,7850,7850,7852,7852,7854,7854,7856,7856,
807797858,7858,7860,7860,7862,7862,7864,7864,7866,7866,7868,7868,7870,7870,7872,
807807872,7874,7874,7876,7876,7878,7878,7880,7880,7882,7882,7884,7884,7886,7886,
807817888,7888,7890,7890,7892,7892,7894,7894,7896,7896,7898,7898,7900,7900,7902,
807827902,7904,7904,7906,7906,7908,7908,7910,7910,7912,7912,7914,7914,7916,7916,
807837918,7918,7920,7920,7922,7922,7924,7924,7926,7926,7928,7928,7930,7930,7932,
807847932,7934,7934,7944,7945,7946,7947,7948,7949,7950,7951,7944,7945,7946,7947,
807857948,7949,7950,7951,7960,7961,7962,7963,7964,7965,7958,7959,7960,7961,7962,
807867963,7964,7965,7966,7967,7976,7977,7978,7979,7980,7981,7982,7983,7976,7977,
807877978,7979,7980,7981,7982,7983,7992,7993,7994,7995,7996,7997,7998,7999,7992,
807887993,7994,7995,7996,7997,7998,7999,8008,8009,8010,8011,8012,8013,8006,8007,
807898008,8009,8010,8011,8012,8013,8014,8015,8016,8025,8018,8027,8020,8029,8022,
807908031,8024,8025,8026,8027,8028,8029,8030,8031,8040,8041,8042,8043,8044,8045,
807918046,8047,8040,8041,8042,8043,8044,8045,8046,8047,8122,8123,8136,8137,8138,
807928139,8154,8155,8184,8185,8170,8171,8186,8187,8062,8063,8064,8065,8066,8067,
807938068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080,8081,8082,
807948083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,
807958098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,8120,
807968121,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,921,8127,
807978128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,
807988143,8152,8153,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,
807998158,8159,8168,8169,8162,8163,8164,8172,8166,8167,8168,8169,8170,8171,8172,
808008173,8174,8175,8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,
808018188,8189,8190,8191,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,
808028203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,
808038218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229,8230,8231,8232,
808048233,8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245,8246,8247,
808058248,8249,8250,8251,8252,8253,8254,8255,8256,8257,8258,8259,8260,8261,8262,
808068263,8264,8265,8266,8267,8268,8269,8270,8271,8272,8273,8274,8275,8276,8277,
808078278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,8290,8291,8292,
808088293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,
808098308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322,
808108323,8324,8325,8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337,
808118338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,
808128353,8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,
808138368,8369,8370,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382,
808148383,8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,
808158398,8399,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,
808168413,8414,8415,8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,
808178428,8429,8430,8431,8432,8433,8434,8435,8436,8437,8438,8439,8440,8441,8442,
808188443,8444,8445,8446,8447,8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,
808198458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8468,8469,8470,8471,8472,
808208473,8474,8475,8476,8477,8478,8479,8480,8481,8482,8483,8484,8485,8486,8487,
808218488,8489,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,
808228503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517,
808238518,8519,8520,8521,8522,8523,8524,8525,8498,8527,8528,8529,8530,8531,8532,
808248533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,
808258548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8544,8545,8546,
808268547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8576,8577,
808278578,8579,8579,8581,8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,8592,
808288593,8594,8595,8596,8597,8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,
808298608,8609,8610,8611,8612,8613,8614,8615,8616,8617,8618,8619,8620,8621,8622,
808308623,8624,8625,8626,8627,8628,8629,8630,8631,8632,8633,8634,8635,8636,8637,
808318638,8639,8640,8641,8642,8643,8644,8645,8646,8647,8648,8649,8650,8651,8652,
808328653,8654,8655,8656,8657,8658,8659,8660,8661,8662,8663,8664,8665,8666,8667,
808338668,8669,8670,8671,8672,8673,8674,8675,8676,8677,8678,8679,8680,8681,8682,
808348683,8684,8685,8686,8687,8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,
808358698,8699,8700,8701,8702,8703,8704,8705,8706,8707,8708,8709,8710,8711,8712,
808368713,8714,8715,8716,8717,8718,8719,8720,8721,8722,8723,8724,8725,8726,8727,
808378728,8729,8730,8731,8732,8733,8734,8735,8736,8737,8738,8739,8740,8741,8742,
808388743,8744,8745,8746,8747,8748,8749,8750,8751,8752,8753,8754,8755,8756,8757,
808398758,8759,8760,8761,8762,8763,8764,8765,8766,8767,8768,8769,8770,8771,8772,
808408773,8774,8775,8776,8777,8778,8779,8780,8781,8782,8783,8784,8785,8786,8787,
808418788,8789,8790,8791,8792,8793,8794,8795,8796,8797,8798,8799,8800,8801,8802,
808428803,8804,8805,8806,8807,8808,8809,8810,8811,8812,8813,8814,8815,8816,8817,
808438818,8819,8820,8821,8822,8823,8824,8825,8826,8827,8828,8829,8830,8831,8832,
808448833,8834,8835,8836,8837,8838,8839,8840,8841,8842,8843,8844,8845,8846,8847,
808458848,8849,8850,8851,8852,8853,8854,8855,8856,8857,8858,8859,8860,8861,8862,
808468863,8864,8865,8866,8867,8868,8869,8870,8871,8872,8873,8874,8875,8876,8877,
808478878,8879,8880,8881,8882,8883,8884,8885,8886,8887,8888,8889,8890,8891,8892,
808488893,8894,8895,8896,8897,8898,8899,8900,8901,8902,8903,8904,8905,8906,8907,
808498908,8909,8910,8911,8912,8913,8914,8915,8916,8917,8918,8919,8920,8921,8922,
808508923,8924,8925,8926,8927,8928,8929,8930,8931,8932,8933,8934,8935,8936,8937,
808518938,8939,8940,8941,8942,8943,8944,8945,8946,8947,8948,8949,8950,8951,8952,
808528953,8954,8955,8956,8957,8958,8959,8960,8961,8962,8963,8964,8965,8966,8967,
808538968,8969,8970,8971,8972,8973,8974,8975,8976,8977,8978,8979,8980,8981,8982,
808548983,8984,8985,8986,8987,8988,8989,8990,8991,8992,8993,8994,8995,8996,8997,
808558998,8999,9000,9001,9002,9003,9004,9005,9006,9007,9008,9009,9010,9011,9012,
808569013,9014,9015,9016,9017,9018,9019,9020,9021,9022,9023,9024,9025,9026,9027,
808579028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039,9040,9041,9042,
808589043,9044,9045,9046,9047,9048,9049,9050,9051,9052,9053,9054,9055,9056,9057,
808599058,9059,9060,9061,9062,9063,9064,9065,9066,9067,9068,9069,9070,9071,9072,
808609073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085,9086,9087,
808619088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9101,9102,
808629103,9104,9105,9106,9107,9108,9109,9110,9111,9112,9113,9114,9115,9116,9117,
808639118,9119,9120,9121,9122,9123,9124,9125,9126,9127,9128,9129,9130,9131,9132,
808649133,9134,9135,9136,9137,9138,9139,9140,9141,9142,9143,9144,9145,9146,9147,
808659148,9149,9150,9151,9152,9153,9154,9155,9156,9157,9158,9159,9160,9161,9162,
808669163,9164,9165,9166,9167,9168,9169,9170,9171,9172,9173,9174,9175,9176,9177,
808679178,9179,9180,9181,9182,9183,9184,9185,9186,9187,9188,9189,9190,9191,9192,
808689193,9194,9195,9196,9197,9198,9199,9200,9201,9202,9203,9204,9205,9206,9207,
808699208,9209,9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,9221,9222,
808709223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,
808719238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9248,9249,9250,9251,9252,
808729253,9254,9255,9256,9257,9258,9259,9260,9261,9262,9263,9264,9265,9266,9267,
808739268,9269,9270,9271,9272,9273,9274,9275,9276,9277,9278,9279,9280,9281,9282,
808749283,9284,9285,9286,9287,9288,9289,9290,9291,9292,9293,9294,9295,9296,9297,
808759298,9299,9300,9301,9302,9303,9304,9305,9306,9307,9308,9309,9310,9311,9312,
808769313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,
808779328,9329,9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,
808789343,9344,9345,9346,9347,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,
808799358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9372,
808809373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,
808819388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,
808829403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,
808839418,9419,9420,9421,9422,9423,9398,9399,9400,9401,9402,9403,9404,9405,9406,
808849407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,
808859422,9423,9450,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461,9462,
808869463,9464,9465,9466,9467,9468,9469,9470,9471,9472,9473,9474,9475,9476,9477,
808879478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,
808889493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,
808899508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,
808909523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,
808919538,9539,9540,9541,9542,9543,9544,9545,9546,9547,9548,9549,9550,9551,9552,
808929553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,
808939568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,
808949583,9584,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,
808959598,9599,9600,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,
808969613,9614,9615,9616,9617,9618,9619,9620,9621,9622,9623,9624,9625,9626,9627,
808979628,9629,9630,9631,9632,9633,9634,9635,9636,9637,9638,9639,9640,9641,9642,
808989643,9644,9645,9646,9647,9648,9649,9650,9651,9652,9653,9654,9655,9656,9657,
808999658,9659,9660,9661,9662,9663,9664,9665,9666,9667,9668,9669,9670,9671,9672,
809009673,9674,9675,9676,9677,9678,9679,9680,9681,9682,9683,9684,9685,9686,9687,
809019688,9689,9690,9691,9692,9693,9694,9695,9696,9697,9698,9699,9700,9701,9702,
809029703,9704,9705,9706,9707,9708,9709,9710,9711,9712,9713,9714,9715,9716,9717,
809039718,9719,9720,9721,9722,9723,9724,9725,9726,9727,9728,9729,9730,9731,9732,
809049733,9734,9735,9736,9737,9738,9739,9740,9741,9742,9743,9744,9745,9746,9747,
809059748,9749,9750,9751,9752,9753,9754,9755,9756,9757,9758,9759,9760,9761,9762,
809069763,9764,9765,9766,9767,9768,9769,9770,9771,9772,9773,9774,9775,9776,9777,
809079778,9779,9780,9781,9782,9783,9784,9785,9786,9787,9788,9789,9790,9791,9792,
809089793,9794,9795,9796,9797,9798,9799,9800,9801,9802,9803,9804,9805,9806,9807,
809099808,9809,9810,9811,9812,9813,9814,9815,9816,9817,9818,9819,9820,9821,9822,
809109823,9824,9825,9826,9827,9828,9829,9830,9831,9832,9833,9834,9835,9836,9837,
809119838,9839,9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,
809129853,9854,9855,9856,9857,9858,9859,9860,9861,9862,9863,9864,9865,9866,9867,
809139868,9869,9870,9871,9872,9873,9874,9875,9876,9877,9878,9879,9880,9881,9882,
809149883,9884,9885,9886,9887,9888,9889,9890,9891,9892,9893,9894,9895,9896,9897,
809159898,9899,9900,9901,9902,9903,9904,9905,9906,9907,9908,9909,9910,9911,9912,
809169913,9914,9915,9916,9917,9918,9919,9920,9921,9922,9923,9924,9925,9926,9927,
809179928,9929,9930,9931,9932,9933,9934,9935,9936,9937,9938,9939,9940,9941,9942,
809189943,9944,9945,9946,9947,9948,9949,9950,9951,9952,9953,9954,9955,9956,9957,
809199958,9959,9960,9961,9962,9963,9964,9965,9966,9967,9968,9969,9970,9971,9972,
809209973,9974,9975,9976,9977,9978,9979,9980,9981,9982,9983,9984,9985,9986,9987,
809219988,9989,9990,9991,9992,9993,9994,9995,9996,9997,9998,9999,10000,10001,
8092210002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,
8092310014,10015,10016,10017,10018,10019,10020,10021,10022,10023,10024,10025,
8092410026,10027,10028,10029,10030,10031,10032,10033,10034,10035,10036,10037,
8092510038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,10049,
8092610050,10051,10052,10053,10054,10055,10056,10057,10058,10059,10060,10061,
8092710062,10063,10064,10065,10066,10067,10068,10069,10070,10071,10072,10073,
8092810074,10075,10076,10077,10078,10079,10080,10081,10082,10083,10084,10085,
8092910086,10087,10088,10089,10090,10091,10092,10093,10094,10095,10096,10097,
8093010098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,
8093110110,10111,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,
8093210122,10123,10124,10125,10126,10127,10128,10129,10130,10131,10132,10133,
8093310134,10135,10136,10137,10138,10139,10140,10141,10142,10143,10144,10145,
8093410146,10147,10148,10149,10150,10151,10152,10153,10154,10155,10156,10157,
8093510158,10159,10160,10161,10162,10163,10164,10165,10166,10167,10168,10169,
8093610170,10171,10172,10173,10174,10175,10176,10177,10178,10179,10180,10181,
8093710182,10183,10184,10185,10186,10187,10188,10189,10190,10191,10192,10193,
8093810194,10195,10196,10197,10198,10199,10200,10201,10202,10203,10204,10205,
8093910206,10207,10208,10209,10210,10211,10212,10213,10214,10215,10216,10217,
8094010218,10219,10220,10221,10222,10223,10224,10225,10226,10227,10228,10229,
8094110230,10231,10232,10233,10234,10235,10236,10237,10238,10239,10240,10241,
8094210242,10243,10244,10245,10246,10247,10248,10249,10250,10251,10252,10253,
8094310254,10255,10256,10257,10258,10259,10260,10261,10262,10263,10264,10265,
8094410266,10267,10268,10269,10270,10271,10272,10273,10274,10275,10276,10277,
8094510278,10279,10280,10281,10282,10283,10284,10285,10286,10287,10288,10289,
8094610290,10291,10292,10293,10294,10295,10296,10297,10298,10299,10300,10301,
8094710302,10303,10304,10305,10306,10307,10308,10309,10310,10311,10312,10313,
8094810314,10315,10316,10317,10318,10319,10320,10321,10322,10323,10324,10325,
8094910326,10327,10328,10329,10330,10331,10332,10333,10334,10335,10336,10337,
8095010338,10339,10340,10341,10342,10343,10344,10345,10346,10347,10348,10349,
8095110350,10351,10352,10353,10354,10355,10356,10357,10358,10359,10360,10361,
8095210362,10363,10364,10365,10366,10367,10368,10369,10370,10371,10372,10373,
8095310374,10375,10376,10377,10378,10379,10380,10381,10382,10383,10384,10385,
8095410386,10387,10388,10389,10390,10391,10392,10393,10394,10395,10396,10397,
8095510398,10399,10400,10401,10402,10403,10404,10405,10406,10407,10408,10409,
8095610410,10411,10412,10413,10414,10415,10416,10417,10418,10419,10420,10421,
8095710422,10423,10424,10425,10426,10427,10428,10429,10430,10431,10432,10433,
8095810434,10435,10436,10437,10438,10439,10440,10441,10442,10443,10444,10445,
8095910446,10447,10448,10449,10450,10451,10452,10453,10454,10455,10456,10457,
8096010458,10459,10460,10461,10462,10463,10464,10465,10466,10467,10468,10469,
8096110470,10471,10472,10473,10474,10475,10476,10477,10478,10479,10480,10481,
8096210482,10483,10484,10485,10486,10487,10488,10489,10490,10491,10492,10493,
8096310494,10495,10496,10497,10498,10499,10500,10501,10502,10503,10504,10505,
8096410506,10507,10508,10509,10510,10511,10512,10513,10514,10515,10516,10517,
8096510518,10519,10520,10521,10522,10523,10524,10525,10526,10527,10528,10529,
8096610530,10531,10532,10533,10534,10535,10536,10537,10538,10539,10540,10541,
8096710542,10543,10544,10545,10546,10547,10548,10549,10550,10551,10552,10553,
8096810554,10555,10556,10557,10558,10559,10560,10561,10562,10563,10564,10565,
8096910566,10567,10568,10569,10570,10571,10572,10573,10574,10575,10576,10577,
8097010578,10579,10580,10581,10582,10583,10584,10585,10586,10587,10588,10589,
8097110590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,
8097210602,10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,
8097310614,10615,10616,10617,10618,10619,10620,10621,10622,10623,10624,10625,
8097410626,10627,10628,10629,10630,10631,10632,10633,10634,10635,10636,10637,
8097510638,10639,10640,10641,10642,10643,10644,10645,10646,10647,10648,10649,
8097610650,10651,10652,10653,10654,10655,10656,10657,10658,10659,10660,10661,
8097710662,10663,10664,10665,10666,10667,10668,10669,10670,10671,10672,10673,
8097810674,10675,10676,10677,10678,10679,10680,10681,10682,10683,10684,10685,
8097910686,10687,10688,10689,10690,10691,10692,10693,10694,10695,10696,10697,
8098010698,10699,10700,10701,10702,10703,10704,10705,10706,10707,10708,10709,
8098110710,10711,10712,10713,10714,10715,10716,10717,10718,10719,10720,10721,
8098210722,10723,10724,10725,10726,10727,10728,10729,10730,10731,10732,10733,
8098310734,10735,10736,10737,10738,10739,10740,10741,10742,10743,10744,10745,
8098410746,10747,10748,10749,10750,10751,10752,10753,10754,10755,10756,10757,
8098510758,10759,10760,10761,10762,10763,10764,10765,10766,10767,10768,10769,
8098610770,10771,10772,10773,10774,10775,10776,10777,10778,10779,10780,10781,
8098710782,10783,10784,10785,10786,10787,10788,10789,10790,10791,10792,10793,
8098810794,10795,10796,10797,10798,10799,10800,10801,10802,10803,10804,10805,
8098910806,10807,10808,10809,10810,10811,10812,10813,10814,10815,10816,10817,
8099010818,10819,10820,10821,10822,10823,10824,10825,10826,10827,10828,10829,
8099110830,10831,10832,10833,10834,10835,10836,10837,10838,10839,10840,10841,
8099210842,10843,10844,10845,10846,10847,10848,10849,10850,10851,10852,10853,
8099310854,10855,10856,10857,10858,10859,10860,10861,10862,10863,10864,10865,
8099410866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876,10877,
8099510878,10879,10880,10881,10882,10883,10884,10885,10886,10887,10888,10889,
8099610890,10891,10892,10893,10894,10895,10896,10897,10898,10899,10900,10901,
8099710902,10903,10904,10905,10906,10907,10908,10909,10910,10911,10912,10913,
8099810914,10915,10916,10917,10918,10919,10920,10921,10922,10923,10924,10925,
8099910926,10927,10928,10929,10930,10931,10932,10933,10934,10935,10936,10937,
8100010938,10939,10940,10941,10942,10943,10944,10945,10946,10947,10948,10949,
8100110950,10951,10952,10953,10954,10955,10956,10957,10958,10959,10960,10961,
8100210962,10963,10964,10965,10966,10967,10968,10969,10970,10971,10972,10973,
8100310974,10975,10976,10977,10978,10979,10980,10981,10982,10983,10984,10985,
8100410986,10987,10988,10989,10990,10991,10992,10993,10994,10995,10996,10997,
8100510998,10999,11000,11001,11002,11003,11004,11005,11006,11007,11008,11009,
8100611010,11011,11012,11013,11014,11015,11016,11017,11018,11019,11020,11021,
8100711022,11023,11024,11025,11026,11027,11028,11029,11030,11031,11032,11033,
8100811034,11035,11036,11037,11038,11039,11040,11041,11042,11043,11044,11045,
8100911046,11047,11048,11049,11050,11051,11052,11053,11054,11055,11056,11057,
8101011058,11059,11060,11061,11062,11063,11064,11065,11066,11067,11068,11069,
8101111070,11071,11072,11073,11074,11075,11076,11077,11078,11079,11080,11081,
8101211082,11083,11084,11085,11086,11087,11088,11089,11090,11091,11092,11093,
8101311094,11095,11096,11097,11098,11099,11100,11101,11102,11103,11104,11105,
8101411106,11107,11108,11109,11110,11111,11112,11113,11114,11115,11116,11117,
8101511118,11119,11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,
8101611130,11131,11132,11133,11134,11135,11136,11137,11138,11139,11140,11141,
8101711142,11143,11144,11145,11146,11147,11148,11149,11150,11151,11152,11153,
8101811154,11155,11156,11157,11158,11159,11160,11161,11162,11163,11164,11165,
8101911166,11167,11168,11169,11170,11171,11172,11173,11174,11175,11176,11177,
8102011178,11179,11180,11181,11182,11183,11184,11185,11186,11187,11188,11189,
8102111190,11191,11192,11193,11194,11195,11196,11197,11198,11199,11200,11201,
8102211202,11203,11204,11205,11206,11207,11208,11209,11210,11211,11212,11213,
8102311214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225,
8102411226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,
8102511238,11239,11240,11241,11242,11243,11244,11245,11246,11247,11248,11249,
8102611250,11251,11252,11253,11254,11255,11256,11257,11258,11259,11260,11261,
8102711262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
8102811274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
8102911286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
8103011298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
8103111310,11311,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
8103211274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
8103311286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
8103411298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
8103511310,11359,11360,11360,11362,11363,11364,570,574,11367,11367,11369,11369,
8103611371,11371,11373,11374,11375,11376,11377,11378,11378,11380,11381,11381,
8103711383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11392,11394,
8103811394,11396,11396,11398,11398,11400,11400,11402,11402,11404,11404,11406,
8103911406,11408,11408,11410,11410,11412,11412,11414,11414,11416,11416,11418,
8104011418,11420,11420,11422,11422,11424,11424,11426,11426,11428,11428,11430,
8104111430,11432,11432,11434,11434,11436,11436,11438,11438,11440,11440,11442,
8104211442,11444,11444,11446,11446,11448,11448,11450,11450,11452,11452,11454,
8104311454,11456,11456,11458,11458,11460,11460,11462,11462,11464,11464,11466,
8104411466,11468,11468,11470,11470,11472,11472,11474,11474,11476,11476,11478,
8104511478,11480,11480,11482,11482,11484,11484,11486,11486,11488,11488,11490,
8104611490,11492,11493,11494,11495,11496,11497,11498,11499,11499,11501,11501,
8104711503,11504,11505,11506,11507,11508,11509,11510,11511,11512,11513,11514,
8104811515,11516,11517,11518,11519,4256,4257,4258,4259,4260,4261,4262,4263,4264,
810494265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,
810504280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,
8105111558,11559,11560,11561,11562,11563,11564,11565,11566,11567,11568,11569,
8105211570,11571,11572,11573,11574,11575,11576,11577,11578,11579,11580,11581,
8105311582,11583,11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,
8105411594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,11605,
8105511606,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,
8105611618,11619,11620,11621,11622,11623,11624,11625,11626,11627,11628,11629,
8105711630,11631,11632,11633,11634,11635,11636,11637,11638,11639,11640,11641,
8105811642,11643,11644,11645,11646,11647,11648,11649,11650,11651,11652,11653,
8105911654,11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,
8106011666,11667,11668,11669,11670,11671,11672,11673,11674,11675,11676,11677,
8106111678,11679,11680,11681,11682,11683,11684,11685,11686,11687,11688,11689,
8106211690,11691,11692,11693,11694,11695,11696,11697,11698,11699,11700,11701,
8106311702,11703,11704,11705,11706,11707,11708,11709,11710,11711,11712,11713,
8106411714,11715,11716,11717,11718,11719,11720,11721,11722,11723,11724,11725,
8106511726,11727,11728,11729,11730,11731,11732,11733,11734,11735,11736,11737,
8106611738,11739,11740,11741,11742,11743,11744,11745,11746,11747,11748,11749,
8106711750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,
8106811762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,
8106911774,11775,11776,11777,11778,11779,11780,11781,11782,11783,11784,11785,
8107011786,11787,11788,11789,11790,11791,11792,11793,11794,11795,11796,11797,
8107111798,11799,11800,11801,11802,11803,11804,11805,11806,11807,11808,11809,
8107211810,11811,11812,11813,11814,11815,11816,11817,11818,11819,11820,11821,
8107311822,11823,11824,11825,11826,11827,11828,11829,11830,11831,11832,11833,
8107411834,11835,11836,11837,11838,11839,11840,11841,11842,11843,11844,11845,
8107511846,11847,11848,11849,11850,11851,11852,11853,11854,11855,11856,11857,
8107611858,11859,11860,11861,11862,11863,11864,11865,11866,11867,11868,11869,
8107711870,11871,11872,11873,11874,11875,11876,11877,11878,11879,11880,11881,
8107811882,11883,11884,11885,11886,11887,11888,11889,11890,11891,11892,11893,
8107911894,11895,11896,11897,11898,11899,11900,11901,11902,11903,11904,11905,
8108011906,11907,11908,11909,11910,11911,11912,11913,11914,11915,11916,11917,
8108111918,11919,11920,11921,11922,11923,11924,11925,11926,11927,11928,11929,
8108211930,11931,11932,11933,11934,11935,11936,11937,11938,11939,11940,11941,
8108311942,11943,11944,11945,11946,11947,11948,11949,11950,11951,11952,11953,
8108411954,11955,11956,11957,11958,11959,11960,11961,11962,11963,11964,11965,
8108511966,11967,11968,11969,11970,11971,11972,11973,11974,11975,11976,11977,
8108611978,11979,11980,11981,11982,11983,11984,11985,11986,11987,11988,11989,
8108711990,11991,11992,11993,11994,11995,11996,11997,11998,11999,12000,12001,
8108812002,12003,12004,12005,12006,12007,12008,12009,12010,12011,12012,12013,
8108912014,12015,12016,12017,12018,12019,12020,12021,12022,12023,12024,12025,
8109012026,12027,12028,12029,12030,12031,12032,12033,12034,12035,12036,12037,
8109112038,12039,12040,12041,12042,12043,12044,12045,12046,12047,12048,12049,
8109212050,12051,12052,12053,12054,12055,12056,12057,12058,12059,12060,12061,
8109312062,12063,12064,12065,12066,12067,12068,12069,12070,12071,12072,12073,
8109412074,12075,12076,12077,12078,12079,12080,12081,12082,12083,12084,12085,
8109512086,12087,12088,12089,12090,12091,12092,12093,12094,12095,12096,12097,
8109612098,12099,12100,12101,12102,12103,12104,12105,12106,12107,12108,12109,
8109712110,12111,12112,12113,12114,12115,12116,12117,12118,12119,12120,12121,
8109812122,12123,12124,12125,12126,12127,12128,12129,12130,12131,12132,12133,
8109912134,12135,12136,12137,12138,12139,12140,12141,12142,12143,12144,12145,
8110012146,12147,12148,12149,12150,12151,12152,12153,12154,12155,12156,12157,
8110112158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168,12169,
8110212170,12171,12172,12173,12174,12175,12176,12177,12178,12179,12180,12181,
8110312182,12183,12184,12185,12186,12187,12188,12189,12190,12191,12192,12193,
8110412194,12195,12196,12197,12198,12199,12200,12201,12202,12203,12204,12205,
8110512206,12207,12208,12209,12210,12211,12212,12213,12214,12215,12216,12217,
8110612218,12219,12220,12221,12222,12223,12224,12225,12226,12227,12228,12229,
8110712230,12231,12232,12233,12234,12235,12236,12237,12238,12239,12240,12241,
8110812242,12243,12244,12245,12246,12247,12248,12249,12250,12251,12252,12253,
8110912254,12255,12256,12257,12258,12259,12260,12261,12262,12263,12264,12265,
8111012266,12267,12268,12269,12270,12271,12272,12273,12274,12275,12276,12277,
8111112278,12279,12280,12281,12282,12283,12284,12285,12286,12287,12288,12289,
8111212290,12291,12292,12293,12294,12295,12296,12297,12298,12299,12300,12301,
8111312302,12303,12304,12305,12306,12307,12308,12309,12310,12311,12312,12313,
8111412314,12315,12316,12317,12318,12319,12320,12321,12322,12323,12324,12325,
8111512326,12327,12328,12329,12330,12331,12332,12333,12334,12335,12336,12337,
8111612338,12339,12340,12341,12342,12343,12344,12345,12346,12347,12348,12349,
8111712350,12351,12352,12353,12354,12355,12356,12357,12358,12359,12360,12361,
8111812362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,
8111912374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,
8112012386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,
8112112398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,
8112212410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,
8112312422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,
8112412434,12435,12436,12437,12438,12439,12440,12441,12442,12443,12444,12445,
8112512446,12447,12448,12449,12450,12451,12452,12453,12454,12455,12456,12457,
8112612458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,
8112712470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,
8112812482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,
8112912494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,
8113012506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,
8113112518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,
8113212530,12531,12532,12533,12534,12535,12536,12537,12538,12539,12540,12541,
8113312542,12543,12544,12545,12546,12547,12548,12549,12550,12551,12552,12553,
8113412554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,
8113512566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,
8113612578,12579,12580,12581,12582,12583,12584,12585,12586,12587,12588,12589,
8113712590,12591,12592,12593,12594,12595,12596,12597,12598,12599,12600,12601,
8113812602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,
8113912614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,
8114012626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,
8114112638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,
8114212650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,
8114312662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,
8114412674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,
8114512686,12687,12688,12689,12690,12691,12692,12693,12694,12695,12696,12697,
8114612698,12699,12700,12701,12702,12703,12704,12705,12706,12707,12708,12709,
8114712710,12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,
8114812722,12723,12724,12725,12726,12727,12728,12729,12730,12731,12732,12733,
8114912734,12735,12736,12737,12738,12739,12740,12741,12742,12743,12744,12745,
8115012746,12747,12748,12749,12750,12751,12752,12753,12754,12755,12756,12757,
8115112758,12759,12760,12761,12762,12763,12764,12765,12766,12767,12768,12769,
8115212770,12771,12772,12773,12774,12775,12776,12777,12778,12779,12780,12781,
8115312782,12783,12784,12785,12786,12787,12788,12789,12790,12791,12792,12793,
8115412794,12795,12796,12797,12798,12799,12800,12801,12802,12803,12804,12805,
8115512806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,
8115612818,12819,12820,12821,12822,12823,12824,12825,12826,12827,12828,12829,
8115712830,12831,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,
8115812842,12843,12844,12845,12846,12847,12848,12849,12850,12851,12852,12853,
8115912854,12855,12856,12857,12858,12859,12860,12861,12862,12863,12864,12865,
8116012866,12867,12868,12869,12870,12871,12872,12873,12874,12875,12876,12877,
8116112878,12879,12880,12881,12882,12883,12884,12885,12886,12887,12888,12889,
8116212890,12891,12892,12893,12894,12895,12896,12897,12898,12899,12900,12901,
8116312902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,
8116412914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,
8116512926,12927,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,
8116612938,12939,12940,12941,12942,12943,12944,12945,12946,12947,12948,12949,
8116712950,12951,12952,12953,12954,12955,12956,12957,12958,12959,12960,12961,
8116812962,12963,12964,12965,12966,12967,12968,12969,12970,12971,12972,12973,
8116912974,12975,12976,12977,12978,12979,12980,12981,12982,12983,12984,12985,
8117012986,12987,12988,12989,12990,12991,12992,12993,12994,12995,12996,12997,
8117112998,12999,13000,13001,13002,13003,13004,13005,13006,13007,13008,13009,
8117213010,13011,13012,13013,13014,13015,13016,13017,13018,13019,13020,13021,
8117313022,13023,13024,13025,13026,13027,13028,13029,13030,13031,13032,13033,
8117413034,13035,13036,13037,13038,13039,13040,13041,13042,13043,13044,13045,
8117513046,13047,13048,13049,13050,13051,13052,13053,13054,13055,13056,13057,
8117613058,13059,13060,13061,13062,13063,13064,13065,13066,13067,13068,13069,
8117713070,13071,13072,13073,13074,13075,13076,13077,13078,13079,13080,13081,
8117813082,13083,13084,13085,13086,13087,13088,13089,13090,13091,13092,13093,
8117913094,13095,13096,13097,13098,13099,13100,13101,13102,13103,13104,13105,
8118013106,13107,13108,13109,13110,13111,13112,13113,13114,13115,13116,13117,
8118113118,13119,13120,13121,13122,13123,13124,13125,13126,13127,13128,13129,
8118213130,13131,13132,13133,13134,13135,13136,13137,13138,13139,13140,13141,
8118313142,13143,13144,13145,13146,13147,13148,13149,13150,13151,13152,13153,
8118413154,13155,13156,13157,13158,13159,13160,13161,13162,13163,13164,13165,
8118513166,13167,13168,13169,13170,13171,13172,13173,13174,13175,13176,13177,
8118613178,13179,13180,13181,13182,13183,13184,13185,13186,13187,13188,13189,
8118713190,13191,13192,13193,13194,13195,13196,13197,13198,13199,13200,13201,
8118813202,13203,13204,13205,13206,13207,13208,13209,13210,13211,13212,13213,
8118913214,13215,13216,13217,13218,13219,13220,13221,13222,13223,13224,13225,
8119013226,13227,13228,13229,13230,13231,13232,13233,13234,13235,13236,13237,
8119113238,13239,13240,13241,13242,13243,13244,13245,13246,13247,13248,13249,
8119213250,13251,13252,13253,13254,13255,13256,13257,13258,13259,13260,13261,
8119313262,13263,13264,13265,13266,13267,13268,13269,13270,13271,13272,13273,
8119413274,13275,13276,13277,13278,13279,13280,13281,13282,13283,13284,13285,
8119513286,13287,13288,13289,13290,13291,13292,13293,13294,13295,13296,13297,
8119613298,13299,13300,13301,13302,13303,13304,13305,13306,13307,13308,13309,
8119713310,13311,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321,
8119813322,13323,13324,13325,13326,13327,13328,13329,13330,13331,13332,13333,
8119913334,13335,13336,13337,13338,13339,13340,13341,13342,13343,13344,13345,
8120013346,13347,13348,13349,13350,13351,13352,13353,13354,13355,13356,13357,
8120113358,13359,13360,13361,13362,13363,13364,13365,13366,13367,13368,13369,
8120213370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,
8120313382,13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,
8120413394,13395,13396,13397,13398,13399,13400,13401,13402,13403,13404,13405,
8120513406,13407,13408,13409,13410,13411,13412,13413,13414,13415,13416,13417,
8120613418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,
8120713430,13431,13432,13433,13434,13435,13436,13437,13438,13439,13440,13441,
8120813442,13443,13444,13445,13446,13447,13448,13449,13450,13451,13452,13453,
8120913454,13455,13456,13457,13458,13459,13460,13461,13462,13463,13464,13465,
8121013466,13467,13468,13469,13470,13471,13472,13473,13474,13475,13476,13477,
8121113478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,
8121213490,13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,
8121313502,13503,13504,13505,13506,13507,13508,13509,13510,13511,13512,13513,
8121413514,13515,13516,13517,13518,13519,13520,13521,13522,13523,13524,13525,
8121513526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,
8121613538,13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,
8121713550,13551,13552,13553,13554,13555,13556,13557,13558,13559,13560,13561,
8121813562,13563,13564,13565,13566,13567,13568,13569,13570,13571,13572,13573,
8121913574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,
8122013586,13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,
8122113598,13599,13600,13601,13602,13603,13604,13605,13606,13607,13608,13609,
8122213610,13611,13612,13613,13614,13615,13616,13617,13618,13619,13620,13621,
8122313622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,
8122413634,13635,13636,13637,13638,13639,13640,13641,13642,13643,13644,13645,
8122513646,13647,13648,13649,13650,13651,13652,13653,13654,13655,13656,13657,
8122613658,13659,13660,13661,13662,13663,13664,13665,13666,13667,13668,13669,
8122713670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680,13681,
8122813682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,
8122913694,13695,13696,13697,13698,13699,13700,13701,13702,13703,13704,13705,
8123013706,13707,13708,13709,13710,13711,13712,13713,13714,13715,13716,13717,
8123113718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728,13729,
8123213730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,
8123313742,13743,13744,13745,13746,13747,13748,13749,13750,13751,13752,13753,
8123413754,13755,13756,13757,13758,13759,13760,13761,13762,13763,13764,13765,
8123513766,13767,13768,13769,13770,13771,13772,13773,13774,13775,13776,13777,
8123613778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,
8123713790,13791,13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,
8123813802,13803,13804,13805,13806,13807,13808,13809,13810,13811,13812,13813,
8123913814,13815,13816,13817,13818,13819,13820,13821,13822,13823,13824,13825,
8124013826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,
8124113838,13839,13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,
8124213850,13851,13852,13853,13854,13855,13856,13857,13858,13859,13860,13861,
8124313862,13863,13864,13865,13866,13867,13868,13869,13870,13871,13872,13873,
8124413874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,
8124513886,13887,13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,
8124613898,13899,13900,13901,13902,13903,13904,13905,13906,13907,13908,13909,
8124713910,13911,13912,13913,13914,13915,13916,13917,13918,13919,13920,13921,
8124813922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,
8124913934,13935,13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,
8125013946,13947,13948,13949,13950,13951,13952,13953,13954,13955,13956,13957,
8125113958,13959,13960,13961,13962,13963,13964,13965,13966,13967,13968,13969,
8125213970,13971,13972,13973,13974,13975,13976,13977,13978,13979,13980,13981,
8125313982,13983,13984,13985,13986,13987,13988,13989,13990,13991,13992,13993,
8125413994,13995,13996,13997,13998,13999,14000,14001,14002,14003,14004,14005,
8125514006,14007,14008,14009,14010,14011,14012,14013,14014,14015,14016,14017,
8125614018,14019,14020,14021,14022,14023,14024,14025,14026,14027,14028,14029,
8125714030,14031,14032,14033,14034,14035,14036,14037,14038,14039,14040,14041,
8125814042,14043,14044,14045,14046,14047,14048,14049,14050,14051,14052,14053,
8125914054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,
8126014066,14067,14068,14069,14070,14071,14072,14073,14074,14075,14076,14077,
8126114078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,
8126214090,14091,14092,14093,14094,14095,14096,14097,14098,14099,14100,14101,
8126314102,14103,14104,14105,14106,14107,14108,14109,14110,14111,14112,14113,
8126414114,14115,14116,14117,14118,14119,14120,14121,14122,14123,14124,14125,
8126514126,14127,14128,14129,14130,14131,14132,14133,14134,14135,14136,14137,
8126614138,14139,14140,14141,14142,14143,14144,14145,14146,14147,14148,14149,
8126714150,14151,14152,14153,14154,14155,14156,14157,14158,14159,14160,14161,
8126814162,14163,14164,14165,14166,14167,14168,14169,14170,14171,14172,14173,
8126914174,14175,14176,14177,14178,14179,14180,14181,14182,14183,14184,14185,
8127014186,14187,14188,14189,14190,14191,14192,14193,14194,14195,14196,14197,
8127114198,14199,14200,14201,14202,14203,14204,14205,14206,14207,14208,14209,
8127214210,14211,14212,14213,14214,14215,14216,14217,14218,14219,14220,14221,
8127314222,14223,14224,14225,14226,14227,14228,14229,14230,14231,14232,14233,
8127414234,14235,14236,14237,14238,14239,14240,14241,14242,14243,14244,14245,
8127514246,14247,14248,14249,14250,14251,14252,14253,14254,14255,14256,14257,
8127614258,14259,14260,14261,14262,14263,14264,14265,14266,14267,14268,14269,
8127714270,14271,14272,14273,14274,14275,14276,14277,14278,14279,14280,14281,
8127814282,14283,14284,14285,14286,14287,14288,14289,14290,14291,14292,14293,
8127914294,14295,14296,14297,14298,14299,14300,14301,14302,14303,14304,14305,
8128014306,14307,14308,14309,14310,14311,14312,14313,14314,14315,14316,14317,
8128114318,14319,14320,14321,14322,14323,14324,14325,14326,14327,14328,14329,
8128214330,14331,14332,14333,14334,14335,14336,14337,14338,14339,14340,14341,
8128314342,14343,14344,14345,14346,14347,14348,14349,14350,14351,14352,14353,
8128414354,14355,14356,14357,14358,14359,14360,14361,14362,14363,14364,14365,
8128514366,14367,14368,14369,14370,14371,14372,14373,14374,14375,14376,14377,
8128614378,14379,14380,14381,14382,14383,14384,14385,14386,14387,14388,14389,
8128714390,14391,14392,14393,14394,14395,14396,14397,14398,14399,14400,14401,
8128814402,14403,14404,14405,14406,14407,14408,14409,14410,14411,14412,14413,
8128914414,14415,14416,14417,14418,14419,14420,14421,14422,14423,14424,14425,
8129014426,14427,14428,14429,14430,14431,14432,14433,14434,14435,14436,14437,
8129114438,14439,14440,14441,14442,14443,14444,14445,14446,14447,14448,14449,
8129214450,14451,14452,14453,14454,14455,14456,14457,14458,14459,14460,14461,
8129314462,14463,14464,14465,14466,14467,14468,14469,14470,14471,14472,14473,
8129414474,14475,14476,14477,14478,14479,14480,14481,14482,14483,14484,14485,
8129514486,14487,14488,14489,14490,14491,14492,14493,14494,14495,14496,14497,
8129614498,14499,14500,14501,14502,14503,14504,14505,14506,14507,14508,14509,
8129714510,14511,14512,14513,14514,14515,14516,14517,14518,14519,14520,14521,
8129814522,14523,14524,14525,14526,14527,14528,14529,14530,14531,14532,14533,
8129914534,14535,14536,14537,14538,14539,14540,14541,14542,14543,14544,14545,
8130014546,14547,14548,14549,14550,14551,14552,14553,14554,14555,14556,14557,
8130114558,14559,14560,14561,14562,14563,14564,14565,14566,14567,14568,14569,
8130214570,14571,14572,14573,14574,14575,14576,14577,14578,14579,14580,14581,
8130314582,14583,14584,14585,14586,14587,14588,14589,14590,14591,14592,14593,
8130414594,14595,14596,14597,14598,14599,14600,14601,14602,14603,14604,14605,
8130514606,14607,14608,14609,14610,14611,14612,14613,14614,14615,14616,14617,
8130614618,14619,14620,14621,14622,14623,14624,14625,14626,14627,14628,14629,
8130714630,14631,14632,14633,14634,14635,14636,14637,14638,14639,14640,14641,
8130814642,14643,14644,14645,14646,14647,14648,14649,14650,14651,14652,14653,
8130914654,14655,14656,14657,14658,14659,14660,14661,14662,14663,14664,14665,
8131014666,14667,14668,14669,14670,14671,14672,14673,14674,14675,14676,14677,
8131114678,14679,14680,14681,14682,14683,14684,14685,14686,14687,14688,14689,
8131214690,14691,14692,14693,14694,14695,14696,14697,14698,14699,14700,14701,
8131314702,14703,14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,
8131414714,14715,14716,14717,14718,14719,14720,14721,14722,14723,14724,14725,
8131514726,14727,14728,14729,14730,14731,14732,14733,14734,14735,14736,14737,
8131614738,14739,14740,14741,14742,14743,14744,14745,14746,14747,14748,14749,
8131714750,14751,14752,14753,14754,14755,14756,14757,14758,14759,14760,14761,
8131814762,14763,14764,14765,14766,14767,14768,14769,14770,14771,14772,14773,
8131914774,14775,14776,14777,14778,14779,14780,14781,14782,14783,14784,14785,
8132014786,14787,14788,14789,14790,14791,14792,14793,14794,14795,14796,14797,
8132114798,14799,14800,14801,14802,14803,14804,14805,14806,14807,14808,14809,
8132214810,14811,14812,14813,14814,14815,14816,14817,14818,14819,14820,14821,
8132314822,14823,14824,14825,14826,14827,14828,14829,14830,14831,14832,14833,
8132414834,14835,14836,14837,14838,14839,14840,14841,14842,14843,14844,14845,
8132514846,14847,14848,14849,14850,14851,14852,14853,14854,14855,14856,14857,
8132614858,14859,14860,14861,14862,14863,14864,14865,14866,14867,14868,14869,
8132714870,14871,14872,14873,14874,14875,14876,14877,14878,14879,14880,14881,
8132814882,14883,14884,14885,14886,14887,14888,14889,14890,14891,14892,14893,
8132914894,14895,14896,14897,14898,14899,14900,14901,14902,14903,14904,14905,
8133014906,14907,14908,14909,14910,14911,14912,14913,14914,14915,14916,14917,
8133114918,14919,14920,14921,14922,14923,14924,14925,14926,14927,14928,14929,
8133214930,14931,14932,14933,14934,14935,14936,14937,14938,14939,14940,14941,
8133314942,14943,14944,14945,14946,14947,14948,14949,14950,14951,14952,14953,
8133414954,14955,14956,14957,14958,14959,14960,14961,14962,14963,14964,14965,
8133514966,14967,14968,14969,14970,14971,14972,14973,14974,14975,14976,14977,
8133614978,14979,14980,14981,14982,14983,14984,14985,14986,14987,14988,14989,
8133714990,14991,14992,14993,14994,14995,14996,14997,14998,14999,15000,15001,
8133815002,15003,15004,15005,15006,15007,15008,15009,15010,15011,15012,15013,
8133915014,15015,15016,15017,15018,15019,15020,15021,15022,15023,15024,15025,
8134015026,15027,15028,15029,15030,15031,15032,15033,15034,15035,15036,15037,
8134115038,15039,15040,15041,15042,15043,15044,15045,15046,15047,15048,15049,
8134215050,15051,15052,15053,15054,15055,15056,15057,15058,15059,15060,15061,
8134315062,15063,15064,15065,15066,15067,15068,15069,15070,15071,15072,15073,
8134415074,15075,15076,15077,15078,15079,15080,15081,15082,15083,15084,15085,
8134515086,15087,15088,15089,15090,15091,15092,15093,15094,15095,15096,15097,
8134615098,15099,15100,15101,15102,15103,15104,15105,15106,15107,15108,15109,
8134715110,15111,15112,15113,15114,15115,15116,15117,15118,15119,15120,15121,
8134815122,15123,15124,15125,15126,15127,15128,15129,15130,15131,15132,15133,
8134915134,15135,15136,15137,15138,15139,15140,15141,15142,15143,15144,15145,
8135015146,15147,15148,15149,15150,15151,15152,15153,15154,15155,15156,15157,
8135115158,15159,15160,15161,15162,15163,15164,15165,15166,15167,15168,15169,
8135215170,15171,15172,15173,15174,15175,15176,15177,15178,15179,15180,15181,
8135315182,15183,15184,15185,15186,15187,15188,15189,15190,15191,15192,15193,
8135415194,15195,15196,15197,15198,15199,15200,15201,15202,15203,15204,15205,
8135515206,15207,15208,15209,15210,15211,15212,15213,15214,15215,15216,15217,
8135615218,15219,15220,15221,15222,15223,15224,15225,15226,15227,15228,15229,
8135715230,15231,15232,15233,15234,15235,15236,15237,15238,15239,15240,15241,
8135815242,15243,15244,15245,15246,15247,15248,15249,15250,15251,15252,15253,
8135915254,15255,15256,15257,15258,15259,15260,15261,15262,15263,15264,15265,
8136015266,15267,15268,15269,15270,15271,15272,15273,15274,15275,15276,15277,
8136115278,15279,15280,15281,15282,15283,15284,15285,15286,15287,15288,15289,
8136215290,15291,15292,15293,15294,15295,15296,15297,15298,15299,15300,15301,
8136315302,15303,15304,15305,15306,15307,15308,15309,15310,15311,15312,15313,
8136415314,15315,15316,15317,15318,15319,15320,15321,15322,15323,15324,15325,
8136515326,15327,15328,15329,15330,15331,15332,15333,15334,15335,15336,15337,
8136615338,15339,15340,15341,15342,15343,15344,15345,15346,15347,15348,15349,
8136715350,15351,15352,15353,15354,15355,15356,15357,15358,15359,15360,15361,
8136815362,15363,15364,15365,15366,15367,15368,15369,15370,15371,15372,15373,
8136915374,15375,15376,15377,15378,15379,15380,15381,15382,15383,15384,15385,
8137015386,15387,15388,15389,15390,15391,15392,15393,15394,15395,15396,15397,
8137115398,15399,15400,15401,15402,15403,15404,15405,15406,15407,15408,15409,
8137215410,15411,15412,15413,15414,15415,15416,15417,15418,15419,15420,15421,
8137315422,15423,15424,15425,15426,15427,15428,15429,15430,15431,15432,15433,
8137415434,15435,15436,15437,15438,15439,15440,15441,15442,15443,15444,15445,
8137515446,15447,15448,15449,15450,15451,15452,15453,15454,15455,15456,15457,
8137615458,15459,15460,15461,15462,15463,15464,15465,15466,15467,15468,15469,
8137715470,15471,15472,15473,15474,15475,15476,15477,15478,15479,15480,15481,
8137815482,15483,15484,15485,15486,15487,15488,15489,15490,15491,15492,15493,
8137915494,15495,15496,15497,15498,15499,15500,15501,15502,15503,15504,15505,
8138015506,15507,15508,15509,15510,15511,15512,15513,15514,15515,15516,15517,
8138115518,15519,15520,15521,15522,15523,15524,15525,15526,15527,15528,15529,
8138215530,15531,15532,15533,15534,15535,15536,15537,15538,15539,15540,15541,
8138315542,15543,15544,15545,15546,15547,15548,15549,15550,15551,15552,15553,
8138415554,15555,15556,15557,15558,15559,15560,15561,15562,15563,15564,15565,
8138515566,15567,15568,15569,15570,15571,15572,15573,15574,15575,15576,15577,
8138615578,15579,15580,15581,15582,15583,15584,15585,15586,15587,15588,15589,
8138715590,15591,15592,15593,15594,15595,15596,15597,15598,15599,15600,15601,
8138815602,15603,15604,15605,15606,15607,15608,15609,15610,15611,15612,15613,
8138915614,15615,15616,15617,15618,15619,15620,15621,15622,15623,15624,15625,
8139015626,15627,15628,15629,15630,15631,15632,15633,15634,15635,15636,15637,
8139115638,15639,15640,15641,15642,15643,15644,15645,15646,15647,15648,15649,
8139215650,15651,15652,15653,15654,15655,15656,15657,15658,15659,15660,15661,
8139315662,15663,15664,15665,15666,15667,15668,15669,15670,15671,15672,15673,
8139415674,15675,15676,15677,15678,15679,15680,15681,15682,15683,15684,15685,
8139515686,15687,15688,15689,15690,15691,15692,15693,15694,15695,15696,15697,
8139615698,15699,15700,15701,15702,15703,15704,15705,15706,15707,15708,15709,
8139715710,15711,15712,15713,15714,15715,15716,15717,15718,15719,15720,15721,
8139815722,15723,15724,15725,15726,15727,15728,15729,15730,15731,15732,15733,
8139915734,15735,15736,15737,15738,15739,15740,15741,15742,15743,15744,15745,
8140015746,15747,15748,15749,15750,15751,15752,15753,15754,15755,15756,15757,
8140115758,15759,15760,15761,15762,15763,15764,15765,15766,15767,15768,15769,
8140215770,15771,15772,15773,15774,15775,15776,15777,15778,15779,15780,15781,
8140315782,15783,15784,15785,15786,15787,15788,15789,15790,15791,15792,15793,
8140415794,15795,15796,15797,15798,15799,15800,15801,15802,15803,15804,15805,
8140515806,15807,15808,15809,15810,15811,15812,15813,15814,15815,15816,15817,
8140615818,15819,15820,15821,15822,15823,15824,15825,15826,15827,15828,15829,
8140715830,15831,15832,15833,15834,15835,15836,15837,15838,15839,15840,15841,
8140815842,15843,15844,15845,15846,15847,15848,15849,15850,15851,15852,15853,
8140915854,15855,15856,15857,15858,15859,15860,15861,15862,15863,15864,15865,
8141015866,15867,15868,15869,15870,15871,15872,15873,15874,15875,15876,15877,
8141115878,15879,15880,15881,15882,15883,15884,15885,15886,15887,15888,15889,
8141215890,15891,15892,15893,15894,15895,15896,15897,15898,15899,15900,15901,
8141315902,15903,15904,15905,15906,15907,15908,15909,15910,15911,15912,15913,
8141415914,15915,15916,15917,15918,15919,15920,15921,15922,15923,15924,15925,
8141515926,15927,15928,15929,15930,15931,15932,15933,15934,15935,15936,15937,
8141615938,15939,15940,15941,15942,15943,15944,15945,15946,15947,15948,15949,
8141715950,15951,15952,15953,15954,15955,15956,15957,15958,15959,15960,15961,
8141815962,15963,15964,15965,15966,15967,15968,15969,15970,15971,15972,15973,
8141915974,15975,15976,15977,15978,15979,15980,15981,15982,15983,15984,15985,
8142015986,15987,15988,15989,15990,15991,15992,15993,15994,15995,15996,15997,
8142115998,15999,16000,16001,16002,16003,16004,16005,16006,16007,16008,16009,
8142216010,16011,16012,16013,16014,16015,16016,16017,16018,16019,16020,16021,
8142316022,16023,16024,16025,16026,16027,16028,16029,16030,16031,16032,16033,
8142416034,16035,16036,16037,16038,16039,16040,16041,16042,16043,16044,16045,
8142516046,16047,16048,16049,16050,16051,16052,16053,16054,16055,16056,16057,
8142616058,16059,16060,16061,16062,16063,16064,16065,16066,16067,16068,16069,
8142716070,16071,16072,16073,16074,16075,16076,16077,16078,16079,16080,16081,
8142816082,16083,16084,16085,16086,16087,16088,16089,16090,16091,16092,16093,
8142916094,16095,16096,16097,16098,16099,16100,16101,16102,16103,16104,16105,
8143016106,16107,16108,16109,16110,16111,16112,16113,16114,16115,16116,16117,
8143116118,16119,16120,16121,16122,16123,16124,16125,16126,16127,16128,16129,
8143216130,16131,16132,16133,16134,16135,16136,16137,16138,16139,16140,16141,
8143316142,16143,16144,16145,16146,16147,16148,16149,16150,16151,16152,16153,
8143416154,16155,16156,16157,16158,16159,16160,16161,16162,16163,16164,16165,
8143516166,16167,16168,16169,16170,16171,16172,16173,16174,16175,16176,16177,
8143616178,16179,16180,16181,16182,16183,16184,16185,16186,16187,16188,16189,
8143716190,16191,16192,16193,16194,16195,16196,16197,16198,16199,16200,16201,
8143816202,16203,16204,16205,16206,16207,16208,16209,16210,16211,16212,16213,
8143916214,16215,16216,16217,16218,16219,16220,16221,16222,16223,16224,16225,
8144016226,16227,16228,16229,16230,16231,16232,16233,16234,16235,16236,16237,
8144116238,16239,16240,16241,16242,16243,16244,16245,16246,16247,16248,16249,
8144216250,16251,16252,16253,16254,16255,16256,16257,16258,16259,16260,16261,
8144316262,16263,16264,16265,16266,16267,16268,16269,16270,16271,16272,16273,
8144416274,16275,16276,16277,16278,16279,16280,16281,16282,16283,16284,16285,
8144516286,16287,16288,16289,16290,16291,16292,16293,16294,16295,16296,16297,
8144616298,16299,16300,16301,16302,16303,16304,16305,16306,16307,16308,16309,
8144716310,16311,16312,16313,16314,16315,16316,16317,16318,16319,16320,16321,
8144816322,16323,16324,16325,16326,16327,16328,16329,16330,16331,16332,16333,
8144916334,16335,16336,16337,16338,16339,16340,16341,16342,16343,16344,16345,
8145016346,16347,16348,16349,16350,16351,16352,16353,16354,16355,16356,16357,
8145116358,16359,16360,16361,16362,16363,16364,16365,16366,16367,16368,16369,
8145216370,16371,16372,16373,16374,16375,16376,16377,16378,16379,16380,16381,
8145316382,16383,16384,16385,16386,16387,16388,16389,16390,16391,16392,16393,
8145416394,16395,16396,16397,16398,16399,16400,16401,16402,16403,16404,16405,
8145516406,16407,16408,16409,16410,16411,16412,16413,16414,16415,16416,16417,
8145616418,16419,16420,16421,16422,16423,16424,16425,16426,16427,16428,16429,
8145716430,16431,16432,16433,16434,16435,16436,16437,16438,16439,16440,16441,
8145816442,16443,16444,16445,16446,16447,16448,16449,16450,16451,16452,16453,
8145916454,16455,16456,16457,16458,16459,16460,16461,16462,16463,16464,16465,
8146016466,16467,16468,16469,16470,16471,16472,16473,16474,16475,16476,16477,
8146116478,16479,16480,16481,16482,16483,16484,16485,16486,16487,16488,16489,
8146216490,16491,16492,16493,16494,16495,16496,16497,16498,16499,16500,16501,
8146316502,16503,16504,16505,16506,16507,16508,16509,16510,16511,16512,16513,
8146416514,16515,16516,16517,16518,16519,16520,16521,16522,16523,16524,16525,
8146516526,16527,16528,16529,16530,16531,16532,16533,16534,16535,16536,16537,
8146616538,16539,16540,16541,16542,16543,16544,16545,16546,16547,16548,16549,
8146716550,16551,16552,16553,16554,16555,16556,16557,16558,16559,16560,16561,
8146816562,16563,16564,16565,16566,16567,16568,16569,16570,16571,16572,16573,
8146916574,16575,16576,16577,16578,16579,16580,16581,16582,16583,16584,16585,
8147016586,16587,16588,16589,16590,16591,16592,16593,16594,16595,16596,16597,
8147116598,16599,16600,16601,16602,16603,16604,16605,16606,16607,16608,16609,
8147216610,16611,16612,16613,16614,16615,16616,16617,16618,16619,16620,16621,
8147316622,16623,16624,16625,16626,16627,16628,16629,16630,16631,16632,16633,
8147416634,16635,16636,16637,16638,16639,16640,16641,16642,16643,16644,16645,
8147516646,16647,16648,16649,16650,16651,16652,16653,16654,16655,16656,16657,
8147616658,16659,16660,16661,16662,16663,16664,16665,16666,16667,16668,16669,
8147716670,16671,16672,16673,16674,16675,16676,16677,16678,16679,16680,16681,
8147816682,16683,16684,16685,16686,16687,16688,16689,16690,16691,16692,16693,
8147916694,16695,16696,16697,16698,16699,16700,16701,16702,16703,16704,16705,
8148016706,16707,16708,16709,16710,16711,16712,16713,16714,16715,16716,16717,
8148116718,16719,16720,16721,16722,16723,16724,16725,16726,16727,16728,16729,
8148216730,16731,16732,16733,16734,16735,16736,16737,16738,16739,16740,16741,
8148316742,16743,16744,16745,16746,16747,16748,16749,16750,16751,16752,16753,
8148416754,16755,16756,16757,16758,16759,16760,16761,16762,16763,16764,16765,
8148516766,16767,16768,16769,16770,16771,16772,16773,16774,16775,16776,16777,
8148616778,16779,16780,16781,16782,16783,16784,16785,16786,16787,16788,16789,
8148716790,16791,16792,16793,16794,16795,16796,16797,16798,16799,16800,16801,
8148816802,16803,16804,16805,16806,16807,16808,16809,16810,16811,16812,16813,
8148916814,16815,16816,16817,16818,16819,16820,16821,16822,16823,16824,16825,
8149016826,16827,16828,16829,16830,16831,16832,16833,16834,16835,16836,16837,
8149116838,16839,16840,16841,16842,16843,16844,16845,16846,16847,16848,16849,
8149216850,16851,16852,16853,16854,16855,16856,16857,16858,16859,16860,16861,
8149316862,16863,16864,16865,16866,16867,16868,16869,16870,16871,16872,16873,
8149416874,16875,16876,16877,16878,16879,16880,16881,16882,16883,16884,16885,
8149516886,16887,16888,16889,16890,16891,16892,16893,16894,16895,16896,16897,
8149616898,16899,16900,16901,16902,16903,16904,16905,16906,16907,16908,16909,
8149716910,16911,16912,16913,16914,16915,16916,16917,16918,16919,16920,16921,
8149816922,16923,16924,16925,16926,16927,16928,16929,16930,16931,16932,16933,
8149916934,16935,16936,16937,16938,16939,16940,16941,16942,16943,16944,16945,
8150016946,16947,16948,16949,16950,16951,16952,16953,16954,16955,16956,16957,
8150116958,16959,16960,16961,16962,16963,16964,16965,16966,16967,16968,16969,
8150216970,16971,16972,16973,16974,16975,16976,16977,16978,16979,16980,16981,
8150316982,16983,16984,16985,16986,16987,16988,16989,16990,16991,16992,16993,
8150416994,16995,16996,16997,16998,16999,17000,17001,17002,17003,17004,17005,
8150517006,17007,17008,17009,17010,17011,17012,17013,17014,17015,17016,17017,
8150617018,17019,17020,17021,17022,17023,17024,17025,17026,17027,17028,17029,
8150717030,17031,17032,17033,17034,17035,17036,17037,17038,17039,17040,17041,
8150817042,17043,17044,17045,17046,17047,17048,17049,17050,17051,17052,17053,
8150917054,17055,17056,17057,17058,17059,17060,17061,17062,17063,17064,17065,
8151017066,17067,17068,17069,17070,17071,17072,17073,17074,17075,17076,17077,
8151117078,17079,17080,17081,17082,17083,17084,17085,17086,17087,17088,17089,
8151217090,17091,17092,17093,17094,17095,17096,17097,17098,17099,17100,17101,
8151317102,17103,17104,17105,17106,17107,17108,17109,17110,17111,17112,17113,
8151417114,17115,17116,17117,17118,17119,17120,17121,17122,17123,17124,17125,
8151517126,17127,17128,17129,17130,17131,17132,17133,17134,17135,17136,17137,
8151617138,17139,17140,17141,17142,17143,17144,17145,17146,17147,17148,17149,
8151717150,17151,17152,17153,17154,17155,17156,17157,17158,17159,17160,17161,
8151817162,17163,17164,17165,17166,17167,17168,17169,17170,17171,17172,17173,
8151917174,17175,17176,17177,17178,17179,17180,17181,17182,17183,17184,17185,
8152017186,17187,17188,17189,17190,17191,17192,17193,17194,17195,17196,17197,
8152117198,17199,17200,17201,17202,17203,17204,17205,17206,17207,17208,17209,
8152217210,17211,17212,17213,17214,17215,17216,17217,17218,17219,17220,17221,
8152317222,17223,17224,17225,17226,17227,17228,17229,17230,17231,17232,17233,
8152417234,17235,17236,17237,17238,17239,17240,17241,17242,17243,17244,17245,
8152517246,17247,17248,17249,17250,17251,17252,17253,17254,17255,17256,17257,
8152617258,17259,17260,17261,17262,17263,17264,17265,17266,17267,17268,17269,
8152717270,17271,17272,17273,17274,17275,17276,17277,17278,17279,17280,17281,
8152817282,17283,17284,17285,17286,17287,17288,17289,17290,17291,17292,17293,
8152917294,17295,17296,17297,17298,17299,17300,17301,17302,17303,17304,17305,
8153017306,17307,17308,17309,17310,17311,17312,17313,17314,17315,17316,17317,
8153117318,17319,17320,17321,17322,17323,17324,17325,17326,17327,17328,17329,
8153217330,17331,17332,17333,17334,17335,17336,17337,17338,17339,17340,17341,
8153317342,17343,17344,17345,17346,17347,17348,17349,17350,17351,17352,17353,
8153417354,17355,17356,17357,17358,17359,17360,17361,17362,17363,17364,17365,
8153517366,17367,17368,17369,17370,17371,17372,17373,17374,17375,17376,17377,
8153617378,17379,17380,17381,17382,17383,17384,17385,17386,17387,17388,17389,
8153717390,17391,17392,17393,17394,17395,17396,17397,17398,17399,17400,17401,
8153817402,17403,17404,17405,17406,17407,17408,17409,17410,17411,17412,17413,
8153917414,17415,17416,17417,17418,17419,17420,17421,17422,17423,17424,17425,
8154017426,17427,17428,17429,17430,17431,17432,17433,17434,17435,17436,17437,
8154117438,17439,17440,17441,17442,17443,17444,17445,17446,17447,17448,17449,
8154217450,17451,17452,17453,17454,17455,17456,17457,17458,17459,17460,17461,
8154317462,17463,17464,17465,17466,17467,17468,17469,17470,17471,17472,17473,
8154417474,17475,17476,17477,17478,17479,17480,17481,17482,17483,17484,17485,
8154517486,17487,17488,17489,17490,17491,17492,17493,17494,17495,17496,17497,
8154617498,17499,17500,17501,17502,17503,17504,17505,17506,17507,17508,17509,
8154717510,17511,17512,17513,17514,17515,17516,17517,17518,17519,17520,17521,
8154817522,17523,17524,17525,17526,17527,17528,17529,17530,17531,17532,17533,
8154917534,17535,17536,17537,17538,17539,17540,17541,17542,17543,17544,17545,
8155017546,17547,17548,17549,17550,17551,17552,17553,17554,17555,17556,17557,
8155117558,17559,17560,17561,17562,17563,17564,17565,17566,17567,17568,17569,
8155217570,17571,17572,17573,17574,17575,17576,17577,17578,17579,17580,17581,
8155317582,17583,17584,17585,17586,17587,17588,17589,17590,17591,17592,17593,
8155417594,17595,17596,17597,17598,17599,17600,17601,17602,17603,17604,17605,
8155517606,17607,17608,17609,17610,17611,17612,17613,17614,17615,17616,17617,
8155617618,17619,17620,17621,17622,17623,17624,17625,17626,17627,17628,17629,
8155717630,17631,17632,17633,17634,17635,17636,17637,17638,17639,17640,17641,
8155817642,17643,17644,17645,17646,17647,17648,17649,17650,17651,17652,17653,
8155917654,17655,17656,17657,17658,17659,17660,17661,17662,17663,17664,17665,
8156017666,17667,17668,17669,17670,17671,17672,17673,17674,17675,17676,17677,
8156117678,17679,17680,17681,17682,17683,17684,17685,17686,17687,17688,17689,
8156217690,17691,17692,17693,17694,17695,17696,17697,17698,17699,17700,17701,
8156317702,17703,17704,17705,17706,17707,17708,17709,17710,17711,17712,17713,
8156417714,17715,17716,17717,17718,17719,17720,17721,17722,17723,17724,17725,
8156517726,17727,17728,17729,17730,17731,17732,17733,17734,17735,17736,17737,
8156617738,17739,17740,17741,17742,17743,17744,17745,17746,17747,17748,17749,
8156717750,17751,17752,17753,17754,17755,17756,17757,17758,17759,17760,17761,
8156817762,17763,17764,17765,17766,17767,17768,17769,17770,17771,17772,17773,
8156917774,17775,17776,17777,17778,17779,17780,17781,17782,17783,17784,17785,
8157017786,17787,17788,17789,17790,17791,17792,17793,17794,17795,17796,17797,
8157117798,17799,17800,17801,17802,17803,17804,17805,17806,17807,17808,17809,
8157217810,17811,17812,17813,17814,17815,17816,17817,17818,17819,17820,17821,
8157317822,17823,17824,17825,17826,17827,17828,17829,17830,17831,17832,17833,
8157417834,17835,17836,17837,17838,17839,17840,17841,17842,17843,17844,17845,
8157517846,17847,17848,17849,17850,17851,17852,17853,17854,17855,17856,17857,
8157617858,17859,17860,17861,17862,17863,17864,17865,17866,17867,17868,17869,
8157717870,17871,17872,17873,17874,17875,17876,17877,17878,17879,17880,17881,
8157817882,17883,17884,17885,17886,17887,17888,17889,17890,17891,17892,17893,
8157917894,17895,17896,17897,17898,17899,17900,17901,17902,17903,17904,17905,
8158017906,17907,17908,17909,17910,17911,17912,17913,17914,17915,17916,17917,
8158117918,17919,17920,17921,17922,17923,17924,17925,17926,17927,17928,17929,
8158217930,17931,17932,17933,17934,17935,17936,17937,17938,17939,17940,17941,
8158317942,17943,17944,17945,17946,17947,17948,17949,17950,17951,17952,17953,
8158417954,17955,17956,17957,17958,17959,17960,17961,17962,17963,17964,17965,
8158517966,17967,17968,17969,17970,17971,17972,17973,17974,17975,17976,17977,
8158617978,17979,17980,17981,17982,17983,17984,17985,17986,17987,17988,17989,
8158717990,17991,17992,17993,17994,17995,17996,17997,17998,17999,18000,18001,
8158818002,18003,18004,18005,18006,18007,18008,18009,18010,18011,18012,18013,
8158918014,18015,18016,18017,18018,18019,18020,18021,18022,18023,18024,18025,
8159018026,18027,18028,18029,18030,18031,18032,18033,18034,18035,18036,18037,
8159118038,18039,18040,18041,18042,18043,18044,18045,18046,18047,18048,18049,
8159218050,18051,18052,18053,18054,18055,18056,18057,18058,18059,18060,18061,
8159318062,18063,18064,18065,18066,18067,18068,18069,18070,18071,18072,18073,
8159418074,18075,18076,18077,18078,18079,18080,18081,18082,18083,18084,18085,
8159518086,18087,18088,18089,18090,18091,18092,18093,18094,18095,18096,18097,
8159618098,18099,18100,18101,18102,18103,18104,18105,18106,18107,18108,18109,
8159718110,18111,18112,18113,18114,18115,18116,18117,18118,18119,18120,18121,
8159818122,18123,18124,18125,18126,18127,18128,18129,18130,18131,18132,18133,
8159918134,18135,18136,18137,18138,18139,18140,18141,18142,18143,18144,18145,
8160018146,18147,18148,18149,18150,18151,18152,18153,18154,18155,18156,18157,
8160118158,18159,18160,18161,18162,18163,18164,18165,18166,18167,18168,18169,
8160218170,18171,18172,18173,18174,18175,18176,18177,18178,18179,18180,18181,
8160318182,18183,18184,18185,18186,18187,18188,18189,18190,18191,18192,18193,
8160418194,18195,18196,18197,18198,18199,18200,18201,18202,18203,18204,18205,
8160518206,18207,18208,18209,18210,18211,18212,18213,18214,18215,18216,18217,
8160618218,18219,18220,18221,18222,18223,18224,18225,18226,18227,18228,18229,
8160718230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,
8160818242,18243,18244,18245,18246,18247,18248,18249,18250,18251,18252,18253,
8160918254,18255,18256,18257,18258,18259,18260,18261,18262,18263,18264,18265,
8161018266,18267,18268,18269,18270,18271,18272,18273,18274,18275,18276,18277,
8161118278,18279,18280,18281,18282,18283,18284,18285,18286,18287,18288,18289,
8161218290,18291,18292,18293,18294,18295,18296,18297,18298,18299,18300,18301,
8161318302,18303,18304,18305,18306,18307,18308,18309,18310,18311,18312,18313,
8161418314,18315,18316,18317,18318,18319,18320,18321,18322,18323,18324,18325,
8161518326,18327,18328,18329,18330,18331,18332,18333,18334,18335,18336,18337,
8161618338,18339,18340,18341,18342,18343,18344,18345,18346,18347,18348,18349,
8161718350,18351,18352,18353,18354,18355,18356,18357,18358,18359,18360,18361,
8161818362,18363,18364,18365,18366,18367,18368,18369,18370,18371,18372,18373,
8161918374,18375,18376,18377,18378,18379,18380,18381,18382,18383,18384,18385,
8162018386,18387,18388,18389,18390,18391,18392,18393,18394,18395,18396,18397,
8162118398,18399,18400,18401,18402,18403,18404,18405,18406,18407,18408,18409,
8162218410,18411,18412,18413,18414,18415,18416,18417,18418,18419,18420,18421,
8162318422,18423,18424,18425,18426,18427,18428,18429,18430,18431,18432,18433,
8162418434,18435,18436,18437,18438,18439,18440,18441,18442,18443,18444,18445,
8162518446,18447,18448,18449,18450,18451,18452,18453,18454,18455,18456,18457,
8162618458,18459,18460,18461,18462,18463,18464,18465,18466,18467,18468,18469,
8162718470,18471,18472,18473,18474,18475,18476,18477,18478,18479,18480,18481,
8162818482,18483,18484,18485,18486,18487,18488,18489,18490,18491,18492,18493,
8162918494,18495,18496,18497,18498,18499,18500,18501,18502,18503,18504,18505,
8163018506,18507,18508,18509,18510,18511,18512,18513,18514,18515,18516,18517,
8163118518,18519,18520,18521,18522,18523,18524,18525,18526,18527,18528,18529,
8163218530,18531,18532,18533,18534,18535,18536,18537,18538,18539,18540,18541,
8163318542,18543,18544,18545,18546,18547,18548,18549,18550,18551,18552,18553,
8163418554,18555,18556,18557,18558,18559,18560,18561,18562,18563,18564,18565,
8163518566,18567,18568,18569,18570,18571,18572,18573,18574,18575,18576,18577,
8163618578,18579,18580,18581,18582,18583,18584,18585,18586,18587,18588,18589,
8163718590,18591,18592,18593,18594,18595,18596,18597,18598,18599,18600,18601,
8163818602,18603,18604,18605,18606,18607,18608,18609,18610,18611,18612,18613,
8163918614,18615,18616,18617,18618,18619,18620,18621,18622,18623,18624,18625,
8164018626,18627,18628,18629,18630,18631,18632,18633,18634,18635,18636,18637,
8164118638,18639,18640,18641,18642,18643,18644,18645,18646,18647,18648,18649,
8164218650,18651,18652,18653,18654,18655,18656,18657,18658,18659,18660,18661,
8164318662,18663,18664,18665,18666,18667,18668,18669,18670,18671,18672,18673,
8164418674,18675,18676,18677,18678,18679,18680,18681,18682,18683,18684,18685,
8164518686,18687,18688,18689,18690,18691,18692,18693,18694,18695,18696,18697,
8164618698,18699,18700,18701,18702,18703,18704,18705,18706,18707,18708,18709,
8164718710,18711,18712,18713,18714,18715,18716,18717,18718,18719,18720,18721,
8164818722,18723,18724,18725,18726,18727,18728,18729,18730,18731,18732,18733,
8164918734,18735,18736,18737,18738,18739,18740,18741,18742,18743,18744,18745,
8165018746,18747,18748,18749,18750,18751,18752,18753,18754,18755,18756,18757,
8165118758,18759,18760,18761,18762,18763,18764,18765,18766,18767,18768,18769,
8165218770,18771,18772,18773,18774,18775,18776,18777,18778,18779,18780,18781,
8165318782,18783,18784,18785,18786,18787,18788,18789,18790,18791,18792,18793,
8165418794,18795,18796,18797,18798,18799,18800,18801,18802,18803,18804,18805,
8165518806,18807,18808,18809,18810,18811,18812,18813,18814,18815,18816,18817,
8165618818,18819,18820,18821,18822,18823,18824,18825,18826,18827,18828,18829,
8165718830,18831,18832,18833,18834,18835,18836,18837,18838,18839,18840,18841,
8165818842,18843,18844,18845,18846,18847,18848,18849,18850,18851,18852,18853,
8165918854,18855,18856,18857,18858,18859,18860,18861,18862,18863,18864,18865,
8166018866,18867,18868,18869,18870,18871,18872,18873,18874,18875,18876,18877,
8166118878,18879,18880,18881,18882,18883,18884,18885,18886,18887,18888,18889,
8166218890,18891,18892,18893,18894,18895,18896,18897,18898,18899,18900,18901,
8166318902,18903,18904,18905,18906,18907,18908,18909,18910,18911,18912,18913,
8166418914,18915,18916,18917,18918,18919,18920,18921,18922,18923,18924,18925,
8166518926,18927,18928,18929,18930,18931,18932,18933,18934,18935,18936,18937,
8166618938,18939,18940,18941,18942,18943,18944,18945,18946,18947,18948,18949,
8166718950,18951,18952,18953,18954,18955,18956,18957,18958,18959,18960,18961,
8166818962,18963,18964,18965,18966,18967,18968,18969,18970,18971,18972,18973,
8166918974,18975,18976,18977,18978,18979,18980,18981,18982,18983,18984,18985,
8167018986,18987,18988,18989,18990,18991,18992,18993,18994,18995,18996,18997,
8167118998,18999,19000,19001,19002,19003,19004,19005,19006,19007,19008,19009,
8167219010,19011,19012,19013,19014,19015,19016,19017,19018,19019,19020,19021,
8167319022,19023,19024,19025,19026,19027,19028,19029,19030,19031,19032,19033,
8167419034,19035,19036,19037,19038,19039,19040,19041,19042,19043,19044,19045,
8167519046,19047,19048,19049,19050,19051,19052,19053,19054,19055,19056,19057,
8167619058,19059,19060,19061,19062,19063,19064,19065,19066,19067,19068,19069,
8167719070,19071,19072,19073,19074,19075,19076,19077,19078,19079,19080,19081,
8167819082,19083,19084,19085,19086,19087,19088,19089,19090,19091,19092,19093,
8167919094,19095,19096,19097,19098,19099,19100,19101,19102,19103,19104,19105,
8168019106,19107,19108,19109,19110,19111,19112,19113,19114,19115,19116,19117,
8168119118,19119,19120,19121,19122,19123,19124,19125,19126,19127,19128,19129,
8168219130,19131,19132,19133,19134,19135,19136,19137,19138,19139,19140,19141,
8168319142,19143,19144,19145,19146,19147,19148,19149,19150,19151,19152,19153,
8168419154,19155,19156,19157,19158,19159,19160,19161,19162,19163,19164,19165,
8168519166,19167,19168,19169,19170,19171,19172,19173,19174,19175,19176,19177,
8168619178,19179,19180,19181,19182,19183,19184,19185,19186,19187,19188,19189,
8168719190,19191,19192,19193,19194,19195,19196,19197,19198,19199,19200,19201,
8168819202,19203,19204,19205,19206,19207,19208,19209,19210,19211,19212,19213,
8168919214,19215,19216,19217,19218,19219,19220,19221,19222,19223,19224,19225,
8169019226,19227,19228,19229,19230,19231,19232,19233,19234,19235,19236,19237,
8169119238,19239,19240,19241,19242,19243,19244,19245,19246,19247,19248,19249,
8169219250,19251,19252,19253,19254,19255,19256,19257,19258,19259,19260,19261,
8169319262,19263,19264,19265,19266,19267,19268,19269,19270,19271,19272,19273,
8169419274,19275,19276,19277,19278,19279,19280,19281,19282,19283,19284,19285,
8169519286,19287,19288,19289,19290,19291,19292,19293,19294,19295,19296,19297,
8169619298,19299,19300,19301,19302,19303,19304,19305,19306,19307,19308,19309,
8169719310,19311,19312,19313,19314,19315,19316,19317,19318,19319,19320,19321,
8169819322,19323,19324,19325,19326,19327,19328,19329,19330,19331,19332,19333,
8169919334,19335,19336,19337,19338,19339,19340,19341,19342,19343,19344,19345,
8170019346,19347,19348,19349,19350,19351,19352,19353,19354,19355,19356,19357,
8170119358,19359,19360,19361,19362,19363,19364,19365,19366,19367,19368,19369,
8170219370,19371,19372,19373,19374,19375,19376,19377,19378,19379,19380,19381,
8170319382,19383,19384,19385,19386,19387,19388,19389,19390,19391,19392,19393,
8170419394,19395,19396,19397,19398,19399,19400,19401,19402,19403,19404,19405,
8170519406,19407,19408,19409,19410,19411,19412,19413,19414,19415,19416,19417,
8170619418,19419,19420,19421,19422,19423,19424,19425,19426,19427,19428,19429,
8170719430,19431,19432,19433,19434,19435,19436,19437,19438,19439,19440,19441,
8170819442,19443,19444,19445,19446,19447,19448,19449,19450,19451,19452,19453,
8170919454,19455,19456,19457,19458,19459,19460,19461,19462,19463,19464,19465,
8171019466,19467,19468,19469,19470,19471,19472,19473,19474,19475,19476,19477,
8171119478,19479,19480,19481,19482,19483,19484,19485,19486,19487,19488,19489,
8171219490,19491,19492,19493,19494,19495,19496,19497,19498,19499,19500,19501,
8171319502,19503,19504,19505,19506,19507,19508,19509,19510,19511,19512,19513,
8171419514,19515,19516,19517,19518,19519,19520,19521,19522,19523,19524,19525,
8171519526,19527,19528,19529,19530,19531,19532,19533,19534,19535,19536,19537,
8171619538,19539,19540,19541,19542,19543,19544,19545,19546,19547,19548,19549,
8171719550,19551,19552,19553,19554,19555,19556,19557,19558,19559,19560,19561,
8171819562,19563,19564,19565,19566,19567,19568,19569,19570,19571,19572,19573,
8171919574,19575,19576,19577,19578,19579,19580,19581,19582,19583,19584,19585,
8172019586,19587,19588,19589,19590,19591,19592,19593,19594,19595,19596,19597,
8172119598,19599,19600,19601,19602,19603,19604,19605,19606,19607,19608,19609,
8172219610,19611,19612,19613,19614,19615,19616,19617,19618,19619,19620,19621,
8172319622,19623,19624,19625,19626,19627,19628,19629,19630,19631,19632,19633,
8172419634,19635,19636,19637,19638,19639,19640,19641,19642,19643,19644,19645,
8172519646,19647,19648,19649,19650,19651,19652,19653,19654,19655,19656,19657,
8172619658,19659,19660,19661,19662,19663,19664,19665,19666,19667,19668,19669,
8172719670,19671,19672,19673,19674,19675,19676,19677,19678,19679,19680,19681,
8172819682,19683,19684,19685,19686,19687,19688,19689,19690,19691,19692,19693,
8172919694,19695,19696,19697,19698,19699,19700,19701,19702,19703,19704,19705,
8173019706,19707,19708,19709,19710,19711,19712,19713,19714,19715,19716,19717,
8173119718,19719,19720,19721,19722,19723,19724,19725,19726,19727,19728,19729,
8173219730,19731,19732,19733,19734,19735,19736,19737,19738,19739,19740,19741,
8173319742,19743,19744,19745,19746,19747,19748,19749,19750,19751,19752,19753,
8173419754,19755,19756,19757,19758,19759,19760,19761,19762,19763,19764,19765,
8173519766,19767,19768,19769,19770,19771,19772,19773,19774,19775,19776,19777,
8173619778,19779,19780,19781,19782,19783,19784,19785,19786,19787,19788,19789,
8173719790,19791,19792,19793,19794,19795,19796,19797,19798,19799,19800,19801,
8173819802,19803,19804,19805,19806,19807,19808,19809,19810,19811,19812,19813,
8173919814,19815,19816,19817,19818,19819,19820,19821,19822,19823,19824,19825,
8174019826,19827,19828,19829,19830,19831,19832,19833,19834,19835,19836,19837,
8174119838,19839,19840,19841,19842,19843,19844,19845,19846,19847,19848,19849,
8174219850,19851,19852,19853,19854,19855,19856,19857,19858,19859,19860,19861,
8174319862,19863,19864,19865,19866,19867,19868,19869,19870,19871,19872,19873,
8174419874,19875,19876,19877,19878,19879,19880,19881,19882,19883,19884,19885,
8174519886,19887,19888,19889,19890,19891,19892,19893,19894,19895,19896,19897,
8174619898,19899,19900,19901,19902,19903,19904,19905,19906,19907,19908,19909,
8174719910,19911,19912,19913,19914,19915,19916,19917,19918,19919,19920,19921,
8174819922,19923,19924,19925,19926,19927,19928,19929,19930,19931,19932,19933,
8174919934,19935,19936,19937,19938,19939,19940,19941,19942,19943,19944,19945,
8175019946,19947,19948,19949,19950,19951,19952,19953,19954,19955,19956,19957,
8175119958,19959,19960,19961,19962,19963,19964,19965,19966,19967,19968,19969,
8175219970,19971,19972,19973,19974,19975,19976,19977,19978,19979,19980,19981,
8175319982,19983,19984,19985,19986,19987,19988,19989,19990,19991,19992,19993,
8175419994,19995,19996,19997,19998,19999,20000,20001,20002,20003,20004,20005,
8175520006,20007,20008,20009,20010,20011,20012,20013,20014,20015,20016,20017,
8175620018,20019,20020,20021,20022,20023,20024,20025,20026,20027,20028,20029,
8175720030,20031,20032,20033,20034,20035,20036,20037,20038,20039,20040,20041,
8175820042,20043,20044,20045,20046,20047,20048,20049,20050,20051,20052,20053,
8175920054,20055,20056,20057,20058,20059,20060,20061,20062,20063,20064,20065,
8176020066,20067,20068,20069,20070,20071,20072,20073,20074,20075,20076,20077,
8176120078,20079,20080,20081,20082,20083,20084,20085,20086,20087,20088,20089,
8176220090,20091,20092,20093,20094,20095,20096,20097,20098,20099,20100,20101,
8176320102,20103,20104,20105,20106,20107,20108,20109,20110,20111,20112,20113,
8176420114,20115,20116,20117,20118,20119,20120,20121,20122,20123,20124,20125,
8176520126,20127,20128,20129,20130,20131,20132,20133,20134,20135,20136,20137,
8176620138,20139,20140,20141,20142,20143,20144,20145,20146,20147,20148,20149,
8176720150,20151,20152,20153,20154,20155,20156,20157,20158,20159,20160,20161,
8176820162,20163,20164,20165,20166,20167,20168,20169,20170,20171,20172,20173,
8176920174,20175,20176,20177,20178,20179,20180,20181,20182,20183,20184,20185,
8177020186,20187,20188,20189,20190,20191,20192,20193,20194,20195,20196,20197,
8177120198,20199,20200,20201,20202,20203,20204,20205,20206,20207,20208,20209,
8177220210,20211,20212,20213,20214,20215,20216,20217,20218,20219,20220,20221,
8177320222,20223,20224,20225,20226,20227,20228,20229,20230,20231,20232,20233,
8177420234,20235,20236,20237,20238,20239,20240,20241,20242,20243,20244,20245,
8177520246,20247,20248,20249,20250,20251,20252,20253,20254,20255,20256,20257,
8177620258,20259,20260,20261,20262,20263,20264,20265,20266,20267,20268,20269,
8177720270,20271,20272,20273,20274,20275,20276,20277,20278,20279,20280,20281,
8177820282,20283,20284,20285,20286,20287,20288,20289,20290,20291,20292,20293,
8177920294,20295,20296,20297,20298,20299,20300,20301,20302,20303,20304,20305,
8178020306,20307,20308,20309,20310,20311,20312,20313,20314,20315,20316,20317,
8178120318,20319,20320,20321,20322,20323,20324,20325,20326,20327,20328,20329,
8178220330,20331,20332,20333,20334,20335,20336,20337,20338,20339,20340,20341,
8178320342,20343,20344,20345,20346,20347,20348,20349,20350,20351,20352,20353,
8178420354,20355,20356,20357,20358,20359,20360,20361,20362,20363,20364,20365,
8178520366,20367,20368,20369,20370,20371,20372,20373,20374,20375,20376,20377,
8178620378,20379,20380,20381,20382,20383,20384,20385,20386,20387,20388,20389,
8178720390,20391,20392,20393,20394,20395,20396,20397,20398,20399,20400,20401,
8178820402,20403,20404,20405,20406,20407,20408,20409,20410,20411,20412,20413,
8178920414,20415,20416,20417,20418,20419,20420,20421,20422,20423,20424,20425,
8179020426,20427,20428,20429,20430,20431,20432,20433,20434,20435,20436,20437,
8179120438,20439,20440,20441,20442,20443,20444,20445,20446,20447,20448,20449,
8179220450,20451,20452,20453,20454,20455,20456,20457,20458,20459,20460,20461,
8179320462,20463,20464,20465,20466,20467,20468,20469,20470,20471,20472,20473,
8179420474,20475,20476,20477,20478,20479,20480,20481,20482,20483,20484,20485,
8179520486,20487,20488,20489,20490,20491,20492,20493,20494,20495,20496,20497,
8179620498,20499,20500,20501,20502,20503,20504,20505,20506,20507,20508,20509,
8179720510,20511,20512,20513,20514,20515,20516,20517,20518,20519,20520,20521,
8179820522,20523,20524,20525,20526,20527,20528,20529,20530,20531,20532,20533,
8179920534,20535,20536,20537,20538,20539,20540,20541,20542,20543,20544,20545,
8180020546,20547,20548,20549,20550,20551,20552,20553,20554,20555,20556,20557,
8180120558,20559,20560,20561,20562,20563,20564,20565,20566,20567,20568,20569,
8180220570,20571,20572,20573,20574,20575,20576,20577,20578,20579,20580,20581,
8180320582,20583,20584,20585,20586,20587,20588,20589,20590,20591,20592,20593,
8180420594,20595,20596,20597,20598,20599,20600,20601,20602,20603,20604,20605,
8180520606,20607,20608,20609,20610,20611,20612,20613,20614,20615,20616,20617,
8180620618,20619,20620,20621,20622,20623,20624,20625,20626,20627,20628,20629,
8180720630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,
8180820642,20643,20644,20645,20646,20647,20648,20649,20650,20651,20652,20653,
8180920654,20655,20656,20657,20658,20659,20660,20661,20662,20663,20664,20665,
8181020666,20667,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,
8181120678,20679,20680,20681,20682,20683,20684,20685,20686,20687,20688,20689,
8181220690,20691,20692,20693,20694,20695,20696,20697,20698,20699,20700,20701,
8181320702,20703,20704,20705,20706,20707,20708,20709,20710,20711,20712,20713,
8181420714,20715,20716,20717,20718,20719,20720,20721,20722,20723,20724,20725,
8181520726,20727,20728,20729,20730,20731,20732,20733,20734,20735,20736,20737,
8181620738,20739,20740,20741,20742,20743,20744,20745,20746,20747,20748,20749,
8181720750,20751,20752,20753,20754,20755,20756,20757,20758,20759,20760,20761,
8181820762,20763,20764,20765,20766,20767,20768,20769,20770,20771,20772,20773,
8181920774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,
8182020786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,
8182120798,20799,20800,20801,20802,20803,20804,20805,20806,20807,20808,20809,
8182220810,20811,20812,20813,20814,20815,20816,20817,20818,20819,20820,20821,
8182320822,20823,20824,20825,20826,20827,20828,20829,20830,20831,20832,20833,
8182420834,20835,20836,20837,20838,20839,20840,20841,20842,20843,20844,20845,
8182520846,20847,20848,20849,20850,20851,20852,20853,20854,20855,20856,20857,
8182620858,20859,20860,20861,20862,20863,20864,20865,20866,20867,20868,20869,
8182720870,20871,20872,20873,20874,20875,20876,20877,20878,20879,20880,20881,
8182820882,20883,20884,20885,20886,20887,20888,20889,20890,20891,20892,20893,
8182920894,20895,20896,20897,20898,20899,20900,20901,20902,20903,20904,20905,
8183020906,20907,20908,20909,20910,20911,20912,20913,20914,20915,20916,20917,
8183120918,20919,20920,20921,20922,20923,20924,20925,20926,20927,20928,20929,
8183220930,20931,20932,20933,20934,20935,20936,20937,20938,20939,20940,20941,
8183320942,20943,20944,20945,20946,20947,20948,20949,20950,20951,20952,20953,
8183420954,20955,20956,20957,20958,20959,20960,20961,20962,20963,20964,20965,
8183520966,20967,20968,20969,20970,20971,20972,20973,20974,20975,20976,20977,
8183620978,20979,20980,20981,20982,20983,20984,20985,20986,20987,20988,20989,
8183720990,20991,20992,20993,20994,20995,20996,20997,20998,20999,21000,21001,
8183821002,21003,21004,21005,21006,21007,21008,21009,21010,21011,21012,21013,
8183921014,21015,21016,21017,21018,21019,21020,21021,21022,21023,21024,21025,
8184021026,21027,21028,21029,21030,21031,21032,21033,21034,21035,21036,21037,
8184121038,21039,21040,21041,21042,21043,21044,21045,21046,21047,21048,21049,
8184221050,21051,21052,21053,21054,21055,21056,21057,21058,21059,21060,21061,
8184321062,21063,21064,21065,21066,21067,21068,21069,21070,21071,21072,21073,
8184421074,21075,21076,21077,21078,21079,21080,21081,21082,21083,21084,21085,
8184521086,21087,21088,21089,21090,21091,21092,21093,21094,21095,21096,21097,
8184621098,21099,21100,21101,21102,21103,21104,21105,21106,21107,21108,21109,
8184721110,21111,21112,21113,21114,21115,21116,21117,21118,21119,21120,21121,
8184821122,21123,21124,21125,21126,21127,21128,21129,21130,21131,21132,21133,
8184921134,21135,21136,21137,21138,21139,21140,21141,21142,21143,21144,21145,
8185021146,21147,21148,21149,21150,21151,21152,21153,21154,21155,21156,21157,
8185121158,21159,21160,21161,21162,21163,21164,21165,21166,21167,21168,21169,
8185221170,21171,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,
8185321182,21183,21184,21185,21186,21187,21188,21189,21190,21191,21192,21193,
8185421194,21195,21196,21197,21198,21199,21200,21201,21202,21203,21204,21205,
8185521206,21207,21208,21209,21210,21211,21212,21213,21214,21215,21216,21217,
8185621218,21219,21220,21221,21222,21223,21224,21225,21226,21227,21228,21229,
8185721230,21231,21232,21233,21234,21235,21236,21237,21238,21239,21240,21241,
8185821242,21243,21244,21245,21246,21247,21248,21249,21250,21251,21252,21253,
8185921254,21255,21256,21257,21258,21259,21260,21261,21262,21263,21264,21265,
8186021266,21267,21268,21269,21270,21271,21272,21273,21274,21275,21276,21277,
8186121278,21279,21280,21281,21282,21283,21284,21285,21286,21287,21288,21289,
8186221290,21291,21292,21293,21294,21295,21296,21297,21298,21299,21300,21301,
8186321302,21303,21304,21305,21306,21307,21308,21309,21310,21311,21312,21313,
8186421314,21315,21316,21317,21318,21319,21320,21321,21322,21323,21324,21325,
8186521326,21327,21328,21329,21330,21331,21332,21333,21334,21335,21336,21337,
8186621338,21339,21340,21341,21342,21343,21344,21345,21346,21347,21348,21349,
8186721350,21351,21352,21353,21354,21355,21356,21357,21358,21359,21360,21361,
8186821362,21363,21364,21365,21366,21367,21368,21369,21370,21371,21372,21373,
8186921374,21375,21376,21377,21378,21379,21380,21381,21382,21383,21384,21385,
8187021386,21387,21388,21389,21390,21391,21392,21393,21394,21395,21396,21397,
8187121398,21399,21400,21401,21402,21403,21404,21405,21406,21407,21408,21409,
8187221410,21411,21412,21413,21414,21415,21416,21417,21418,21419,21420,21421,
8187321422,21423,21424,21425,21426,21427,21428,21429,21430,21431,21432,21433,
8187421434,21435,21436,21437,21438,21439,21440,21441,21442,21443,21444,21445,
8187521446,21447,21448,21449,21450,21451,21452,21453,21454,21455,21456,21457,
8187621458,21459,21460,21461,21462,21463,21464,21465,21466,21467,21468,21469,
8187721470,21471,21472,21473,21474,21475,21476,21477,21478,21479,21480,21481,
8187821482,21483,21484,21485,21486,21487,21488,21489,21490,21491,21492,21493,
8187921494,21495,21496,21497,21498,21499,21500,21501,21502,21503,21504,21505,
8188021506,21507,21508,21509,21510,21511,21512,21513,21514,21515,21516,21517,
8188121518,21519,21520,21521,21522,21523,21524,21525,21526,21527,21528,21529,
8188221530,21531,21532,21533,21534,21535,21536,21537,21538,21539,21540,21541,
8188321542,21543,21544,21545,21546,21547,21548,21549,21550,21551,21552,21553,
8188421554,21555,21556,21557,21558,21559,21560,21561,21562,21563,21564,21565,
8188521566,21567,21568,21569,21570,21571,21572,21573,21574,21575,21576,21577,
8188621578,21579,21580,21581,21582,21583,21584,21585,21586,21587,21588,21589,
8188721590,21591,21592,21593,21594,21595,21596,21597,21598,21599,21600,21601,
8188821602,21603,21604,21605,21606,21607,21608,21609,21610,21611,21612,21613,
8188921614,21615,21616,21617,21618,21619,21620,21621,21622,21623,21624,21625,
8189021626,21627,21628,21629,21630,21631,21632,21633,21634,21635,21636,21637,
8189121638,21639,21640,21641,21642,21643,21644,21645,21646,21647,21648,21649,
8189221650,21651,21652,21653,21654,21655,21656,21657,21658,21659,21660,21661,
8189321662,21663,21664,21665,21666,21667,21668,21669,21670,21671,21672,21673,
8189421674,21675,21676,21677,21678,21679,21680,21681,21682,21683,21684,21685,
8189521686,21687,21688,21689,21690,21691,21692,21693,21694,21695,21696,21697,
8189621698,21699,21700,21701,21702,21703,21704,21705,21706,21707,21708,21709,
8189721710,21711,21712,21713,21714,21715,21716,21717,21718,21719,21720,21721,
8189821722,21723,21724,21725,21726,21727,21728,21729,21730,21731,21732,21733,
8189921734,21735,21736,21737,21738,21739,21740,21741,21742,21743,21744,21745,
8190021746,21747,21748,21749,21750,21751,21752,21753,21754,21755,21756,21757,
8190121758,21759,21760,21761,21762,21763,21764,21765,21766,21767,21768,21769,
8190221770,21771,21772,21773,21774,21775,21776,21777,21778,21779,21780,21781,
8190321782,21783,21784,21785,21786,21787,21788,21789,21790,21791,21792,21793,
8190421794,21795,21796,21797,21798,21799,21800,21801,21802,21803,21804,21805,
8190521806,21807,21808,21809,21810,21811,21812,21813,21814,21815,21816,21817,
8190621818,21819,21820,21821,21822,21823,21824,21825,21826,21827,21828,21829,
8190721830,21831,21832,21833,21834,21835,21836,21837,21838,21839,21840,21841,
8190821842,21843,21844,21845,21846,21847,21848,21849,21850,21851,21852,21853,
8190921854,21855,21856,21857,21858,21859,21860,21861,21862,21863,21864,21865,
8191021866,21867,21868,21869,21870,21871,21872,21873,21874,21875,21876,21877,
8191121878,21879,21880,21881,21882,21883,21884,21885,21886,21887,21888,21889,
8191221890,21891,21892,21893,21894,21895,21896,21897,21898,21899,21900,21901,
8191321902,21903,21904,21905,21906,21907,21908,21909,21910,21911,21912,21913,
8191421914,21915,21916,21917,21918,21919,21920,21921,21922,21923,21924,21925,
8191521926,21927,21928,21929,21930,21931,21932,21933,21934,21935,21936,21937,
8191621938,21939,21940,21941,21942,21943,21944,21945,21946,21947,21948,21949,
8191721950,21951,21952,21953,21954,21955,21956,21957,21958,21959,21960,21961,
8191821962,21963,21964,21965,21966,21967,21968,21969,21970,21971,21972,21973,
8191921974,21975,21976,21977,21978,21979,21980,21981,21982,21983,21984,21985,
8192021986,21987,21988,21989,21990,21991,21992,21993,21994,21995,21996,21997,
8192121998,21999,22000,22001,22002,22003,22004,22005,22006,22007,22008,22009,
8192222010,22011,22012,22013,22014,22015,22016,22017,22018,22019,22020,22021,
8192322022,22023,22024,22025,22026,22027,22028,22029,22030,22031,22032,22033,
8192422034,22035,22036,22037,22038,22039,22040,22041,22042,22043,22044,22045,
8192522046,22047,22048,22049,22050,22051,22052,22053,22054,22055,22056,22057,
8192622058,22059,22060,22061,22062,22063,22064,22065,22066,22067,22068,22069,
8192722070,22071,22072,22073,22074,22075,22076,22077,22078,22079,22080,22081,
8192822082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22092,22093,
8192922094,22095,22096,22097,22098,22099,22100,22101,22102,22103,22104,22105,
8193022106,22107,22108,22109,22110,22111,22112,22113,22114,22115,22116,22117,
8193122118,22119,22120,22121,22122,22123,22124,22125,22126,22127,22128,22129,
8193222130,22131,22132,22133,22134,22135,22136,22137,22138,22139,22140,22141,
8193322142,22143,22144,22145,22146,22147,22148,22149,22150,22151,22152,22153,
8193422154,22155,22156,22157,22158,22159,22160,22161,22162,22163,22164,22165,
8193522166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,
8193622178,22179,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,
8193722190,22191,22192,22193,22194,22195,22196,22197,22198,22199,22200,22201,
8193822202,22203,22204,22205,22206,22207,22208,22209,22210,22211,22212,22213,
8193922214,22215,22216,22217,22218,22219,22220,22221,22222,22223,22224,22225,
8194022226,22227,22228,22229,22230,22231,22232,22233,22234,22235,22236,22237,
8194122238,22239,22240,22241,22242,22243,22244,22245,22246,22247,22248,22249,
8194222250,22251,22252,22253,22254,22255,22256,22257,22258,22259,22260,22261,
8194322262,22263,22264,22265,22266,22267,22268,22269,22270,22271,22272,22273,
8194422274,22275,22276,22277,22278,22279,22280,22281,22282,22283,22284,22285,
8194522286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,
8194622298,22299,22300,22301,22302,22303,22304,22305,22306,22307,22308,22309,
8194722310,22311,22312,22313,22314,22315,22316,22317,22318,22319,22320,22321,
8194822322,22323,22324,22325,22326,22327,22328,22329,22330,22331,22332,22333,
8194922334,22335,22336,22337,22338,22339,22340,22341,22342,22343,22344,22345,
8195022346,22347,22348,22349,22350,22351,22352,22353,22354,22355,22356,22357,
8195122358,22359,22360,22361,22362,22363,22364,22365,22366,22367,22368,22369,
8195222370,22371,22372,22373,22374,22375,22376,22377,22378,22379,22380,22381,
8195322382,22383,22384,22385,22386,22387,22388,22389,22390,22391,22392,22393,
8195422394,22395,22396,22397,22398,22399,22400,22401,22402,22403,22404,22405,
8195522406,22407,22408,22409,22410,22411,22412,22413,22414,22415,22416,22417,
8195622418,22419,22420,22421,22422,22423,22424,22425,22426,22427,22428,22429,
8195722430,22431,22432,22433,22434,22435,22436,22437,22438,22439,22440,22441,
8195822442,22443,22444,22445,22446,22447,22448,22449,22450,22451,22452,22453,
8195922454,22455,22456,22457,22458,22459,22460,22461,22462,22463,22464,22465,
8196022466,22467,22468,22469,22470,22471,22472,22473,22474,22475,22476,22477,
8196122478,22479,22480,22481,22482,22483,22484,22485,22486,22487,22488,22489,
8196222490,22491,22492,22493,22494,22495,22496,22497,22498,22499,22500,22501,
8196322502,22503,22504,22505,22506,22507,22508,22509,22510,22511,22512,22513,
8196422514,22515,22516,22517,22518,22519,22520,22521,22522,22523,22524,22525,
8196522526,22527,22528,22529,22530,22531,22532,22533,22534,22535,22536,22537,
8196622538,22539,22540,22541,22542,22543,22544,22545,22546,22547,22548,22549,
8196722550,22551,22552,22553,22554,22555,22556,22557,22558,22559,22560,22561,
8196822562,22563,22564,22565,22566,22567,22568,22569,22570,22571,22572,22573,
8196922574,22575,22576,22577,22578,22579,22580,22581,22582,22583,22584,22585,
8197022586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22596,22597,
8197122598,22599,22600,22601,22602,22603,22604,22605,22606,22607,22608,22609,
8197222610,22611,22612,22613,22614,22615,22616,22617,22618,22619,22620,22621,
8197322622,22623,22624,22625,22626,22627,22628,22629,22630,22631,22632,22633,
8197422634,22635,22636,22637,22638,22639,22640,22641,22642,22643,22644,22645,
8197522646,22647,22648,22649,22650,22651,22652,22653,22654,22655,22656,22657,
8197622658,22659,22660,22661,22662,22663,22664,22665,22666,22667,22668,22669,
8197722670,22671,22672,22673,22674,22675,22676,22677,22678,22679,22680,22681,
8197822682,22683,22684,22685,22686,22687,22688,22689,22690,22691,22692,22693,
8197922694,22695,22696,22697,22698,22699,22700,22701,22702,22703,22704,22705,
8198022706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22716,22717,
8198122718,22719,22720,22721,22722,22723,22724,22725,22726,22727,22728,22729,
8198222730,22731,22732,22733,22734,22735,22736,22737,22738,22739,22740,22741,
8198322742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,
8198422754,22755,22756,22757,22758,22759,22760,22761,22762,22763,22764,22765,
8198522766,22767,22768,22769,22770,22771,22772,22773,22774,22775,22776,22777,
8198622778,22779,22780,22781,22782,22783,22784,22785,22786,22787,22788,22789,
8198722790,22791,22792,22793,22794,22795,22796,22797,22798,22799,22800,22801,
8198822802,22803,22804,22805,22806,22807,22808,22809,22810,22811,22812,22813,
8198922814,22815,22816,22817,22818,22819,22820,22821,22822,22823,22824,22825,
8199022826,22827,22828,22829,22830,22831,22832,22833,22834,22835,22836,22837,
8199122838,22839,22840,22841,22842,22843,22844,22845,22846,22847,22848,22849,
8199222850,22851,22852,22853,22854,22855,22856,22857,22858,22859,22860,22861,
8199322862,22863,22864,22865,22866,22867,22868,22869,22870,22871,22872,22873,
8199422874,22875,22876,22877,22878,22879,22880,22881,22882,22883,22884,22885,
8199522886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,
8199622898,22899,22900,22901,22902,22903,22904,22905,22906,22907,22908,22909,
8199722910,22911,22912,22913,22914,22915,22916,22917,22918,22919,22920,22921,
8199822922,22923,22924,22925,22926,22927,22928,22929,22930,22931,22932,22933,
8199922934,22935,22936,22937,22938,22939,22940,22941,22942,22943,22944,22945,
8200022946,22947,22948,22949,22950,22951,22952,22953,22954,22955,22956,22957,
8200122958,22959,22960,22961,22962,22963,22964,22965,22966,22967,22968,22969,
8200222970,22971,22972,22973,22974,22975,22976,22977,22978,22979,22980,22981,
8200322982,22983,22984,22985,22986,22987,22988,22989,22990,22991,22992,22993,
8200422994,22995,22996,22997,22998,22999,23000,23001,23002,23003,23004,23005,
8200523006,23007,23008,23009,23010,23011,23012,23013,23014,23015,23016,23017,
8200623018,23019,23020,23021,23022,23023,23024,23025,23026,23027,23028,23029,
8200723030,23031,23032,23033,23034,23035,23036,23037,23038,23039,23040,23041,
8200823042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,
8200923054,23055,23056,23057,23058,23059,23060,23061,23062,23063,23064,23065,
8201023066,23067,23068,23069,23070,23071,23072,23073,23074,23075,23076,23077,
8201123078,23079,23080,23081,23082,23083,23084,23085,23086,23087,23088,23089,
8201223090,23091,23092,23093,23094,23095,23096,23097,23098,23099,23100,23101,
8201323102,23103,23104,23105,23106,23107,23108,23109,23110,23111,23112,23113,
8201423114,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23125,
8201523126,23127,23128,23129,23130,23131,23132,23133,23134,23135,23136,23137,
8201623138,23139,23140,23141,23142,23143,23144,23145,23146,23147,23148,23149,
8201723150,23151,23152,23153,23154,23155,23156,23157,23158,23159,23160,23161,
8201823162,23163,23164,23165,23166,23167,23168,23169,23170,23171,23172,23173,
8201923174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,
8202023186,23187,23188,23189,23190,23191,23192,23193,23194,23195,23196,23197,
8202123198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,
8202223210,23211,23212,23213,23214,23215,23216,23217,23218,23219,23220,23221,
8202323222,23223,23224,23225,23226,23227,23228,23229,23230,23231,23232,23233,
8202423234,23235,23236,23237,23238,23239,23240,23241,23242,23243,23244,23245,
8202523246,23247,23248,23249,23250,23251,23252,23253,23254,23255,23256,23257,
8202623258,23259,23260,23261,23262,23263,23264,23265,23266,23267,23268,23269,
8202723270,23271,23272,23273,23274,23275,23276,23277,23278,23279,23280,23281,
8202823282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,
8202923294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23305,
8203023306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,
8203123318,23319,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,
8203223330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,
8203323342,23343,23344,23345,23346,23347,23348,23349,23350,23351,23352,23353,
8203423354,23355,23356,23357,23358,23359,23360,23361,23362,23363,23364,23365,
8203523366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23376,23377,
8203623378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23389,
8203723390,23391,23392,23393,23394,23395,23396,23397,23398,23399,23400,23401,
8203823402,23403,23404,23405,23406,23407,23408,23409,23410,23411,23412,23413,
8203923414,23415,23416,23417,23418,23419,23420,23421,23422,23423,23424,23425,
8204023426,23427,23428,23429,23430,23431,23432,23433,23434,23435,23436,23437,
8204123438,23439,23440,23441,23442,23443,23444,23445,23446,23447,23448,23449,
8204223450,23451,23452,23453,23454,23455,23456,23457,23458,23459,23460,23461,
8204323462,23463,23464,23465,23466,23467,23468,23469,23470,23471,23472,23473,
8204423474,23475,23476,23477,23478,23479,23480,23481,23482,23483,23484,23485,
8204523486,23487,23488,23489,23490,23491,23492,23493,23494,23495,23496,23497,
8204623498,23499,23500,23501,23502,23503,23504,23505,23506,23507,23508,23509,
8204723510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,
8204823522,23523,23524,23525,23526,23527,23528,23529,23530,23531,23532,23533,
8204923534,23535,23536,23537,23538,23539,23540,23541,23542,23543,23544,23545,
8205023546,23547,23548,23549,23550,23551,23552,23553,23554,23555,23556,23557,
8205123558,23559,23560,23561,23562,23563,23564,23565,23566,23567,23568,23569,
8205223570,23571,23572,23573,23574,23575,23576,23577,23578,23579,23580,23581,
8205323582,23583,23584,23585,23586,23587,23588,23589,23590,23591,23592,23593,
8205423594,23595,23596,23597,23598,23599,23600,23601,23602,23603,23604,23605,
8205523606,23607,23608,23609,23610,23611,23612,23613,23614,23615,23616,23617,
8205623618,23619,23620,23621,23622,23623,23624,23625,23626,23627,23628,23629,
8205723630,23631,23632,23633,23634,23635,23636,23637,23638,23639,23640,23641,
8205823642,23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,
8205923654,23655,23656,23657,23658,23659,23660,23661,23662,23663,23664,23665,
8206023666,23667,23668,23669,23670,23671,23672,23673,23674,23675,23676,23677,
8206123678,23679,23680,23681,23682,23683,23684,23685,23686,23687,23688,23689,
8206223690,23691,23692,23693,23694,23695,23696,23697,23698,23699,23700,23701,
8206323702,23703,23704,23705,23706,23707,23708,23709,23710,23711,23712,23713,
8206423714,23715,23716,23717,23718,23719,23720,23721,23722,23723,23724,23725,
8206523726,23727,23728,23729,23730,23731,23732,23733,23734,23735,23736,23737,
8206623738,23739,23740,23741,23742,23743,23744,23745,23746,23747,23748,23749,
8206723750,23751,23752,23753,23754,23755,23756,23757,23758,23759,23760,23761,
8206823762,23763,23764,23765,23766,23767,23768,23769,23770,23771,23772,23773,
8206923774,23775,23776,23777,23778,23779,23780,23781,23782,23783,23784,23785,
8207023786,23787,23788,23789,23790,23791,23792,23793,23794,23795,23796,23797,
8207123798,23799,23800,23801,23802,23803,23804,23805,23806,23807,23808,23809,
8207223810,23811,23812,23813,23814,23815,23816,23817,23818,23819,23820,23821,
8207323822,23823,23824,23825,23826,23827,23828,23829,23830,23831,23832,23833,
8207423834,23835,23836,23837,23838,23839,23840,23841,23842,23843,23844,23845,
8207523846,23847,23848,23849,23850,23851,23852,23853,23854,23855,23856,23857,
8207623858,23859,23860,23861,23862,23863,23864,23865,23866,23867,23868,23869,
8207723870,23871,23872,23873,23874,23875,23876,23877,23878,23879,23880,23881,
8207823882,23883,23884,23885,23886,23887,23888,23889,23890,23891,23892,23893,
8207923894,23895,23896,23897,23898,23899,23900,23901,23902,23903,23904,23905,
8208023906,23907,23908,23909,23910,23911,23912,23913,23914,23915,23916,23917,
8208123918,23919,23920,23921,23922,23923,23924,23925,23926,23927,23928,23929,
8208223930,23931,23932,23933,23934,23935,23936,23937,23938,23939,23940,23941,
8208323942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,
8208423954,23955,23956,23957,23958,23959,23960,23961,23962,23963,23964,23965,
8208523966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,
8208623978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,
8208723990,23991,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,
8208824002,24003,24004,24005,24006,24007,24008,24009,24010,24011,24012,24013,
8208924014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,
8209024026,24027,24028,24029,24030,24031,24032,24033,24034,24035,24036,24037,
8209124038,24039,24040,24041,24042,24043,24044,24045,24046,24047,24048,24049,
8209224050,24051,24052,24053,24054,24055,24056,24057,24058,24059,24060,24061,
8209324062,24063,24064,24065,24066,24067,24068,24069,24070,24071,24072,24073,
8209424074,24075,24076,24077,24078,24079,24080,24081,24082,24083,24084,24085,
8209524086,24087,24088,24089,24090,24091,24092,24093,24094,24095,24096,24097,
8209624098,24099,24100,24101,24102,24103,24104,24105,24106,24107,24108,24109,
8209724110,24111,24112,24113,24114,24115,24116,24117,24118,24119,24120,24121,
8209824122,24123,24124,24125,24126,24127,24128,24129,24130,24131,24132,24133,
8209924134,24135,24136,24137,24138,24139,24140,24141,24142,24143,24144,24145,
8210024146,24147,24148,24149,24150,24151,24152,24153,24154,24155,24156,24157,
8210124158,24159,24160,24161,24162,24163,24164,24165,24166,24167,24168,24169,
8210224170,24171,24172,24173,24174,24175,24176,24177,24178,24179,24180,24181,
8210324182,24183,24184,24185,24186,24187,24188,24189,24190,24191,24192,24193,
8210424194,24195,24196,24197,24198,24199,24200,24201,24202,24203,24204,24205,
8210524206,24207,24208,24209,24210,24211,24212,24213,24214,24215,24216,24217,
8210624218,24219,24220,24221,24222,24223,24224,24225,24226,24227,24228,24229,
8210724230,24231,24232,24233,24234,24235,24236,24237,24238,24239,24240,24241,
8210824242,24243,24244,24245,24246,24247,24248,24249,24250,24251,24252,24253,
8210924254,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24265,
8211024266,24267,24268,24269,24270,24271,24272,24273,24274,24275,24276,24277,
8211124278,24279,24280,24281,24282,24283,24284,24285,24286,24287,24288,24289,
8211224290,24291,24292,24293,24294,24295,24296,24297,24298,24299,24300,24301,
8211324302,24303,24304,24305,24306,24307,24308,24309,24310,24311,24312,24313,
8211424314,24315,24316,24317,24318,24319,24320,24321,24322,24323,24324,24325,
8211524326,24327,24328,24329,24330,24331,24332,24333,24334,24335,24336,24337,
8211624338,24339,24340,24341,24342,24343,24344,24345,24346,24347,24348,24349,
8211724350,24351,24352,24353,24354,24355,24356,24357,24358,24359,24360,24361,
8211824362,24363,24364,24365,24366,24367,24368,24369,24370,24371,24372,24373,
8211924374,24375,24376,24377,24378,24379,24380,24381,24382,24383,24384,24385,
8212024386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,
8212124398,24399,24400,24401,24402,24403,24404,24405,24406,24407,24408,24409,
8212224410,24411,24412,24413,24414,24415,24416,24417,24418,24419,24420,24421,
8212324422,24423,24424,24425,24426,24427,24428,24429,24430,24431,24432,24433,
8212424434,24435,24436,24437,24438,24439,24440,24441,24442,24443,24444,24445,
8212524446,24447,24448,24449,24450,24451,24452,24453,24454,24455,24456,24457,
8212624458,24459,24460,24461,24462,24463,24464,24465,24466,24467,24468,24469,
8212724470,24471,24472,24473,24474,24475,24476,24477,24478,24479,24480,24481,
8212824482,24483,24484,24485,24486,24487,24488,24489,24490,24491,24492,24493,
8212924494,24495,24496,24497,24498,24499,24500,24501,24502,24503,24504,24505,
8213024506,24507,24508,24509,24510,24511,24512,24513,24514,24515,24516,24517,
8213124518,24519,24520,24521,24522,24523,24524,24525,24526,24527,24528,24529,
8213224530,24531,24532,24533,24534,24535,24536,24537,24538,24539,24540,24541,
8213324542,24543,24544,24545,24546,24547,24548,24549,24550,24551,24552,24553,
8213424554,24555,24556,24557,24558,24559,24560,24561,24562,24563,24564,24565,
8213524566,24567,24568,24569,24570,24571,24572,24573,24574,24575,24576,24577,
8213624578,24579,24580,24581,24582,24583,24584,24585,24586,24587,24588,24589,
8213724590,24591,24592,24593,24594,24595,24596,24597,24598,24599,24600,24601,
8213824602,24603,24604,24605,24606,24607,24608,24609,24610,24611,24612,24613,
8213924614,24615,24616,24617,24618,24619,24620,24621,24622,24623,24624,24625,
8214024626,24627,24628,24629,24630,24631,24632,24633,24634,24635,24636,24637,
8214124638,24639,24640,24641,24642,24643,24644,24645,24646,24647,24648,24649,
8214224650,24651,24652,24653,24654,24655,24656,24657,24658,24659,24660,24661,
8214324662,24663,24664,24665,24666,24667,24668,24669,24670,24671,24672,24673,
8214424674,24675,24676,24677,24678,24679,24680,24681,24682,24683,24684,24685,
8214524686,24687,24688,24689,24690,24691,24692,24693,24694,24695,24696,24697,
8214624698,24699,24700,24701,24702,24703,24704,24705,24706,24707,24708,24709,
8214724710,24711,24712,24713,24714,24715,24716,24717,24718,24719,24720,24721,
8214824722,24723,24724,24725,24726,24727,24728,24729,24730,24731,24732,24733,
8214924734,24735,24736,24737,24738,24739,24740,24741,24742,24743,24744,24745,
8215024746,24747,24748,24749,24750,24751,24752,24753,24754,24755,24756,24757,
8215124758,24759,24760,24761,24762,24763,24764,24765,24766,24767,24768,24769,
8215224770,24771,24772,24773,24774,24775,24776,24777,24778,24779,24780,24781,
8215324782,24783,24784,24785,24786,24787,24788,24789,24790,24791,24792,24793,
8215424794,24795,24796,24797,24798,24799,24800,24801,24802,24803,24804,24805,
8215524806,24807,24808,24809,24810,24811,24812,24813,24814,24815,24816,24817,
8215624818,24819,24820,24821,24822,24823,24824,24825,24826,24827,24828,24829,
8215724830,24831,24832,24833,24834,24835,24836,24837,24838,24839,24840,24841,
8215824842,24843,24844,24845,24846,24847,24848,24849,24850,24851,24852,24853,
8215924854,24855,24856,24857,24858,24859,24860,24861,24862,24863,24864,24865,
8216024866,24867,24868,24869,24870,24871,24872,24873,24874,24875,24876,24877,
8216124878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,
8216224890,24891,24892,24893,24894,24895,24896,24897,24898,24899,24900,24901,
8216324902,24903,24904,24905,24906,24907,24908,24909,24910,24911,24912,24913,
8216424914,24915,24916,24917,24918,24919,24920,24921,24922,24923,24924,24925,
8216524926,24927,24928,24929,24930,24931,24932,24933,24934,24935,24936,24937,
8216624938,24939,24940,24941,24942,24943,24944,24945,24946,24947,24948,24949,
8216724950,24951,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,
8216824962,24963,24964,24965,24966,24967,24968,24969,24970,24971,24972,24973,
8216924974,24975,24976,24977,24978,24979,24980,24981,24982,24983,24984,24985,
8217024986,24987,24988,24989,24990,24991,24992,24993,24994,24995,24996,24997,
8217124998,24999,25000,25001,25002,25003,25004,25005,25006,25007,25008,25009,
8217225010,25011,25012,25013,25014,25015,25016,25017,25018,25019,25020,25021,
8217325022,25023,25024,25025,25026,25027,25028,25029,25030,25031,25032,25033,
8217425034,25035,25036,25037,25038,25039,25040,25041,25042,25043,25044,25045,
8217525046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,
8217625058,25059,25060,25061,25062,25063,25064,25065,25066,25067,25068,25069,
8217725070,25071,25072,25073,25074,25075,25076,25077,25078,25079,25080,25081,
8217825082,25083,25084,25085,25086,25087,25088,25089,25090,25091,25092,25093,
8217925094,25095,25096,25097,25098,25099,25100,25101,25102,25103,25104,25105,
8218025106,25107,25108,25109,25110,25111,25112,25113,25114,25115,25116,25117,
8218125118,25119,25120,25121,25122,25123,25124,25125,25126,25127,25128,25129,
8218225130,25131,25132,25133,25134,25135,25136,25137,25138,25139,25140,25141,
8218325142,25143,25144,25145,25146,25147,25148,25149,25150,25151,25152,25153,
8218425154,25155,25156,25157,25158,25159,25160,25161,25162,25163,25164,25165,
8218525166,25167,25168,25169,25170,25171,25172,25173,25174,25175,25176,25177,
8218625178,25179,25180,25181,25182,25183,25184,25185,25186,25187,25188,25189,
8218725190,25191,25192,25193,25194,25195,25196,25197,25198,25199,25200,25201,
8218825202,25203,25204,25205,25206,25207,25208,25209,25210,25211,25212,25213,
8218925214,25215,25216,25217,25218,25219,25220,25221,25222,25223,25224,25225,
8219025226,25227,25228,25229,25230,25231,25232,25233,25234,25235,25236,25237,
8219125238,25239,25240,25241,25242,25243,25244,25245,25246,25247,25248,25249,
8219225250,25251,25252,25253,25254,25255,25256,25257,25258,25259,25260,25261,
8219325262,25263,25264,25265,25266,25267,25268,25269,25270,25271,25272,25273,
8219425274,25275,25276,25277,25278,25279,25280,25281,25282,25283,25284,25285,
8219525286,25287,25288,25289,25290,25291,25292,25293,25294,25295,25296,25297,
8219625298,25299,25300,25301,25302,25303,25304,25305,25306,25307,25308,25309,
8219725310,25311,25312,25313,25314,25315,25316,25317,25318,25319,25320,25321,
8219825322,25323,25324,25325,25326,25327,25328,25329,25330,25331,25332,25333,
8219925334,25335,25336,25337,25338,25339,25340,25341,25342,25343,25344,25345,
8220025346,25347,25348,25349,25350,25351,25352,25353,25354,25355,25356,25357,
8220125358,25359,25360,25361,25362,25363,25364,25365,25366,25367,25368,25369,
8220225370,25371,25372,25373,25374,25375,25376,25377,25378,25379,25380,25381,
8220325382,25383,25384,25385,25386,25387,25388,25389,25390,25391,25392,25393,
8220425394,25395,25396,25397,25398,25399,25400,25401,25402,25403,25404,25405,
8220525406,25407,25408,25409,25410,25411,25412,25413,25414,25415,25416,25417,
8220625418,25419,25420,25421,25422,25423,25424,25425,25426,25427,25428,25429,
8220725430,25431,25432,25433,25434,25435,25436,25437,25438,25439,25440,25441,
8220825442,25443,25444,25445,25446,25447,25448,25449,25450,25451,25452,25453,
8220925454,25455,25456,25457,25458,25459,25460,25461,25462,25463,25464,25465,
8221025466,25467,25468,25469,25470,25471,25472,25473,25474,25475,25476,25477,
8221125478,25479,25480,25481,25482,25483,25484,25485,25486,25487,25488,25489,
8221225490,25491,25492,25493,25494,25495,25496,25497,25498,25499,25500,25501,
8221325502,25503,25504,25505,25506,25507,25508,25509,25510,25511,25512,25513,
8221425514,25515,25516,25517,25518,25519,25520,25521,25522,25523,25524,25525,
8221525526,25527,25528,25529,25530,25531,25532,25533,25534,25535,25536,25537,
8221625538,25539,25540,25541,25542,25543,25544,25545,25546,25547,25548,25549,
8221725550,25551,25552,25553,25554,25555,25556,25557,25558,25559,25560,25561,
8221825562,25563,25564,25565,25566,25567,25568,25569,25570,25571,25572,25573,
8221925574,25575,25576,25577,25578,25579,25580,25581,25582,25583,25584,25585,
8222025586,25587,25588,25589,25590,25591,25592,25593,25594,25595,25596,25597,
8222125598,25599,25600,25601,25602,25603,25604,25605,25606,25607,25608,25609,
8222225610,25611,25612,25613,25614,25615,25616,25617,25618,25619,25620,25621,
8222325622,25623,25624,25625,25626,25627,25628,25629,25630,25631,25632,25633,
8222425634,25635,25636,25637,25638,25639,25640,25641,25642,25643,25644,25645,
8222525646,25647,25648,25649,25650,25651,25652,25653,25654,25655,25656,25657,
8222625658,25659,25660,25661,25662,25663,25664,25665,25666,25667,25668,25669,
8222725670,25671,25672,25673,25674,25675,25676,25677,25678,25679,25680,25681,
8222825682,25683,25684,25685,25686,25687,25688,25689,25690,25691,25692,25693,
8222925694,25695,25696,25697,25698,25699,25700,25701,25702,25703,25704,25705,
8223025706,25707,25708,25709,25710,25711,25712,25713,25714,25715,25716,25717,
8223125718,25719,25720,25721,25722,25723,25724,25725,25726,25727,25728,25729,
8223225730,25731,25732,25733,25734,25735,25736,25737,25738,25739,25740,25741,
8223325742,25743,25744,25745,25746,25747,25748,25749,25750,25751,25752,25753,
8223425754,25755,25756,25757,25758,25759,25760,25761,25762,25763,25764,25765,
8223525766,25767,25768,25769,25770,25771,25772,25773,25774,25775,25776,25777,
8223625778,25779,25780,25781,25782,25783,25784,25785,25786,25787,25788,25789,
8223725790,25791,25792,25793,25794,25795,25796,25797,25798,25799,25800,25801,
8223825802,25803,25804,25805,25806,25807,25808,25809,25810,25811,25812,25813,
8223925814,25815,25816,25817,25818,25819,25820,25821,25822,25823,25824,25825,
8224025826,25827,25828,25829,25830,25831,25832,25833,25834,25835,25836,25837,
8224125838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,
8224225850,25851,25852,25853,25854,25855,25856,25857,25858,25859,25860,25861,
8224325862,25863,25864,25865,25866,25867,25868,25869,25870,25871,25872,25873,
8224425874,25875,25876,25877,25878,25879,25880,25881,25882,25883,25884,25885,
8224525886,25887,25888,25889,25890,25891,25892,25893,25894,25895,25896,25897,
8224625898,25899,25900,25901,25902,25903,25904,25905,25906,25907,25908,25909,
8224725910,25911,25912,25913,25914,25915,25916,25917,25918,25919,25920,25921,
8224825922,25923,25924,25925,25926,25927,25928,25929,25930,25931,25932,25933,
8224925934,25935,25936,25937,25938,25939,25940,25941,25942,25943,25944,25945,
8225025946,25947,25948,25949,25950,25951,25952,25953,25954,25955,25956,25957,
8225125958,25959,25960,25961,25962,25963,25964,25965,25966,25967,25968,25969,
8225225970,25971,25972,25973,25974,25975,25976,25977,25978,25979,25980,25981,
8225325982,25983,25984,25985,25986,25987,25988,25989,25990,25991,25992,25993,
8225425994,25995,25996,25997,25998,25999,26000,26001,26002,26003,26004,26005,
8225526006,26007,26008,26009,26010,26011,26012,26013,26014,26015,26016,26017,
8225626018,26019,26020,26021,26022,26023,26024,26025,26026,26027,26028,26029,
8225726030,26031,26032,26033,26034,26035,26036,26037,26038,26039,26040,26041,
8225826042,26043,26044,26045,26046,26047,26048,26049,26050,26051,26052,26053,
8225926054,26055,26056,26057,26058,26059,26060,26061,26062,26063,26064,26065,
8226026066,26067,26068,26069,26070,26071,26072,26073,26074,26075,26076,26077,
8226126078,26079,26080,26081,26082,26083,26084,26085,26086,26087,26088,26089,
8226226090,26091,26092,26093,26094,26095,26096,26097,26098,26099,26100,26101,
8226326102,26103,26104,26105,26106,26107,26108,26109,26110,26111,26112,26113,
8226426114,26115,26116,26117,26118,26119,26120,26121,26122,26123,26124,26125,
8226526126,26127,26128,26129,26130,26131,26132,26133,26134,26135,26136,26137,
8226626138,26139,26140,26141,26142,26143,26144,26145,26146,26147,26148,26149,
8226726150,26151,26152,26153,26154,26155,26156,26157,26158,26159,26160,26161,
8226826162,26163,26164,26165,26166,26167,26168,26169,26170,26171,26172,26173,
8226926174,26175,26176,26177,26178,26179,26180,26181,26182,26183,26184,26185,
8227026186,26187,26188,26189,26190,26191,26192,26193,26194,26195,26196,26197,
8227126198,26199,26200,26201,26202,26203,26204,26205,26206,26207,26208,26209,
8227226210,26211,26212,26213,26214,26215,26216,26217,26218,26219,26220,26221,
8227326222,26223,26224,26225,26226,26227,26228,26229,26230,26231,26232,26233,
8227426234,26235,26236,26237,26238,26239,26240,26241,26242,26243,26244,26245,
8227526246,26247,26248,26249,26250,26251,26252,26253,26254,26255,26256,26257,
8227626258,26259,26260,26261,26262,26263,26264,26265,26266,26267,26268,26269,
8227726270,26271,26272,26273,26274,26275,26276,26277,26278,26279,26280,26281,
8227826282,26283,26284,26285,26286,26287,26288,26289,26290,26291,26292,26293,
8227926294,26295,26296,26297,26298,26299,26300,26301,26302,26303,26304,26305,
8228026306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,
8228126318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26329,
8228226330,26331,26332,26333,26334,26335,26336,26337,26338,26339,26340,26341,
8228326342,26343,26344,26345,26346,26347,26348,26349,26350,26351,26352,26353,
8228426354,26355,26356,26357,26358,26359,26360,26361,26362,26363,26364,26365,
8228526366,26367,26368,26369,26370,26371,26372,26373,26374,26375,26376,26377,
8228626378,26379,26380,26381,26382,26383,26384,26385,26386,26387,26388,26389,
8228726390,26391,26392,26393,26394,26395,26396,26397,26398,26399,26400,26401,
8228826402,26403,26404,26405,26406,26407,26408,26409,26410,26411,26412,26413,
8228926414,26415,26416,26417,26418,26419,26420,26421,26422,26423,26424,26425,
8229026426,26427,26428,26429,26430,26431,26432,26433,26434,26435,26436,26437,
8229126438,26439,26440,26441,26442,26443,26444,26445,26446,26447,26448,26449,
8229226450,26451,26452,26453,26454,26455,26456,26457,26458,26459,26460,26461,
8229326462,26463,26464,26465,26466,26467,26468,26469,26470,26471,26472,26473,
8229426474,26475,26476,26477,26478,26479,26480,26481,26482,26483,26484,26485,
8229526486,26487,26488,26489,26490,26491,26492,26493,26494,26495,26496,26497,
8229626498,26499,26500,26501,26502,26503,26504,26505,26506,26507,26508,26509,
8229726510,26511,26512,26513,26514,26515,26516,26517,26518,26519,26520,26521,
8229826522,26523,26524,26525,26526,26527,26528,26529,26530,26531,26532,26533,
8229926534,26535,26536,26537,26538,26539,26540,26541,26542,26543,26544,26545,
8230026546,26547,26548,26549,26550,26551,26552,26553,26554,26555,26556,26557,
8230126558,26559,26560,26561,26562,26563,26564,26565,26566,26567,26568,26569,
8230226570,26571,26572,26573,26574,26575,26576,26577,26578,26579,26580,26581,
8230326582,26583,26584,26585,26586,26587,26588,26589,26590,26591,26592,26593,
8230426594,26595,26596,26597,26598,26599,26600,26601,26602,26603,26604,26605,
8230526606,26607,26608,26609,26610,26611,26612,26613,26614,26615,26616,26617,
8230626618,26619,26620,26621,26622,26623,26624,26625,26626,26627,26628,26629,
8230726630,26631,26632,26633,26634,26635,26636,26637,26638,26639,26640,26641,
8230826642,26643,26644,26645,26646,26647,26648,26649,26650,26651,26652,26653,
8230926654,26655,26656,26657,26658,26659,26660,26661,26662,26663,26664,26665,
8231026666,26667,26668,26669,26670,26671,26672,26673,26674,26675,26676,26677,
8231126678,26679,26680,26681,26682,26683,26684,26685,26686,26687,26688,26689,
8231226690,26691,26692,26693,26694,26695,26696,26697,26698,26699,26700,26701,
8231326702,26703,26704,26705,26706,26707,26708,26709,26710,26711,26712,26713,
8231426714,26715,26716,26717,26718,26719,26720,26721,26722,26723,26724,26725,
8231526726,26727,26728,26729,26730,26731,26732,26733,26734,26735,26736,26737,
8231626738,26739,26740,26741,26742,26743,26744,26745,26746,26747,26748,26749,
8231726750,26751,26752,26753,26754,26755,26756,26757,26758,26759,26760,26761,
8231826762,26763,26764,26765,26766,26767,26768,26769,26770,26771,26772,26773,
8231926774,26775,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,
8232026786,26787,26788,26789,26790,26791,26792,26793,26794,26795,26796,26797,
8232126798,26799,26800,26801,26802,26803,26804,26805,26806,26807,26808,26809,
8232226810,26811,26812,26813,26814,26815,26816,26817,26818,26819,26820,26821,
8232326822,26823,26824,26825,26826,26827,26828,26829,26830,26831,26832,26833,
8232426834,26835,26836,26837,26838,26839,26840,26841,26842,26843,26844,26845,
8232526846,26847,26848,26849,26850,26851,26852,26853,26854,26855,26856,26857,
8232626858,26859,26860,26861,26862,26863,26864,26865,26866,26867,26868,26869,
8232726870,26871,26872,26873,26874,26875,26876,26877,26878,26879,26880,26881,
8232826882,26883,26884,26885,26886,26887,26888,26889,26890,26891,26892,26893,
8232926894,26895,26896,26897,26898,26899,26900,26901,26902,26903,26904,26905,
8233026906,26907,26908,26909,26910,26911,26912,26913,26914,26915,26916,26917,
8233126918,26919,26920,26921,26922,26923,26924,26925,26926,26927,26928,26929,
8233226930,26931,26932,26933,26934,26935,26936,26937,26938,26939,26940,26941,
8233326942,26943,26944,26945,26946,26947,26948,26949,26950,26951,26952,26953,
8233426954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26964,26965,
8233526966,26967,26968,26969,26970,26971,26972,26973,26974,26975,26976,26977,
8233626978,26979,26980,26981,26982,26983,26984,26985,26986,26987,26988,26989,
8233726990,26991,26992,26993,26994,26995,26996,26997,26998,26999,27000,27001,
8233827002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,
8233927014,27015,27016,27017,27018,27019,27020,27021,27022,27023,27024,27025,
8234027026,27027,27028,27029,27030,27031,27032,27033,27034,27035,27036,27037,
8234127038,27039,27040,27041,27042,27043,27044,27045,27046,27047,27048,27049,
8234227050,27051,27052,27053,27054,27055,27056,27057,27058,27059,27060,27061,
8234327062,27063,27064,27065,27066,27067,27068,27069,27070,27071,27072,27073,
8234427074,27075,27076,27077,27078,27079,27080,27081,27082,27083,27084,27085,
8234527086,27087,27088,27089,27090,27091,27092,27093,27094,27095,27096,27097,
8234627098,27099,27100,27101,27102,27103,27104,27105,27106,27107,27108,27109,
8234727110,27111,27112,27113,27114,27115,27116,27117,27118,27119,27120,27121,
8234827122,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27133,
8234927134,27135,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,
8235027146,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,
8235127158,27159,27160,27161,27162,27163,27164,27165,27166,27167,27168,27169,
8235227170,27171,27172,27173,27174,27175,27176,27177,27178,27179,27180,27181,
8235327182,27183,27184,27185,27186,27187,27188,27189,27190,27191,27192,27193,
8235427194,27195,27196,27197,27198,27199,27200,27201,27202,27203,27204,27205,
8235527206,27207,27208,27209,27210,27211,27212,27213,27214,27215,27216,27217,
8235627218,27219,27220,27221,27222,27223,27224,27225,27226,27227,27228,27229,
8235727230,27231,27232,27233,27234,27235,27236,27237,27238,27239,27240,27241,
8235827242,27243,27244,27245,27246,27247,27248,27249,27250,27251,27252,27253,
8235927254,27255,27256,27257,27258,27259,27260,27261,27262,27263,27264,27265,
8236027266,27267,27268,27269,27270,27271,27272,27273,27274,27275,27276,27277,
8236127278,27279,27280,27281,27282,27283,27284,27285,27286,27287,27288,27289,
8236227290,27291,27292,27293,27294,27295,27296,27297,27298,27299,27300,27301,
8236327302,27303,27304,27305,27306,27307,27308,27309,27310,27311,27312,27313,
8236427314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,
8236527326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,
8236627338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,
8236727350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,
8236827362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,
8236927374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,
8237027386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,
8237127398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,
8237227410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,
8237327422,27423,27424,27425,27426,27427,27428,27429,27430,27431,27432,27433,
8237427434,27435,27436,27437,27438,27439,27440,27441,27442,27443,27444,27445,
8237527446,27447,27448,27449,27450,27451,27452,27453,27454,27455,27456,27457,
8237627458,27459,27460,27461,27462,27463,27464,27465,27466,27467,27468,27469,
8237727470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27481,
8237827482,27483,27484,27485,27486,27487,27488,27489,27490,27491,27492,27493,
8237927494,27495,27496,27497,27498,27499,27500,27501,27502,27503,27504,27505,
8238027506,27507,27508,27509,27510,27511,27512,27513,27514,27515,27516,27517,
8238127518,27519,27520,27521,27522,27523,27524,27525,27526,27527,27528,27529,
8238227530,27531,27532,27533,27534,27535,27536,27537,27538,27539,27540,27541,
8238327542,27543,27544,27545,27546,27547,27548,27549,27550,27551,27552,27553,
8238427554,27555,27556,27557,27558,27559,27560,27561,27562,27563,27564,27565,
8238527566,27567,27568,27569,27570,27571,27572,27573,27574,27575,27576,27577,
8238627578,27579,27580,27581,27582,27583,27584,27585,27586,27587,27588,27589,
8238727590,27591,27592,27593,27594,27595,27596,27597,27598,27599,27600,27601,
8238827602,27603,27604,27605,27606,27607,27608,27609,27610,27611,27612,27613,
8238927614,27615,27616,27617,27618,27619,27620,27621,27622,27623,27624,27625,
8239027626,27627,27628,27629,27630,27631,27632,27633,27634,27635,27636,27637,
8239127638,27639,27640,27641,27642,27643,27644,27645,27646,27647,27648,27649,
8239227650,27651,27652,27653,27654,27655,27656,27657,27658,27659,27660,27661,
8239327662,27663,27664,27665,27666,27667,27668,27669,27670,27671,27672,27673,
8239427674,27675,27676,27677,27678,27679,27680,27681,27682,27683,27684,27685,
8239527686,27687,27688,27689,27690,27691,27692,27693,27694,27695,27696,27697,
8239627698,27699,27700,27701,27702,27703,27704,27705,27706,27707,27708,27709,
8239727710,27711,27712,27713,27714,27715,27716,27717,27718,27719,27720,27721,
8239827722,27723,27724,27725,27726,27727,27728,27729,27730,27731,27732,27733,
8239927734,27735,27736,27737,27738,27739,27740,27741,27742,27743,27744,27745,
8240027746,27747,27748,27749,27750,27751,27752,27753,27754,27755,27756,27757,
8240127758,27759,27760,27761,27762,27763,27764,27765,27766,27767,27768,27769,
8240227770,27771,27772,27773,27774,27775,27776,27777,27778,27779,27780,27781,
8240327782,27783,27784,27785,27786,27787,27788,27789,27790,27791,27792,27793,
8240427794,27795,27796,27797,27798,27799,27800,27801,27802,27803,27804,27805,
8240527806,27807,27808,27809,27810,27811,27812,27813,27814,27815,27816,27817,
8240627818,27819,27820,27821,27822,27823,27824,27825,27826,27827,27828,27829,
8240727830,27831,27832,27833,27834,27835,27836,27837,27838,27839,27840,27841,
8240827842,27843,27844,27845,27846,27847,27848,27849,27850,27851,27852,27853,
8240927854,27855,27856,27857,27858,27859,27860,27861,27862,27863,27864,27865,
8241027866,27867,27868,27869,27870,27871,27872,27873,27874,27875,27876,27877,
8241127878,27879,27880,27881,27882,27883,27884,27885,27886,27887,27888,27889,
8241227890,27891,27892,27893,27894,27895,27896,27897,27898,27899,27900,27901,
8241327902,27903,27904,27905,27906,27907,27908,27909,27910,27911,27912,27913,
8241427914,27915,27916,27917,27918,27919,27920,27921,27922,27923,27924,27925,
8241527926,27927,27928,27929,27930,27931,27932,27933,27934,27935,27936,27937,
8241627938,27939,27940,27941,27942,27943,27944,27945,27946,27947,27948,27949,
8241727950,27951,27952,27953,27954,27955,27956,27957,27958,27959,27960,27961,
8241827962,27963,27964,27965,27966,27967,27968,27969,27970,27971,27972,27973,
8241927974,27975,27976,27977,27978,27979,27980,27981,27982,27983,27984,27985,
8242027986,27987,27988,27989,27990,27991,27992,27993,27994,27995,27996,27997,
8242127998,27999,28000,28001,28002,28003,28004,28005,28006,28007,28008,28009,
8242228010,28011,28012,28013,28014,28015,28016,28017,28018,28019,28020,28021,
8242328022,28023,28024,28025,28026,28027,28028,28029,28030,28031,28032,28033,
8242428034,28035,28036,28037,28038,28039,28040,28041,28042,28043,28044,28045,
8242528046,28047,28048,28049,28050,28051,28052,28053,28054,28055,28056,28057,
8242628058,28059,28060,28061,28062,28063,28064,28065,28066,28067,28068,28069,
8242728070,28071,28072,28073,28074,28075,28076,28077,28078,28079,28080,28081,
8242828082,28083,28084,28085,28086,28087,28088,28089,28090,28091,28092,28093,
8242928094,28095,28096,28097,28098,28099,28100,28101,28102,28103,28104,28105,
8243028106,28107,28108,28109,28110,28111,28112,28113,28114,28115,28116,28117,
8243128118,28119,28120,28121,28122,28123,28124,28125,28126,28127,28128,28129,
8243228130,28131,28132,28133,28134,28135,28136,28137,28138,28139,28140,28141,
8243328142,28143,28144,28145,28146,28147,28148,28149,28150,28151,28152,28153,
8243428154,28155,28156,28157,28158,28159,28160,28161,28162,28163,28164,28165,
8243528166,28167,28168,28169,28170,28171,28172,28173,28174,28175,28176,28177,
8243628178,28179,28180,28181,28182,28183,28184,28185,28186,28187,28188,28189,
8243728190,28191,28192,28193,28194,28195,28196,28197,28198,28199,28200,28201,
8243828202,28203,28204,28205,28206,28207,28208,28209,28210,28211,28212,28213,
8243928214,28215,28216,28217,28218,28219,28220,28221,28222,28223,28224,28225,
8244028226,28227,28228,28229,28230,28231,28232,28233,28234,28235,28236,28237,
8244128238,28239,28240,28241,28242,28243,28244,28245,28246,28247,28248,28249,
8244228250,28251,28252,28253,28254,28255,28256,28257,28258,28259,28260,28261,
8244328262,28263,28264,28265,28266,28267,28268,28269,28270,28271,28272,28273,
8244428274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,
8244528286,28287,28288,28289,28290,28291,28292,28293,28294,28295,28296,28297,
8244628298,28299,28300,28301,28302,28303,28304,28305,28306,28307,28308,28309,
8244728310,28311,28312,28313,28314,28315,28316,28317,28318,28319,28320,28321,
8244828322,28323,28324,28325,28326,28327,28328,28329,28330,28331,28332,28333,
8244928334,28335,28336,28337,28338,28339,28340,28341,28342,28343,28344,28345,
8245028346,28347,28348,28349,28350,28351,28352,28353,28354,28355,28356,28357,
8245128358,28359,28360,28361,28362,28363,28364,28365,28366,28367,28368,28369,
8245228370,28371,28372,28373,28374,28375,28376,28377,28378,28379,28380,28381,
8245328382,28383,28384,28385,28386,28387,28388,28389,28390,28391,28392,28393,
8245428394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28404,28405,
8245528406,28407,28408,28409,28410,28411,28412,28413,28414,28415,28416,28417,
8245628418,28419,28420,28421,28422,28423,28424,28425,28426,28427,28428,28429,
8245728430,28431,28432,28433,28434,28435,28436,28437,28438,28439,28440,28441,
8245828442,28443,28444,28445,28446,28447,28448,28449,28450,28451,28452,28453,
8245928454,28455,28456,28457,28458,28459,28460,28461,28462,28463,28464,28465,
8246028466,28467,28468,28469,28470,28471,28472,28473,28474,28475,28476,28477,
8246128478,28479,28480,28481,28482,28483,28484,28485,28486,28487,28488,28489,
8246228490,28491,28492,28493,28494,28495,28496,28497,28498,28499,28500,28501,
8246328502,28503,28504,28505,28506,28507,28508,28509,28510,28511,28512,28513,
8246428514,28515,28516,28517,28518,28519,28520,28521,28522,28523,28524,28525,
8246528526,28527,28528,28529,28530,28531,28532,28533,28534,28535,28536,28537,
8246628538,28539,28540,28541,28542,28543,28544,28545,28546,28547,28548,28549,
8246728550,28551,28552,28553,28554,28555,28556,28557,28558,28559,28560,28561,
8246828562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28572,28573,
8246928574,28575,28576,28577,28578,28579,28580,28581,28582,28583,28584,28585,
8247028586,28587,28588,28589,28590,28591,28592,28593,28594,28595,28596,28597,
8247128598,28599,28600,28601,28602,28603,28604,28605,28606,28607,28608,28609,
8247228610,28611,28612,28613,28614,28615,28616,28617,28618,28619,28620,28621,
8247328622,28623,28624,28625,28626,28627,28628,28629,28630,28631,28632,28633,
8247428634,28635,28636,28637,28638,28639,28640,28641,28642,28643,28644,28645,
8247528646,28647,28648,28649,28650,28651,28652,28653,28654,28655,28656,28657,
8247628658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,
8247728670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,
8247828682,28683,28684,28685,28686,28687,28688,28689,28690,28691,28692,28693,
8247928694,28695,28696,28697,28698,28699,28700,28701,28702,28703,28704,28705,
8248028706,28707,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,
8248128718,28719,28720,28721,28722,28723,28724,28725,28726,28727,28728,28729,
8248228730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,
8248328742,28743,28744,28745,28746,28747,28748,28749,28750,28751,28752,28753,
8248428754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,
8248528766,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,
8248628778,28779,28780,28781,28782,28783,28784,28785,28786,28787,28788,28789,
8248728790,28791,28792,28793,28794,28795,28796,28797,28798,28799,28800,28801,
8248828802,28803,28804,28805,28806,28807,28808,28809,28810,28811,28812,28813,
8248928814,28815,28816,28817,28818,28819,28820,28821,28822,28823,28824,28825,
8249028826,28827,28828,28829,28830,28831,28832,28833,28834,28835,28836,28837,
8249128838,28839,28840,28841,28842,28843,28844,28845,28846,28847,28848,28849,
8249228850,28851,28852,28853,28854,28855,28856,28857,28858,28859,28860,28861,
8249328862,28863,28864,28865,28866,28867,28868,28869,28870,28871,28872,28873,
8249428874,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,
8249528886,28887,28888,28889,28890,28891,28892,28893,28894,28895,28896,28897,
8249628898,28899,28900,28901,28902,28903,28904,28905,28906,28907,28908,28909,
8249728910,28911,28912,28913,28914,28915,28916,28917,28918,28919,28920,28921,
8249828922,28923,28924,28925,28926,28927,28928,28929,28930,28931,28932,28933,
8249928934,28935,28936,28937,28938,28939,28940,28941,28942,28943,28944,28945,
8250028946,28947,28948,28949,28950,28951,28952,28953,28954,28955,28956,28957,
8250128958,28959,28960,28961,28962,28963,28964,28965,28966,28967,28968,28969,
8250228970,28971,28972,28973,28974,28975,28976,28977,28978,28979,28980,28981,
8250328982,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,
8250428994,28995,28996,28997,28998,28999,29000,29001,29002,29003,29004,29005,
8250529006,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,
8250629018,29019,29020,29021,29022,29023,29024,29025,29026,29027,29028,29029,
8250729030,29031,29032,29033,29034,29035,29036,29037,29038,29039,29040,29041,
8250829042,29043,29044,29045,29046,29047,29048,29049,29050,29051,29052,29053,
8250929054,29055,29056,29057,29058,29059,29060,29061,29062,29063,29064,29065,
8251029066,29067,29068,29069,29070,29071,29072,29073,29074,29075,29076,29077,
8251129078,29079,29080,29081,29082,29083,29084,29085,29086,29087,29088,29089,
8251229090,29091,29092,29093,29094,29095,29096,29097,29098,29099,29100,29101,
8251329102,29103,29104,29105,29106,29107,29108,29109,29110,29111,29112,29113,
8251429114,29115,29116,29117,29118,29119,29120,29121,29122,29123,29124,29125,
8251529126,29127,29128,29129,29130,29131,29132,29133,29134,29135,29136,29137,
8251629138,29139,29140,29141,29142,29143,29144,29145,29146,29147,29148,29149,
8251729150,29151,29152,29153,29154,29155,29156,29157,29158,29159,29160,29161,
8251829162,29163,29164,29165,29166,29167,29168,29169,29170,29171,29172,29173,
8251929174,29175,29176,29177,29178,29179,29180,29181,29182,29183,29184,29185,
8252029186,29187,29188,29189,29190,29191,29192,29193,29194,29195,29196,29197,
8252129198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,
8252229210,29211,29212,29213,29214,29215,29216,29217,29218,29219,29220,29221,
8252329222,29223,29224,29225,29226,29227,29228,29229,29230,29231,29232,29233,
8252429234,29235,29236,29237,29238,29239,29240,29241,29242,29243,29244,29245,
8252529246,29247,29248,29249,29250,29251,29252,29253,29254,29255,29256,29257,
8252629258,29259,29260,29261,29262,29263,29264,29265,29266,29267,29268,29269,
8252729270,29271,29272,29273,29274,29275,29276,29277,29278,29279,29280,29281,
8252829282,29283,29284,29285,29286,29287,29288,29289,29290,29291,29292,29293,
8252929294,29295,29296,29297,29298,29299,29300,29301,29302,29303,29304,29305,
8253029306,29307,29308,29309,29310,29311,29312,29313,29314,29315,29316,29317,
8253129318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,
8253229330,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,
8253329342,29343,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,
8253429354,29355,29356,29357,29358,29359,29360,29361,29362,29363,29364,29365,
8253529366,29367,29368,29369,29370,29371,29372,29373,29374,29375,29376,29377,
8253629378,29379,29380,29381,29382,29383,29384,29385,29386,29387,29388,29389,
8253729390,29391,29392,29393,29394,29395,29396,29397,29398,29399,29400,29401,
8253829402,29403,29404,29405,29406,29407,29408,29409,29410,29411,29412,29413,
8253929414,29415,29416,29417,29418,29419,29420,29421,29422,29423,29424,29425,
8254029426,29427,29428,29429,29430,29431,29432,29433,29434,29435,29436,29437,
8254129438,29439,29440,29441,29442,29443,29444,29445,29446,29447,29448,29449,
8254229450,29451,29452,29453,29454,29455,29456,29457,29458,29459,29460,29461,
8254329462,29463,29464,29465,29466,29467,29468,29469,29470,29471,29472,29473,
8254429474,29475,29476,29477,29478,29479,29480,29481,29482,29483,29484,29485,
8254529486,29487,29488,29489,29490,29491,29492,29493,29494,29495,29496,29497,
8254629498,29499,29500,29501,29502,29503,29504,29505,29506,29507,29508,29509,
8254729510,29511,29512,29513,29514,29515,29516,29517,29518,29519,29520,29521,
8254829522,29523,29524,29525,29526,29527,29528,29529,29530,29531,29532,29533,
8254929534,29535,29536,29537,29538,29539,29540,29541,29542,29543,29544,29545,
8255029546,29547,29548,29549,29550,29551,29552,29553,29554,29555,29556,29557,
8255129558,29559,29560,29561,29562,29563,29564,29565,29566,29567,29568,29569,
8255229570,29571,29572,29573,29574,29575,29576,29577,29578,29579,29580,29581,
8255329582,29583,29584,29585,29586,29587,29588,29589,29590,29591,29592,29593,
8255429594,29595,29596,29597,29598,29599,29600,29601,29602,29603,29604,29605,
8255529606,29607,29608,29609,29610,29611,29612,29613,29614,29615,29616,29617,
8255629618,29619,29620,29621,29622,29623,29624,29625,29626,29627,29628,29629,
8255729630,29631,29632,29633,29634,29635,29636,29637,29638,29639,29640,29641,
8255829642,29643,29644,29645,29646,29647,29648,29649,29650,29651,29652,29653,
8255929654,29655,29656,29657,29658,29659,29660,29661,29662,29663,29664,29665,
8256029666,29667,29668,29669,29670,29671,29672,29673,29674,29675,29676,29677,
8256129678,29679,29680,29681,29682,29683,29684,29685,29686,29687,29688,29689,
8256229690,29691,29692,29693,29694,29695,29696,29697,29698,29699,29700,29701,
8256329702,29703,29704,29705,29706,29707,29708,29709,29710,29711,29712,29713,
8256429714,29715,29716,29717,29718,29719,29720,29721,29722,29723,29724,29725,
8256529726,29727,29728,29729,29730,29731,29732,29733,29734,29735,29736,29737,
8256629738,29739,29740,29741,29742,29743,29744,29745,29746,29747,29748,29749,
8256729750,29751,29752,29753,29754,29755,29756,29757,29758,29759,29760,29761,
8256829762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,
8256929774,29775,29776,29777,29778,29779,29780,29781,29782,29783,29784,29785,
8257029786,29787,29788,29789,29790,29791,29792,29793,29794,29795,29796,29797,
8257129798,29799,29800,29801,29802,29803,29804,29805,29806,29807,29808,29809,
8257229810,29811,29812,29813,29814,29815,29816,29817,29818,29819,29820,29821,
8257329822,29823,29824,29825,29826,29827,29828,29829,29830,29831,29832,29833,
8257429834,29835,29836,29837,29838,29839,29840,29841,29842,29843,29844,29845,
8257529846,29847,29848,29849,29850,29851,29852,29853,29854,29855,29856,29857,
8257629858,29859,29860,29861,29862,29863,29864,29865,29866,29867,29868,29869,
8257729870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,
8257829882,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,
8257929894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,
8258029906,29907,29908,29909,29910,29911,29912,29913,29914,29915,29916,29917,
8258129918,29919,29920,29921,29922,29923,29924,29925,29926,29927,29928,29929,
8258229930,29931,29932,29933,29934,29935,29936,29937,29938,29939,29940,29941,
8258329942,29943,29944,29945,29946,29947,29948,29949,29950,29951,29952,29953,
8258429954,29955,29956,29957,29958,29959,29960,29961,29962,29963,29964,29965,
8258529966,29967,29968,29969,29970,29971,29972,29973,29974,29975,29976,29977,
8258629978,29979,29980,29981,29982,29983,29984,29985,29986,29987,29988,29989,
8258729990,29991,29992,29993,29994,29995,29996,29997,29998,29999,30000,30001,
8258830002,30003,30004,30005,30006,30007,30008,30009,30010,30011,30012,30013,
8258930014,30015,30016,30017,30018,30019,30020,30021,30022,30023,30024,30025,
8259030026,30027,30028,30029,30030,30031,30032,30033,30034,30035,30036,30037,
8259130038,30039,30040,30041,30042,30043,30044,30045,30046,30047,30048,30049,
8259230050,30051,30052,30053,30054,30055,30056,30057,30058,30059,30060,30061,
8259330062,30063,30064,30065,30066,30067,30068,30069,30070,30071,30072,30073,
8259430074,30075,30076,30077,30078,30079,30080,30081,30082,30083,30084,30085,
8259530086,30087,30088,30089,30090,30091,30092,30093,30094,30095,30096,30097,
8259630098,30099,30100,30101,30102,30103,30104,30105,30106,30107,30108,30109,
8259730110,30111,30112,30113,30114,30115,30116,30117,30118,30119,30120,30121,
8259830122,30123,30124,30125,30126,30127,30128,30129,30130,30131,30132,30133,
8259930134,30135,30136,30137,30138,30139,30140,30141,30142,30143,30144,30145,
8260030146,30147,30148,30149,30150,30151,30152,30153,30154,30155,30156,30157,
8260130158,30159,30160,30161,30162,30163,30164,30165,30166,30167,30168,30169,
8260230170,30171,30172,30173,30174,30175,30176,30177,30178,30179,30180,30181,
8260330182,30183,30184,30185,30186,30187,30188,30189,30190,30191,30192,30193,
8260430194,30195,30196,30197,30198,30199,30200,30201,30202,30203,30204,30205,
8260530206,30207,30208,30209,30210,30211,30212,30213,30214,30215,30216,30217,
8260630218,30219,30220,30221,30222,30223,30224,30225,30226,30227,30228,30229,
8260730230,30231,30232,30233,30234,30235,30236,30237,30238,30239,30240,30241,
8260830242,30243,30244,30245,30246,30247,30248,30249,30250,30251,30252,30253,
8260930254,30255,30256,30257,30258,30259,30260,30261,30262,30263,30264,30265,
8261030266,30267,30268,30269,30270,30271,30272,30273,30274,30275,30276,30277,
8261130278,30279,30280,30281,30282,30283,30284,30285,30286,30287,30288,30289,
8261230290,30291,30292,30293,30294,30295,30296,30297,30298,30299,30300,30301,
8261330302,30303,30304,30305,30306,30307,30308,30309,30310,30311,30312,30313,
8261430314,30315,30316,30317,30318,30319,30320,30321,30322,30323,30324,30325,
8261530326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,
8261630338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,
8261730350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,
8261830362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30372,30373,
8261930374,30375,30376,30377,30378,30379,30380,30381,30382,30383,30384,30385,
8262030386,30387,30388,30389,30390,30391,30392,30393,30394,30395,30396,30397,
8262130398,30399,30400,30401,30402,30403,30404,30405,30406,30407,30408,30409,
8262230410,30411,30412,30413,30414,30415,30416,30417,30418,30419,30420,30421,
8262330422,30423,30424,30425,30426,30427,30428,30429,30430,30431,30432,30433,
8262430434,30435,30436,30437,30438,30439,30440,30441,30442,30443,30444,30445,
8262530446,30447,30448,30449,30450,30451,30452,30453,30454,30455,30456,30457,
8262630458,30459,30460,30461,30462,30463,30464,30465,30466,30467,30468,30469,
8262730470,30471,30472,30473,30474,30475,30476,30477,30478,30479,30480,30481,
8262830482,30483,30484,30485,30486,30487,30488,30489,30490,30491,30492,30493,
8262930494,30495,30496,30497,30498,30499,30500,30501,30502,30503,30504,30505,
8263030506,30507,30508,30509,30510,30511,30512,30513,30514,30515,30516,30517,
8263130518,30519,30520,30521,30522,30523,30524,30525,30526,30527,30528,30529,
8263230530,30531,30532,30533,30534,30535,30536,30537,30538,30539,30540,30541,
8263330542,30543,30544,30545,30546,30547,30548,30549,30550,30551,30552,30553,
8263430554,30555,30556,30557,30558,30559,30560,30561,30562,30563,30564,30565,
8263530566,30567,30568,30569,30570,30571,30572,30573,30574,30575,30576,30577,
8263630578,30579,30580,30581,30582,30583,30584,30585,30586,30587,30588,30589,
8263730590,30591,30592,30593,30594,30595,30596,30597,30598,30599,30600,30601,
8263830602,30603,30604,30605,30606,30607,30608,30609,30610,30611,30612,30613,
8263930614,30615,30616,30617,30618,30619,30620,30621,30622,30623,30624,30625,
8264030626,30627,30628,30629,30630,30631,30632,30633,30634,30635,30636,30637,
8264130638,30639,30640,30641,30642,30643,30644,30645,30646,30647,30648,30649,
8264230650,30651,30652,30653,30654,30655,30656,30657,30658,30659,30660,30661,
8264330662,30663,30664,30665,30666,30667,30668,30669,30670,30671,30672,30673,
8264430674,30675,30676,30677,30678,30679,30680,30681,30682,30683,30684,30685,
8264530686,30687,30688,30689,30690,30691,30692,30693,30694,30695,30696,30697,
8264630698,30699,30700,30701,30702,30703,30704,30705,30706,30707,30708,30709,
8264730710,30711,30712,30713,30714,30715,30716,30717,30718,30719,30720,30721,
8264830722,30723,30724,30725,30726,30727,30728,30729,30730,30731,30732,30733,
8264930734,30735,30736,30737,30738,30739,30740,30741,30742,30743,30744,30745,
8265030746,30747,30748,30749,30750,30751,30752,30753,30754,30755,30756,30757,
8265130758,30759,30760,30761,30762,30763,30764,30765,30766,30767,30768,30769,
8265230770,30771,30772,30773,30774,30775,30776,30777,30778,30779,30780,30781,
8265330782,30783,30784,30785,30786,30787,30788,30789,30790,30791,30792,30793,
8265430794,30795,30796,30797,30798,30799,30800,30801,30802,30803,30804,30805,
8265530806,30807,30808,30809,30810,30811,30812,30813,30814,30815,30816,30817,
8265630818,30819,30820,30821,30822,30823,30824,30825,30826,30827,30828,30829,
8265730830,30831,30832,30833,30834,30835,30836,30837,30838,30839,30840,30841,
8265830842,30843,30844,30845,30846,30847,30848,30849,30850,30851,30852,30853,
8265930854,30855,30856,30857,30858,30859,30860,30861,30862,30863,30864,30865,
8266030866,30867,30868,30869,30870,30871,30872,30873,30874,30875,30876,30877,
8266130878,30879,30880,30881,30882,30883,30884,30885,30886,30887,30888,30889,
8266230890,30891,30892,30893,30894,30895,30896,30897,30898,30899,30900,30901,
8266330902,30903,30904,30905,30906,30907,30908,30909,30910,30911,30912,30913,
8266430914,30915,30916,30917,30918,30919,30920,30921,30922,30923,30924,30925,
8266530926,30927,30928,30929,30930,30931,30932,30933,30934,30935,30936,30937,
8266630938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,
8266730950,30951,30952,30953,30954,30955,30956,30957,30958,30959,30960,30961,
8266830962,30963,30964,30965,30966,30967,30968,30969,30970,30971,30972,30973,
8266930974,30975,30976,30977,30978,30979,30980,30981,30982,30983,30984,30985,
8267030986,30987,30988,30989,30990,30991,30992,30993,30994,30995,30996,30997,
8267130998,30999,31000,31001,31002,31003,31004,31005,31006,31007,31008,31009,
8267231010,31011,31012,31013,31014,31015,31016,31017,31018,31019,31020,31021,
8267331022,31023,31024,31025,31026,31027,31028,31029,31030,31031,31032,31033,
8267431034,31035,31036,31037,31038,31039,31040,31041,31042,31043,31044,31045,
8267531046,31047,31048,31049,31050,31051,31052,31053,31054,31055,31056,31057,
8267631058,31059,31060,31061,31062,31063,31064,31065,31066,31067,31068,31069,
8267731070,31071,31072,31073,31074,31075,31076,31077,31078,31079,31080,31081,
8267831082,31083,31084,31085,31086,31087,31088,31089,31090,31091,31092,31093,
8267931094,31095,31096,31097,31098,31099,31100,31101,31102,31103,31104,31105,
8268031106,31107,31108,31109,31110,31111,31112,31113,31114,31115,31116,31117,
8268131118,31119,31120,31121,31122,31123,31124,31125,31126,31127,31128,31129,
8268231130,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,
8268331142,31143,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,
8268431154,31155,31156,31157,31158,31159,31160,31161,31162,31163,31164,31165,
8268531166,31167,31168,31169,31170,31171,31172,31173,31174,31175,31176,31177,
8268631178,31179,31180,31181,31182,31183,31184,31185,31186,31187,31188,31189,
8268731190,31191,31192,31193,31194,31195,31196,31197,31198,31199,31200,31201,
8268831202,31203,31204,31205,31206,31207,31208,31209,31210,31211,31212,31213,
8268931214,31215,31216,31217,31218,31219,31220,31221,31222,31223,31224,31225,
8269031226,31227,31228,31229,31230,31231,31232,31233,31234,31235,31236,31237,
8269131238,31239,31240,31241,31242,31243,31244,31245,31246,31247,31248,31249,
8269231250,31251,31252,31253,31254,31255,31256,31257,31258,31259,31260,31261,
8269331262,31263,31264,31265,31266,31267,31268,31269,31270,31271,31272,31273,
8269431274,31275,31276,31277,31278,31279,31280,31281,31282,31283,31284,31285,
8269531286,31287,31288,31289,31290,31291,31292,31293,31294,31295,31296,31297,
8269631298,31299,31300,31301,31302,31303,31304,31305,31306,31307,31308,31309,
8269731310,31311,31312,31313,31314,31315,31316,31317,31318,31319,31320,31321,
8269831322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,
8269931334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31344,31345,
8270031346,31347,31348,31349,31350,31351,31352,31353,31354,31355,31356,31357,
8270131358,31359,31360,31361,31362,31363,31364,31365,31366,31367,31368,31369,
8270231370,31371,31372,31373,31374,31375,31376,31377,31378,31379,31380,31381,
8270331382,31383,31384,31385,31386,31387,31388,31389,31390,31391,31392,31393,
8270431394,31395,31396,31397,31398,31399,31400,31401,31402,31403,31404,31405,
8270531406,31407,31408,31409,31410,31411,31412,31413,31414,31415,31416,31417,
8270631418,31419,31420,31421,31422,31423,31424,31425,31426,31427,31428,31429,
8270731430,31431,31432,31433,31434,31435,31436,31437,31438,31439,31440,31441,
8270831442,31443,31444,31445,31446,31447,31448,31449,31450,31451,31452,31453,
8270931454,31455,31456,31457,31458,31459,31460,31461,31462,31463,31464,31465,
8271031466,31467,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,
8271131478,31479,31480,31481,31482,31483,31484,31485,31486,31487,31488,31489,
8271231490,31491,31492,31493,31494,31495,31496,31497,31498,31499,31500,31501,
8271331502,31503,31504,31505,31506,31507,31508,31509,31510,31511,31512,31513,
8271431514,31515,31516,31517,31518,31519,31520,31521,31522,31523,31524,31525,
8271531526,31527,31528,31529,31530,31531,31532,31533,31534,31535,31536,31537,
8271631538,31539,31540,31541,31542,31543,31544,31545,31546,31547,31548,31549,
8271731550,31551,31552,31553,31554,31555,31556,31557,31558,31559,31560,31561,
8271831562,31563,31564,31565,31566,31567,31568,31569,31570,31571,31572,31573,
8271931574,31575,31576,31577,31578,31579,31580,31581,31582,31583,31584,31585,
8272031586,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,
8272131598,31599,31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,
8272231610,31611,31612,31613,31614,31615,31616,31617,31618,31619,31620,31621,
8272331622,31623,31624,31625,31626,31627,31628,31629,31630,31631,31632,31633,
8272431634,31635,31636,31637,31638,31639,31640,31641,31642,31643,31644,31645,
8272531646,31647,31648,31649,31650,31651,31652,31653,31654,31655,31656,31657,
8272631658,31659,31660,31661,31662,31663,31664,31665,31666,31667,31668,31669,
8272731670,31671,31672,31673,31674,31675,31676,31677,31678,31679,31680,31681,
8272831682,31683,31684,31685,31686,31687,31688,31689,31690,31691,31692,31693,
8272931694,31695,31696,31697,31698,31699,31700,31701,31702,31703,31704,31705,
8273031706,31707,31708,31709,31710,31711,31712,31713,31714,31715,31716,31717,
8273131718,31719,31720,31721,31722,31723,31724,31725,31726,31727,31728,31729,
8273231730,31731,31732,31733,31734,31735,31736,31737,31738,31739,31740,31741,
8273331742,31743,31744,31745,31746,31747,31748,31749,31750,31751,31752,31753,
8273431754,31755,31756,31757,31758,31759,31760,31761,31762,31763,31764,31765,
8273531766,31767,31768,31769,31770,31771,31772,31773,31774,31775,31776,31777,
8273631778,31779,31780,31781,31782,31783,31784,31785,31786,31787,31788,31789,
8273731790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31800,31801,
8273831802,31803,31804,31805,31806,31807,31808,31809,31810,31811,31812,31813,
8273931814,31815,31816,31817,31818,31819,31820,31821,31822,31823,31824,31825,
8274031826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,
8274131838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,
8274231850,31851,31852,31853,31854,31855,31856,31857,31858,31859,31860,31861,
8274331862,31863,31864,31865,31866,31867,31868,31869,31870,31871,31872,31873,
8274431874,31875,31876,31877,31878,31879,31880,31881,31882,31883,31884,31885,
8274531886,31887,31888,31889,31890,31891,31892,31893,31894,31895,31896,31897,
8274631898,31899,31900,31901,31902,31903,31904,31905,31906,31907,31908,31909,
8274731910,31911,31912,31913,31914,31915,31916,31917,31918,31919,31920,31921,
8274831922,31923,31924,31925,31926,31927,31928,31929,31930,31931,31932,31933,
8274931934,31935,31936,31937,31938,31939,31940,31941,31942,31943,31944,31945,
8275031946,31947,31948,31949,31950,31951,31952,31953,31954,31955,31956,31957,
8275131958,31959,31960,31961,31962,31963,31964,31965,31966,31967,31968,31969,
8275231970,31971,31972,31973,31974,31975,31976,31977,31978,31979,31980,31981,
8275331982,31983,31984,31985,31986,31987,31988,31989,31990,31991,31992,31993,
8275431994,31995,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,
8275532006,32007,32008,32009,32010,32011,32012,32013,32014,32015,32016,32017,
8275632018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,
8275732030,32031,32032,32033,32034,32035,32036,32037,32038,32039,32040,32041,
8275832042,32043,32044,32045,32046,32047,32048,32049,32050,32051,32052,32053,
8275932054,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,
8276032066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,
8276132078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,
8276232090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,
8276332102,32103,32104,32105,32106,32107,32108,32109,32110,32111,32112,32113,
8276432114,32115,32116,32117,32118,32119,32120,32121,32122,32123,32124,32125,
8276532126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,
8276632138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,
8276732150,32151,32152,32153,32154,32155,32156,32157,32158,32159,32160,32161,
8276832162,32163,32164,32165,32166,32167,32168,32169,32170,32171,32172,32173,
8276932174,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,
8277032186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,
8277132198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,
8277232210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,
8277332222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,
8277432234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,
8277532246,32247,32248,32249,32250,32251,32252,32253,32254,32255,32256,32257,
8277632258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,
8277732270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,
8277832282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,
8277932294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,
8278032306,32307,32308,32309,32310,32311,32312,32313,32314,32315,32316,32317,
8278132318,32319,32320,32321,32322,32323,32324,32325,32326,32327,32328,32329,
8278232330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,
8278332342,32343,32344,32345,32346,32347,32348,32349,32350,32351,32352,32353,
8278432354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,
8278532366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,
8278632378,32379,32380,32381,32382,32383,32384,32385,32386,32387,32388,32389,
8278732390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,
8278832402,32403,32404,32405,32406,32407,32408,32409,32410,32411,32412,32413,
8278932414,32415,32416,32417,32418,32419,32420,32421,32422,32423,32424,32425,
8279032426,32427,32428,32429,32430,32431,32432,32433,32434,32435,32436,32437,
8279132438,32439,32440,32441,32442,32443,32444,32445,32446,32447,32448,32449,
8279232450,32451,32452,32453,32454,32455,32456,32457,32458,32459,32460,32461,
8279332462,32463,32464,32465,32466,32467,32468,32469,32470,32471,32472,32473,
8279432474,32475,32476,32477,32478,32479,32480,32481,32482,32483,32484,32485,
8279532486,32487,32488,32489,32490,32491,32492,32493,32494,32495,32496,32497,
8279632498,32499,32500,32501,32502,32503,32504,32505,32506,32507,32508,32509,
8279732510,32511,32512,32513,32514,32515,32516,32517,32518,32519,32520,32521,
8279832522,32523,32524,32525,32526,32527,32528,32529,32530,32531,32532,32533,
8279932534,32535,32536,32537,32538,32539,32540,32541,32542,32543,32544,32545,
8280032546,32547,32548,32549,32550,32551,32552,32553,32554,32555,32556,32557,
8280132558,32559,32560,32561,32562,32563,32564,32565,32566,32567,32568,32569,
8280232570,32571,32572,32573,32574,32575,32576,32577,32578,32579,32580,32581,
8280332582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32592,32593,
8280432594,32595,32596,32597,32598,32599,32600,32601,32602,32603,32604,32605,
8280532606,32607,32608,32609,32610,32611,32612,32613,32614,32615,32616,32617,
8280632618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,
8280732630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,
8280832642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,
8280932654,32655,32656,32657,32658,32659,32660,32661,32662,32663,32664,32665,
8281032666,32667,32668,32669,32670,32671,32672,32673,32674,32675,32676,32677,
8281132678,32679,32680,32681,32682,32683,32684,32685,32686,32687,32688,32689,
8281232690,32691,32692,32693,32694,32695,32696,32697,32698,32699,32700,32701,
8281332702,32703,32704,32705,32706,32707,32708,32709,32710,32711,32712,32713,
8281432714,32715,32716,32717,32718,32719,32720,32721,32722,32723,32724,32725,
8281532726,32727,32728,32729,32730,32731,32732,32733,32734,32735,32736,32737,
8281632738,32739,32740,32741,32742,32743,32744,32745,32746,32747,32748,32749,
8281732750,32751,32752,32753,32754,32755,32756,32757,32758,32759,32760,32761,
8281832762,32763,32764,32765,32766,32767,32768L,32769L,32770L,32771L,32772L,
8281932773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,32781L,32782L,
8282032783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,32791L,32792L,
8282132793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,32801L,32802L,
8282232803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,32811L,32812L,
8282332813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,32821L,32822L,
8282432823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,32831L,32832L,
8282532833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,32841L,32842L,
8282632843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,32851L,32852L,
8282732853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,32861L,32862L,
8282832863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,32871L,32872L,
8282932873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,32881L,32882L,
8283032883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,32891L,32892L,
8283132893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,32901L,32902L,
8283232903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,32911L,32912L,
8283332913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,32921L,32922L,
8283432923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,32931L,32932L,
8283532933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,32941L,32942L,
8283632943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,32951L,32952L,
8283732953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,32961L,32962L,
8283832963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,32971L,32972L,
8283932973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,32981L,32982L,
8284032983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,32991L,32992L,
8284132993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,33001L,33002L,
8284233003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,33011L,33012L,
8284333013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,33021L,33022L,
8284433023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,33031L,33032L,
8284533033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,33041L,33042L,
8284633043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,33051L,33052L,
8284733053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,33061L,33062L,
8284833063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,33071L,33072L,
8284933073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,33081L,33082L,
8285033083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,33091L,33092L,
8285133093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,33101L,33102L,
8285233103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,33111L,33112L,
8285333113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,33121L,33122L,
8285433123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,33131L,33132L,
8285533133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,33141L,33142L,
8285633143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,33151L,33152L,
8285733153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,33161L,33162L,
8285833163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,33171L,33172L,
8285933173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,33181L,33182L,
8286033183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,33191L,33192L,
8286133193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,33201L,33202L,
8286233203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,33211L,33212L,
8286333213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,33221L,33222L,
8286433223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,33231L,33232L,
8286533233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,33241L,33242L,
8286633243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,33251L,33252L,
8286733253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,33261L,33262L,
8286833263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,33271L,33272L,
8286933273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,33281L,33282L,
8287033283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,33291L,33292L,
8287133293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,33301L,33302L,
8287233303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,33311L,33312L,
8287333313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,33321L,33322L,
8287433323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,33331L,33332L,
8287533333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,33341L,33342L,
8287633343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,33351L,33352L,
8287733353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,33361L,33362L,
8287833363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,33371L,33372L,
8287933373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,33381L,33382L,
8288033383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,33391L,33392L,
8288133393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,33401L,33402L,
8288233403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,33411L,33412L,
8288333413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,33421L,33422L,
8288433423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,33431L,33432L,
8288533433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,33441L,33442L,
8288633443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,33451L,33452L,
8288733453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,33461L,33462L,
8288833463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,33471L,33472L,
8288933473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,33481L,33482L,
8289033483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,33491L,33492L,
8289133493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,33501L,33502L,
8289233503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,33511L,33512L,
8289333513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,33521L,33522L,
8289433523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,33531L,33532L,
8289533533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,33541L,33542L,
8289633543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,33551L,33552L,
8289733553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,33561L,33562L,
8289833563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,33571L,33572L,
8289933573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,33581L,33582L,
8290033583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,33591L,33592L,
8290133593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,33601L,33602L,
8290233603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,33611L,33612L,
8290333613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,33621L,33622L,
8290433623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,33631L,33632L,
8290533633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,33641L,33642L,
8290633643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,33651L,33652L,
8290733653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,33661L,33662L,
8290833663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,33671L,33672L,
8290933673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,33681L,33682L,
8291033683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,33691L,33692L,
8291133693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,33701L,33702L,
8291233703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,33711L,33712L,
8291333713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,33721L,33722L,
8291433723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,33731L,33732L,
8291533733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,33741L,33742L,
8291633743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,33751L,33752L,
8291733753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,33761L,33762L,
8291833763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,33771L,33772L,
8291933773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,33781L,33782L,
8292033783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,33791L,33792L,
8292133793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,33801L,33802L,
8292233803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,33811L,33812L,
8292333813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,33821L,33822L,
8292433823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,33831L,33832L,
8292533833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,33841L,33842L,
8292633843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,33851L,33852L,
8292733853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,33861L,33862L,
8292833863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,33871L,33872L,
8292933873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,33881L,33882L,
8293033883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,33891L,33892L,
8293133893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,33901L,33902L,
8293233903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,33911L,33912L,
8293333913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,33921L,33922L,
8293433923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,33931L,33932L,
8293533933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,33941L,33942L,
8293633943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,33951L,33952L,
8293733953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,33961L,33962L,
8293833963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,33971L,33972L,
8293933973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,33981L,33982L,
8294033983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,33991L,33992L,
8294133993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,34001L,34002L,
8294234003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,34011L,34012L,
8294334013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,34021L,34022L,
8294434023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,34031L,34032L,
8294534033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,34041L,34042L,
8294634043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,34051L,34052L,
8294734053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,34061L,34062L,
8294834063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,34071L,34072L,
8294934073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,34081L,34082L,
8295034083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,34091L,34092L,
8295134093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,34101L,34102L,
8295234103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,34111L,34112L,
8295334113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,34121L,34122L,
8295434123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,34131L,34132L,
8295534133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,34141L,34142L,
8295634143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,34151L,34152L,
8295734153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,34161L,34162L,
8295834163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,34171L,34172L,
8295934173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,34181L,34182L,
8296034183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,34191L,34192L,
8296134193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,34201L,34202L,
8296234203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,34211L,34212L,
8296334213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,34221L,34222L,
8296434223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,34231L,34232L,
8296534233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,34241L,34242L,
8296634243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,34251L,34252L,
8296734253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,34261L,34262L,
8296834263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,34271L,34272L,
8296934273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,34281L,34282L,
8297034283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,34291L,34292L,
8297134293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,34301L,34302L,
8297234303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,34311L,34312L,
8297334313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,34321L,34322L,
8297434323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,34331L,34332L,
8297534333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,34341L,34342L,
8297634343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,34351L,34352L,
8297734353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,34361L,34362L,
8297834363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,34371L,34372L,
8297934373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,34381L,34382L,
8298034383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,34391L,34392L,
8298134393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,34401L,34402L,
8298234403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,34411L,34412L,
8298334413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,34421L,34422L,
8298434423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,34431L,34432L,
8298534433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,34441L,34442L,
8298634443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,34451L,34452L,
8298734453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,34461L,34462L,
8298834463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,34471L,34472L,
8298934473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,34481L,34482L,
8299034483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,34491L,34492L,
8299134493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,34501L,34502L,
8299234503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,34511L,34512L,
8299334513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,34521L,34522L,
8299434523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,34531L,34532L,
8299534533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,34541L,34542L,
8299634543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,34551L,34552L,
8299734553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,34561L,34562L,
8299834563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,34571L,34572L,
8299934573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,34581L,34582L,
8300034583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,34591L,34592L,
8300134593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,34601L,34602L,
8300234603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,34611L,34612L,
8300334613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,34621L,34622L,
8300434623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,34631L,34632L,
8300534633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,34641L,34642L,
8300634643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,34651L,34652L,
8300734653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,34661L,34662L,
8300834663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,34671L,34672L,
8300934673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,34681L,34682L,
8301034683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,34691L,34692L,
8301134693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,34701L,34702L,
8301234703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,34711L,34712L,
8301334713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,34721L,34722L,
8301434723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,34731L,34732L,
8301534733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,34741L,34742L,
8301634743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,34751L,34752L,
8301734753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,34761L,34762L,
8301834763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,34771L,34772L,
8301934773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,34781L,34782L,
8302034783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,34791L,34792L,
8302134793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,34801L,34802L,
8302234803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,34811L,34812L,
8302334813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,34821L,34822L,
8302434823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,34831L,34832L,
8302534833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,34841L,34842L,
8302634843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,34851L,34852L,
8302734853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,34861L,34862L,
8302834863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,34871L,34872L,
8302934873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,34881L,34882L,
8303034883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,34891L,34892L,
8303134893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,34901L,34902L,
8303234903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,34911L,34912L,
8303334913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,34921L,34922L,
8303434923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,34931L,34932L,
8303534933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,34941L,34942L,
8303634943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,34951L,34952L,
8303734953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,34961L,34962L,
8303834963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,34971L,34972L,
8303934973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,34981L,34982L,
8304034983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,34991L,34992L,
8304134993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,35001L,35002L,
8304235003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,35011L,35012L,
8304335013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,35021L,35022L,
8304435023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,35031L,35032L,
8304535033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,35041L,35042L,
8304635043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,35051L,35052L,
8304735053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,35061L,35062L,
8304835063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,35071L,35072L,
8304935073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,35081L,35082L,
8305035083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,35091L,35092L,
8305135093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,35101L,35102L,
8305235103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,35111L,35112L,
8305335113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,35121L,35122L,
8305435123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,35131L,35132L,
8305535133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,35141L,35142L,
8305635143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,35151L,35152L,
8305735153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,35161L,35162L,
8305835163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,35171L,35172L,
8305935173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,35181L,35182L,
8306035183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,35191L,35192L,
8306135193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,35201L,35202L,
8306235203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,35211L,35212L,
8306335213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,35221L,35222L,
8306435223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,35231L,35232L,
8306535233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,35241L,35242L,
8306635243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,35251L,35252L,
8306735253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,35261L,35262L,
8306835263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,35271L,35272L,
8306935273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,35281L,35282L,
8307035283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,35291L,35292L,
8307135293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,35301L,35302L,
8307235303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,35311L,35312L,
8307335313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,35321L,35322L,
8307435323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,35331L,35332L,
8307535333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,35341L,35342L,
8307635343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,35351L,35352L,
8307735353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,35361L,35362L,
8307835363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,35371L,35372L,
8307935373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,35381L,35382L,
8308035383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,35391L,35392L,
8308135393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,35401L,35402L,
8308235403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,35411L,35412L,
8308335413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,35421L,35422L,
8308435423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,35431L,35432L,
8308535433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,35441L,35442L,
8308635443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,35451L,35452L,
8308735453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,35461L,35462L,
8308835463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,35471L,35472L,
8308935473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,35481L,35482L,
8309035483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,35491L,35492L,
8309135493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,35501L,35502L,
8309235503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,35511L,35512L,
8309335513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,35521L,35522L,
8309435523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,35531L,35532L,
8309535533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,35541L,35542L,
8309635543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,35551L,35552L,
8309735553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,35561L,35562L,
8309835563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,35571L,35572L,
8309935573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,35581L,35582L,
8310035583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,35591L,35592L,
8310135593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,35601L,35602L,
8310235603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,35611L,35612L,
8310335613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,35621L,35622L,
8310435623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,35631L,35632L,
8310535633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,35641L,35642L,
8310635643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,35651L,35652L,
8310735653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,35661L,35662L,
8310835663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,35671L,35672L,
8310935673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,35681L,35682L,
8311035683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,35691L,35692L,
8311135693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,35701L,35702L,
8311235703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,35711L,35712L,
8311335713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,35721L,35722L,
8311435723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,35731L,35732L,
8311535733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,35741L,35742L,
8311635743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,35751L,35752L,
8311735753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,35761L,35762L,
8311835763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,35771L,35772L,
8311935773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,35781L,35782L,
8312035783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,35791L,35792L,
8312135793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,35801L,35802L,
8312235803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,35811L,35812L,
8312335813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,35821L,35822L,
8312435823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,35831L,35832L,
8312535833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,35841L,35842L,
8312635843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,35851L,35852L,
8312735853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,35861L,35862L,
8312835863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,35871L,35872L,
8312935873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,35881L,35882L,
8313035883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,35891L,35892L,
8313135893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,35901L,35902L,
8313235903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,35911L,35912L,
8313335913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,35921L,35922L,
8313435923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,35931L,35932L,
8313535933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,35941L,35942L,
8313635943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,35951L,35952L,
8313735953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,35961L,35962L,
8313835963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,35971L,35972L,
8313935973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,35981L,35982L,
8314035983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,35991L,35992L,
8314135993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,36001L,36002L,
8314236003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,36011L,36012L,
8314336013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,36021L,36022L,
8314436023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,36031L,36032L,
8314536033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,36041L,36042L,
8314636043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,36051L,36052L,
8314736053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,36061L,36062L,
8314836063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,36071L,36072L,
8314936073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,36081L,36082L,
8315036083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,36091L,36092L,
8315136093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,36101L,36102L,
8315236103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,36111L,36112L,
8315336113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,36121L,36122L,
8315436123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,36131L,36132L,
8315536133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,36141L,36142L,
8315636143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,36151L,36152L,
8315736153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,36161L,36162L,
8315836163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,36171L,36172L,
8315936173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,36181L,36182L,
8316036183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,36191L,36192L,
8316136193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,36201L,36202L,
8316236203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,36211L,36212L,
8316336213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,36221L,36222L,
8316436223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,36231L,36232L,
8316536233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,36241L,36242L,
8316636243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,36251L,36252L,
8316736253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,36261L,36262L,
8316836263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,36271L,36272L,
8316936273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,36281L,36282L,
8317036283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,36291L,36292L,
8317136293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,36301L,36302L,
8317236303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,36311L,36312L,
8317336313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,36321L,36322L,
8317436323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,36331L,36332L,
8317536333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,36341L,36342L,
8317636343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,36351L,36352L,
8317736353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,36361L,36362L,
8317836363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,36371L,36372L,
8317936373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,36381L,36382L,
8318036383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,36391L,36392L,
8318136393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,36401L,36402L,
8318236403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,36411L,36412L,
8318336413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,36421L,36422L,
8318436423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,36431L,36432L,
8318536433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,36441L,36442L,
8318636443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,36451L,36452L,
8318736453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,36461L,36462L,
8318836463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,36471L,36472L,
8318936473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,36481L,36482L,
8319036483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,36491L,36492L,
8319136493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,36501L,36502L,
8319236503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,36511L,36512L,
8319336513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,36521L,36522L,
8319436523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,36531L,36532L,
8319536533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,36541L,36542L,
8319636543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,36551L,36552L,
8319736553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,36561L,36562L,
8319836563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,36571L,36572L,
8319936573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,36581L,36582L,
8320036583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,36591L,36592L,
8320136593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,36601L,36602L,
8320236603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,36611L,36612L,
8320336613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,36621L,36622L,
8320436623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,36631L,36632L,
8320536633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,36641L,36642L,
8320636643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,36651L,36652L,
8320736653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,36661L,36662L,
8320836663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,36671L,36672L,
8320936673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,36681L,36682L,
8321036683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,36691L,36692L,
8321136693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,36701L,36702L,
8321236703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,36711L,36712L,
8321336713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,36721L,36722L,
8321436723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,36731L,36732L,
8321536733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,36741L,36742L,
8321636743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,36751L,36752L,
8321736753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,36761L,36762L,
8321836763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,36771L,36772L,
8321936773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,36781L,36782L,
8322036783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,36791L,36792L,
8322136793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,36801L,36802L,
8322236803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,36811L,36812L,
8322336813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,36821L,36822L,
8322436823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,36831L,36832L,
8322536833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,36841L,36842L,
8322636843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,36851L,36852L,
8322736853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,36861L,36862L,
8322836863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,36871L,36872L,
8322936873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,36881L,36882L,
8323036883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,36891L,36892L,
8323136893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,36901L,36902L,
8323236903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,36911L,36912L,
8323336913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,36921L,36922L,
8323436923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,36931L,36932L,
8323536933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,36941L,36942L,
8323636943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,36951L,36952L,
8323736953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,36961L,36962L,
8323836963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,36971L,36972L,
8323936973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,36981L,36982L,
8324036983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,36991L,36992L,
8324136993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,37001L,37002L,
8324237003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,37011L,37012L,
8324337013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,37021L,37022L,
8324437023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,37031L,37032L,
8324537033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,37041L,37042L,
8324637043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,37051L,37052L,
8324737053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,37061L,37062L,
8324837063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,37071L,37072L,
8324937073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,37081L,37082L,
8325037083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,37091L,37092L,
8325137093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,37101L,37102L,
8325237103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,37111L,37112L,
8325337113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,37121L,37122L,
8325437123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,37131L,37132L,
8325537133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,37141L,37142L,
8325637143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,37151L,37152L,
8325737153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,37161L,37162L,
8325837163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,37171L,37172L,
8325937173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,37181L,37182L,
8326037183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,37191L,37192L,
8326137193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,37201L,37202L,
8326237203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,37211L,37212L,
8326337213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,37221L,37222L,
8326437223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,37231L,37232L,
8326537233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,37241L,37242L,
8326637243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,37251L,37252L,
8326737253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,37261L,37262L,
8326837263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,37271L,37272L,
8326937273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,37281L,37282L,
8327037283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,37291L,37292L,
8327137293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,37301L,37302L,
8327237303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,37311L,37312L,
8327337313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,37321L,37322L,
8327437323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,37331L,37332L,
8327537333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,37341L,37342L,
8327637343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,37351L,37352L,
8327737353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,37361L,37362L,
8327837363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,37371L,37372L,
8327937373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,37381L,37382L,
8328037383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,37391L,37392L,
8328137393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,37401L,37402L,
8328237403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,37411L,37412L,
8328337413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,37421L,37422L,
8328437423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,37431L,37432L,
8328537433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,37441L,37442L,
8328637443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,37451L,37452L,
8328737453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,37461L,37462L,
8328837463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,37471L,37472L,
8328937473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,37481L,37482L,
8329037483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,37491L,37492L,
8329137493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,37501L,37502L,
8329237503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,37511L,37512L,
8329337513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,37521L,37522L,
8329437523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,37531L,37532L,
8329537533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,37541L,37542L,
8329637543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,37551L,37552L,
8329737553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,37561L,37562L,
8329837563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,37571L,37572L,
8329937573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,37581L,37582L,
8330037583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,37591L,37592L,
8330137593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,37601L,37602L,
8330237603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,37611L,37612L,
8330337613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,37621L,37622L,
8330437623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,37631L,37632L,
8330537633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,37641L,37642L,
8330637643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,37651L,37652L,
8330737653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,37661L,37662L,
8330837663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,37671L,37672L,
8330937673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,37681L,37682L,
8331037683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,37691L,37692L,
8331137693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,37701L,37702L,
8331237703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,37711L,37712L,
8331337713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,37721L,37722L,
8331437723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,37731L,37732L,
8331537733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,37741L,37742L,
8331637743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,37751L,37752L,
8331737753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,37761L,37762L,
8331837763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,37771L,37772L,
8331937773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,37781L,37782L,
8332037783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,37791L,37792L,
8332137793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,37801L,37802L,
8332237803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,37811L,37812L,
8332337813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,37821L,37822L,
8332437823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,37831L,37832L,
8332537833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,37841L,37842L,
8332637843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,37851L,37852L,
8332737853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,37861L,37862L,
8332837863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,37871L,37872L,
8332937873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,37881L,37882L,
8333037883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,37891L,37892L,
8333137893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,37901L,37902L,
8333237903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,37911L,37912L,
8333337913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,37921L,37922L,
8333437923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,37931L,37932L,
8333537933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,37941L,37942L,
8333637943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,37951L,37952L,
8333737953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,37961L,37962L,
8333837963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,37971L,37972L,
8333937973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,37981L,37982L,
8334037983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,37991L,37992L,
8334137993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,38001L,38002L,
8334238003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,38011L,38012L,
8334338013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,38021L,38022L,
8334438023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,38031L,38032L,
8334538033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,38041L,38042L,
8334638043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,38051L,38052L,
8334738053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,38061L,38062L,
8334838063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,38071L,38072L,
8334938073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,38081L,38082L,
8335038083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,38091L,38092L,
8335138093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,38101L,38102L,
8335238103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,38111L,38112L,
8335338113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,38121L,38122L,
8335438123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,38131L,38132L,
8335538133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,38141L,38142L,
8335638143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,38151L,38152L,
8335738153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,38161L,38162L,
8335838163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,38171L,38172L,
8335938173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,38181L,38182L,
8336038183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,38191L,38192L,
8336138193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,38201L,38202L,
8336238203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,38211L,38212L,
8336338213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,38221L,38222L,
8336438223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,38231L,38232L,
8336538233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,38241L,38242L,
8336638243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,38251L,38252L,
8336738253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,38261L,38262L,
8336838263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,38271L,38272L,
8336938273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,38281L,38282L,
8337038283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,38291L,38292L,
8337138293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,38301L,38302L,
8337238303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,38311L,38312L,
8337338313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,38321L,38322L,
8337438323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,38331L,38332L,
8337538333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,38341L,38342L,
8337638343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,38351L,38352L,
8337738353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,38361L,38362L,
8337838363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,38371L,38372L,
8337938373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,38381L,38382L,
8338038383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,38391L,38392L,
8338138393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,38401L,38402L,
8338238403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,38411L,38412L,
8338338413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,38421L,38422L,
8338438423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,38431L,38432L,
8338538433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,38441L,38442L,
8338638443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,38451L,38452L,
8338738453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,38461L,38462L,
8338838463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,38471L,38472L,
8338938473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,38481L,38482L,
8339038483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,38491L,38492L,
8339138493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,38501L,38502L,
8339238503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,38511L,38512L,
8339338513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,38521L,38522L,
8339438523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,38531L,38532L,
8339538533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,38541L,38542L,
8339638543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,38551L,38552L,
8339738553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,38561L,38562L,
8339838563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,38571L,38572L,
8339938573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,38581L,38582L,
8340038583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,38591L,38592L,
8340138593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,38601L,38602L,
8340238603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,38611L,38612L,
8340338613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,38621L,38622L,
8340438623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,38631L,38632L,
8340538633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,38641L,38642L,
8340638643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,38651L,38652L,
8340738653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,38661L,38662L,
8340838663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,38671L,38672L,
8340938673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,38681L,38682L,
8341038683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,38691L,38692L,
8341138693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,38701L,38702L,
8341238703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,38711L,38712L,
8341338713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,38721L,38722L,
8341438723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,38731L,38732L,
8341538733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,38741L,38742L,
8341638743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,38751L,38752L,
8341738753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,38761L,38762L,
8341838763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,38771L,38772L,
8341938773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,38781L,38782L,
8342038783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,38791L,38792L,
8342138793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,38801L,38802L,
8342238803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,38811L,38812L,
8342338813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,38821L,38822L,
8342438823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,38831L,38832L,
8342538833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,38841L,38842L,
8342638843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,38851L,38852L,
8342738853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,38861L,38862L,
8342838863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,38871L,38872L,
8342938873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,38881L,38882L,
8343038883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,38891L,38892L,
8343138893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,38901L,38902L,
8343238903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,38911L,38912L,
8343338913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,38921L,38922L,
8343438923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,38931L,38932L,
8343538933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,38941L,38942L,
8343638943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,38951L,38952L,
8343738953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,38961L,38962L,
8343838963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,38971L,38972L,
8343938973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,38981L,38982L,
8344038983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,38991L,38992L,
8344138993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,39001L,39002L,
8344239003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,39011L,39012L,
8344339013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,39021L,39022L,
8344439023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,39031L,39032L,
8344539033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,39041L,39042L,
8344639043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,39051L,39052L,
8344739053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,39061L,39062L,
8344839063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,39071L,39072L,
8344939073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,39081L,39082L,
8345039083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,39091L,39092L,
8345139093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,39101L,39102L,
8345239103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,39111L,39112L,
8345339113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,39121L,39122L,
8345439123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,39131L,39132L,
8345539133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,39141L,39142L,
8345639143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,39151L,39152L,
8345739153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,39161L,39162L,
8345839163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,39171L,39172L,
8345939173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,39181L,39182L,
8346039183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,39191L,39192L,
8346139193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,39201L,39202L,
8346239203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,39211L,39212L,
8346339213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,39221L,39222L,
8346439223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,39231L,39232L,
8346539233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,39241L,39242L,
8346639243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,39251L,39252L,
8346739253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,39261L,39262L,
8346839263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,39271L,39272L,
8346939273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,39281L,39282L,
8347039283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,39291L,39292L,
8347139293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,39301L,39302L,
8347239303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,39311L,39312L,
8347339313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,39321L,39322L,
8347439323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,39331L,39332L,
8347539333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,39341L,39342L,
8347639343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,39351L,39352L,
8347739353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,39361L,39362L,
8347839363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,39371L,39372L,
8347939373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,39381L,39382L,
8348039383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,39391L,39392L,
8348139393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,39401L,39402L,
8348239403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,39411L,39412L,
8348339413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,39421L,39422L,
8348439423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,39431L,39432L,
8348539433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,39441L,39442L,
8348639443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,39451L,39452L,
8348739453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,39461L,39462L,
8348839463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,39471L,39472L,
8348939473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,39481L,39482L,
8349039483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,39491L,39492L,
8349139493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,39501L,39502L,
8349239503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,39511L,39512L,
8349339513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,39521L,39522L,
8349439523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,39531L,39532L,
8349539533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,39541L,39542L,
8349639543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,39551L,39552L,
8349739553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,39561L,39562L,
8349839563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,39571L,39572L,
8349939573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,39581L,39582L,
8350039583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,39591L,39592L,
8350139593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,39601L,39602L,
8350239603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,39611L,39612L,
8350339613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,39621L,39622L,
8350439623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,39631L,39632L,
8350539633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,39641L,39642L,
8350639643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,39651L,39652L,
8350739653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,39661L,39662L,
8350839663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,39671L,39672L,
8350939673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,39681L,39682L,
8351039683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,39691L,39692L,
8351139693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,39701L,39702L,
8351239703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,39711L,39712L,
8351339713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,39721L,39722L,
8351439723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,39731L,39732L,
8351539733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,39741L,39742L,
8351639743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,39751L,39752L,
8351739753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,39761L,39762L,
8351839763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,39771L,39772L,
8351939773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,39781L,39782L,
8352039783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,39791L,39792L,
8352139793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,39801L,39802L,
8352239803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,39811L,39812L,
8352339813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,39821L,39822L,
8352439823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,39831L,39832L,
8352539833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,39841L,39842L,
8352639843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,39851L,39852L,
8352739853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,39861L,39862L,
8352839863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,39871L,39872L,
8352939873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,39881L,39882L,
8353039883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,39891L,39892L,
8353139893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,39901L,39902L,
8353239903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,39911L,39912L,
8353339913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,39921L,39922L,
8353439923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,39931L,39932L,
8353539933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,39941L,39942L,
8353639943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,39951L,39952L,
8353739953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,39961L,39962L,
8353839963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,39971L,39972L,
8353939973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,39981L,39982L,
8354039983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,39991L,39992L,
8354139993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,40001L,40002L,
8354240003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,40011L,40012L,
8354340013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,40021L,40022L,
8354440023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,40031L,40032L,
8354540033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,40041L,40042L,
8354640043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,40051L,40052L,
8354740053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,40061L,40062L,
8354840063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,40071L,40072L,
8354940073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,40081L,40082L,
8355040083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,40091L,40092L,
8355140093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,40101L,40102L,
8355240103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,40111L,40112L,
8355340113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,40121L,40122L,
8355440123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,40131L,40132L,
8355540133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,40141L,40142L,
8355640143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,40151L,40152L,
8355740153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,40161L,40162L,
8355840163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,40171L,40172L,
8355940173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,40181L,40182L,
8356040183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,40191L,40192L,
8356140193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,40201L,40202L,
8356240203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,40211L,40212L,
8356340213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,40221L,40222L,
8356440223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,40231L,40232L,
8356540233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,40241L,40242L,
8356640243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,40251L,40252L,
8356740253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,40261L,40262L,
8356840263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,40271L,40272L,
8356940273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,40281L,40282L,
8357040283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,40291L,40292L,
8357140293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,40301L,40302L,
8357240303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,40311L,40312L,
8357340313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,40321L,40322L,
8357440323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,40331L,40332L,
8357540333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,40341L,40342L,
8357640343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,40351L,40352L,
8357740353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,40361L,40362L,
8357840363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,40371L,40372L,
8357940373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,40381L,40382L,
8358040383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,40391L,40392L,
8358140393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,40401L,40402L,
8358240403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,40411L,40412L,
8358340413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,40421L,40422L,
8358440423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,40431L,40432L,
8358540433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,40441L,40442L,
8358640443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,40451L,40452L,
8358740453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,40461L,40462L,
8358840463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,40471L,40472L,
8358940473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,40481L,40482L,
8359040483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,40491L,40492L,
8359140493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,40501L,40502L,
8359240503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,40511L,40512L,
8359340513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,40521L,40522L,
8359440523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,40531L,40532L,
8359540533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,40541L,40542L,
8359640543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,40551L,40552L,
8359740553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,40561L,40562L,
8359840563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,40571L,40572L,
8359940573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,40581L,40582L,
8360040583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,40591L,40592L,
8360140593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,40601L,40602L,
8360240603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,40611L,40612L,
8360340613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,40621L,40622L,
8360440623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,40631L,40632L,
8360540633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,40641L,40642L,
8360640643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,40651L,40652L,
8360740653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,40661L,40662L,
8360840663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,40671L,40672L,
8360940673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,40681L,40682L,
8361040683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,40691L,40692L,
8361140693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,40701L,40702L,
8361240703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,40711L,40712L,
8361340713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,40721L,40722L,
8361440723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,40731L,40732L,
8361540733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,40741L,40742L,
8361640743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,40751L,40752L,
8361740753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,40761L,40762L,
8361840763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,40771L,40772L,
8361940773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,40781L,40782L,
8362040783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,40791L,40792L,
8362140793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,40801L,40802L,
8362240803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,40811L,40812L,
8362340813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,40821L,40822L,
8362440823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,40831L,40832L,
8362540833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,40841L,40842L,
8362640843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,40851L,40852L,
8362740853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,40861L,40862L,
8362840863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,40871L,40872L,
8362940873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,40881L,40882L,
8363040883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,40891L,40892L,
8363140893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,40901L,40902L,
8363240903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,40911L,40912L,
8363340913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,40921L,40922L,
8363440923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,40931L,40932L,
8363540933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,40941L,40942L,
8363640943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,40951L,40952L,
8363740953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,40961L,40962L,
8363840963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,40971L,40972L,
8363940973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,40981L,40982L,
8364040983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,40991L,40992L,
8364140993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,41001L,41002L,
8364241003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,41011L,41012L,
8364341013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,41021L,41022L,
8364441023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,41031L,41032L,
8364541033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,41041L,41042L,
8364641043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,41051L,41052L,
8364741053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,41061L,41062L,
8364841063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,41071L,41072L,
8364941073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,41081L,41082L,
8365041083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,41091L,41092L,
8365141093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,41101L,41102L,
8365241103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,41111L,41112L,
8365341113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,41121L,41122L,
8365441123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,41131L,41132L,
8365541133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,41141L,41142L,
8365641143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,41151L,41152L,
8365741153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,41161L,41162L,
8365841163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,41171L,41172L,
8365941173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,41181L,41182L,
8366041183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,41191L,41192L,
8366141193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,41201L,41202L,
8366241203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,41211L,41212L,
8366341213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,41221L,41222L,
8366441223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,41231L,41232L,
8366541233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,41241L,41242L,
8366641243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,41251L,41252L,
8366741253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,41261L,41262L,
8366841263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,41271L,41272L,
8366941273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,41281L,41282L,
8367041283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,41291L,41292L,
8367141293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,41301L,41302L,
8367241303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,41311L,41312L,
8367341313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,41321L,41322L,
8367441323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,41331L,41332L,
8367541333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,41341L,41342L,
8367641343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,41351L,41352L,
8367741353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,41361L,41362L,
8367841363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,41371L,41372L,
8367941373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,41381L,41382L,
8368041383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,41391L,41392L,
8368141393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,41401L,41402L,
8368241403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,41411L,41412L,
8368341413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,41421L,41422L,
8368441423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,41431L,41432L,
8368541433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,41441L,41442L,
8368641443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,41451L,41452L,
8368741453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,41461L,41462L,
8368841463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,41471L,41472L,
8368941473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,41481L,41482L,
8369041483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,41491L,41492L,
8369141493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,41501L,41502L,
8369241503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,41511L,41512L,
8369341513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,41521L,41522L,
8369441523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,41531L,41532L,
8369541533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,41541L,41542L,
8369641543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,41551L,41552L,
8369741553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,41561L,41562L,
8369841563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,41571L,41572L,
8369941573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,41581L,41582L,
8370041583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,41591L,41592L,
8370141593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,41601L,41602L,
8370241603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,41611L,41612L,
8370341613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,41621L,41622L,
8370441623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,41631L,41632L,
8370541633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,41641L,41642L,
8370641643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,41651L,41652L,
8370741653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,41661L,41662L,
8370841663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,41671L,41672L,
8370941673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,41681L,41682L,
8371041683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,41691L,41692L,
8371141693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,41701L,41702L,
8371241703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,41711L,41712L,
8371341713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,41721L,41722L,
8371441723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,41731L,41732L,
8371541733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,41741L,41742L,
8371641743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,41751L,41752L,
8371741753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,41761L,41762L,
8371841763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,41771L,41772L,
8371941773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,41781L,41782L,
8372041783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,41791L,41792L,
8372141793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,41801L,41802L,
8372241803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,41811L,41812L,
8372341813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,41821L,41822L,
8372441823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,41831L,41832L,
8372541833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,41841L,41842L,
8372641843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,41851L,41852L,
8372741853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,41861L,41862L,
8372841863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,41871L,41872L,
8372941873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,41881L,41882L,
8373041883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,41891L,41892L,
8373141893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,41901L,41902L,
8373241903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,41911L,41912L,
8373341913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,41921L,41922L,
8373441923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,41931L,41932L,
8373541933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,41941L,41942L,
8373641943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,41951L,41952L,
8373741953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,41961L,41962L,
8373841963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,41971L,41972L,
8373941973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,41981L,41982L,
8374041983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,41991L,41992L,
8374141993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,42001L,42002L,
8374242003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,42011L,42012L,
8374342013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,42021L,42022L,
8374442023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,42031L,42032L,
8374542033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,42041L,42042L,
8374642043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,42051L,42052L,
8374742053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,42061L,42062L,
8374842063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,42071L,42072L,
8374942073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,42081L,42082L,
8375042083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,42091L,42092L,
8375142093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,42101L,42102L,
8375242103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,42111L,42112L,
8375342113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,42121L,42122L,
8375442123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,42131L,42132L,
8375542133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,42141L,42142L,
8375642143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,42151L,42152L,
8375742153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,42161L,42162L,
8375842163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,42171L,42172L,
8375942173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,42181L,42182L,
8376042183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,42191L,42192L,
8376142193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,42201L,42202L,
8376242203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,42211L,42212L,
8376342213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,42221L,42222L,
8376442223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,42231L,42232L,
8376542233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,42241L,42242L,
8376642243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,42251L,42252L,
8376742253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,42261L,42262L,
8376842263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,42271L,42272L,
8376942273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,42281L,42282L,
8377042283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,42291L,42292L,
8377142293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,42301L,42302L,
8377242303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,42311L,42312L,
8377342313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,42321L,42322L,
8377442323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,42331L,42332L,
8377542333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,42341L,42342L,
8377642343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,42351L,42352L,
8377742353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,42361L,42362L,
8377842363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,42371L,42372L,
8377942373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,42381L,42382L,
8378042383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,42391L,42392L,
8378142393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,42401L,42402L,
8378242403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,42411L,42412L,
8378342413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,42421L,42422L,
8378442423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,42431L,42432L,
8378542433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,42441L,42442L,
8378642443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,42451L,42452L,
8378742453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,42461L,42462L,
8378842463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,42471L,42472L,
8378942473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,42481L,42482L,
8379042483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,42491L,42492L,
8379142493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,42501L,42502L,
8379242503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,42511L,42512L,
8379342513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,42521L,42522L,
8379442523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,42531L,42532L,
8379542533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,42541L,42542L,
8379642543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,42551L,42552L,
8379742553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,42560L,42562L,
8379842562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,42570L,42572L,
8379942572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,42580L,42582L,
8380042582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,42590L,42592L,
8380142592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,42600L,42602L,
8380242602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,42611L,42612L,
8380342613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,42621L,42622L,
8380442623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,42630L,42632L,
8380542632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,42640L,42642L,
8380642642L,42644L,42644L,42646L,42646L,42648L,42649L,42650L,42651L,42652L,
8380742653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,42661L,42662L,
8380842663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,42671L,42672L,
8380942673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,42681L,42682L,
8381042683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,42691L,42692L,
8381142693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,42701L,42702L,
8381242703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,42711L,42712L,
8381342713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,42721L,42722L,
8381442723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,42731L,42732L,
8381542733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,42741L,42742L,
8381642743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,42751L,42752L,
8381742753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,42761L,42762L,
8381842763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,42771L,42772L,
8381942773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,42781L,42782L,
8382042783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,42790L,42792L,
8382142792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,42801L,42802L,
8382242802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,42810L,42812L,
8382342812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,42820L,42822L,
8382442822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,42830L,42832L,
8382542832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,42840L,42842L,
8382642842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,42850L,42852L,
8382742852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,42860L,42862L,
8382842862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,42871L,42872L,
8382942873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,42880L,42882L,
8383042882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,42891L,42891L,
8383142893L,42894L,42895L,42896L,42896L,42898L,42899L,42900L,42901L,42902L,
8383242903L,42904L,42905L,42906L,42907L,42908L,42909L,42910L,42911L,42912L,
8383342912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,42920L,42922L,
8383442923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,42931L,42932L,
8383542933L,42934L,42935L,42936L,42937L,42938L,42939L,42940L,42941L,42942L,
8383642943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,42951L,42952L,
8383742953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,42961L,42962L,
8383842963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,42971L,42972L,
8383942973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,42981L,42982L,
8384042983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,42991L,42992L,
8384142993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,43001L,43002L,
8384243003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,43011L,43012L,
8384343013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,43021L,43022L,
8384443023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,43031L,43032L,
8384543033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,43041L,43042L,
8384643043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,43051L,43052L,
8384743053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,43061L,43062L,
8384843063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,43071L,43072L,
8384943073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,43081L,43082L,
8385043083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,43091L,43092L,
8385143093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,43101L,43102L,
8385243103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,43111L,43112L,
8385343113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,43121L,43122L,
8385443123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,43131L,43132L,
8385543133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,43141L,43142L,
8385643143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,43151L,43152L,
8385743153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,43161L,43162L,
8385843163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,43171L,43172L,
8385943173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,43181L,43182L,
8386043183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,43191L,43192L,
8386143193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,43201L,43202L,
8386243203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,43211L,43212L,
8386343213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,43221L,43222L,
8386443223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,43231L,43232L,
8386543233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,43241L,43242L,
8386643243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,43251L,43252L,
8386743253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,43261L,43262L,
8386843263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,43271L,43272L,
8386943273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,43281L,43282L,
8387043283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,43291L,43292L,
8387143293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,43301L,43302L,
8387243303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,43311L,43312L,
8387343313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,43321L,43322L,
8387443323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,43331L,43332L,
8387543333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,43341L,43342L,
8387643343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,43351L,43352L,
8387743353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,43361L,43362L,
8387843363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,43371L,43372L,
8387943373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,43381L,43382L,
8388043383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,43391L,43392L,
8388143393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,43401L,43402L,
8388243403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,43411L,43412L,
8388343413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,43421L,43422L,
8388443423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,43431L,43432L,
8388543433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,43441L,43442L,
8388643443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,43451L,43452L,
8388743453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,43461L,43462L,
8388843463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,43471L,43472L,
8388943473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,43481L,43482L,
8389043483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,43491L,43492L,
8389143493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,43501L,43502L,
8389243503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,43511L,43512L,
8389343513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,43521L,43522L,
8389443523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,43531L,43532L,
8389543533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,43541L,43542L,
8389643543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,43551L,43552L,
8389743553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,43561L,43562L,
8389843563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,43571L,43572L,
8389943573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,43581L,43582L,
8390043583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,43591L,43592L,
8390143593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,43601L,43602L,
8390243603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,43611L,43612L,
8390343613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,43621L,43622L,
8390443623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,43631L,43632L,
8390543633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,43641L,43642L,
8390643643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,43651L,43652L,
8390743653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,43661L,43662L,
8390843663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,43671L,43672L,
8390943673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,43681L,43682L,
8391043683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,43691L,43692L,
8391143693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,43701L,43702L,
8391243703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,43711L,43712L,
8391343713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,43721L,43722L,
8391443723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,43731L,43732L,
8391543733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,43741L,43742L,
8391643743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,43751L,43752L,
8391743753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,43761L,43762L,
8391843763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,43771L,43772L,
8391943773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,43781L,43782L,
8392043783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,43791L,43792L,
8392143793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,43801L,43802L,
8392243803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,43811L,43812L,
8392343813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,43821L,43822L,
8392443823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,43831L,43832L,
8392543833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,43841L,43842L,
8392643843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,43851L,43852L,
8392743853L,43854L,43855L,43856L,43857L,43858L,43859L,43860L,43861L,43862L,
8392843863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,43871L,43872L,
8392943873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,43881L,43882L,
8393043883L,43884L,43885L,43886L,43887L,43888L,43889L,43890L,43891L,43892L,
8393143893L,43894L,43895L,43896L,43897L,43898L,43899L,43900L,43901L,43902L,
8393243903L,43904L,43905L,43906L,43907L,43908L,43909L,43910L,43911L,43912L,
8393343913L,43914L,43915L,43916L,43917L,43918L,43919L,43920L,43921L,43922L,
8393443923L,43924L,43925L,43926L,43927L,43928L,43929L,43930L,43931L,43932L,
8393543933L,43934L,43935L,43936L,43937L,43938L,43939L,43940L,43941L,43942L,
8393643943L,43944L,43945L,43946L,43947L,43948L,43949L,43950L,43951L,43952L,
8393743953L,43954L,43955L,43956L,43957L,43958L,43959L,43960L,43961L,43962L,
8393843963L,43964L,43965L,43966L,43967L,43968L,43969L,43970L,43971L,43972L,
8393943973L,43974L,43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,
8394043983L,43984L,43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,
8394143993L,43994L,43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,
8394244003L,44004L,44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,
8394344013L,44014L,44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,
8394444023L,44024L,44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,
8394544033L,44034L,44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,
8394644043L,44044L,44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,
8394744053L,44054L,44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,
8394844063L,44064L,44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,
8394944073L,44074L,44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,
8395044083L,44084L,44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,
8395144093L,44094L,44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,
8395244103L,44104L,44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,
8395344113L,44114L,44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,
8395444123L,44124L,44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,
8395544133L,44134L,44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,
8395644143L,44144L,44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,
8395744153L,44154L,44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,
8395844163L,44164L,44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,
8395944173L,44174L,44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,
8396044183L,44184L,44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,
8396144193L,44194L,44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,
8396244203L,44204L,44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,
8396344213L,44214L,44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,
8396444223L,44224L,44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,
8396544233L,44234L,44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,
8396644243L,44244L,44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,
8396744253L,44254L,44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,
8396844263L,44264L,44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,
8396944273L,44274L,44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,
8397044283L,44284L,44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,
8397144293L,44294L,44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,
8397244303L,44304L,44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,
8397344313L,44314L,44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,
8397444323L,44324L,44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,
8397544333L,44334L,44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,
8397644343L,44344L,44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,
8397744353L,44354L,44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,
8397844363L,44364L,44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,
8397944373L,44374L,44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,
8398044383L,44384L,44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,
8398144393L,44394L,44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,
8398244403L,44404L,44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,
8398344413L,44414L,44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,
8398444423L,44424L,44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,
8398544433L,44434L,44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,
8398644443L,44444L,44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,
8398744453L,44454L,44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,
8398844463L,44464L,44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,
8398944473L,44474L,44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,
8399044483L,44484L,44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,
8399144493L,44494L,44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,
8399244503L,44504L,44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,
8399344513L,44514L,44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,
8399444523L,44524L,44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,
8399544533L,44534L,44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,
8399644543L,44544L,44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,
8399744553L,44554L,44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,
8399844563L,44564L,44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,
8399944573L,44574L,44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,
8400044583L,44584L,44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,
8400144593L,44594L,44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,
8400244603L,44604L,44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,
8400344613L,44614L,44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,
8400444623L,44624L,44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,
8400544633L,44634L,44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,
8400644643L,44644L,44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,
8400744653L,44654L,44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,
8400844663L,44664L,44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,
8400944673L,44674L,44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,
8401044683L,44684L,44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,
8401144693L,44694L,44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,
8401244703L,44704L,44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,
8401344713L,44714L,44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,
8401444723L,44724L,44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,
8401544733L,44734L,44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,
8401644743L,44744L,44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,
8401744753L,44754L,44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,
8401844763L,44764L,44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,
8401944773L,44774L,44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,
8402044783L,44784L,44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,
8402144793L,44794L,44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,
8402244803L,44804L,44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,
8402344813L,44814L,44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,
8402444823L,44824L,44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,
8402544833L,44834L,44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,
8402644843L,44844L,44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,
8402744853L,44854L,44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,
8402844863L,44864L,44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,
8402944873L,44874L,44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,
8403044883L,44884L,44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,
8403144893L,44894L,44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,
8403244903L,44904L,44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,
8403344913L,44914L,44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,
8403444923L,44924L,44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,
8403544933L,44934L,44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,
8403644943L,44944L,44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,
8403744953L,44954L,44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,
8403844963L,44964L,44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,
8403944973L,44974L,44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,
8404044983L,44984L,44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,
8404144993L,44994L,44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,
8404245003L,45004L,45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,
8404345013L,45014L,45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,
8404445023L,45024L,45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,
8404545033L,45034L,45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,
8404645043L,45044L,45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,
8404745053L,45054L,45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,
8404845063L,45064L,45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,
8404945073L,45074L,45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,
8405045083L,45084L,45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,
8405145093L,45094L,45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,
8405245103L,45104L,45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,
8405345113L,45114L,45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,
8405445123L,45124L,45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,
8405545133L,45134L,45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,
8405645143L,45144L,45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,
8405745153L,45154L,45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,
8405845163L,45164L,45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,
8405945173L,45174L,45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,
8406045183L,45184L,45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,
8406145193L,45194L,45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,
8406245203L,45204L,45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,
8406345213L,45214L,45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,
8406445223L,45224L,45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,
8406545233L,45234L,45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,
8406645243L,45244L,45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,
8406745253L,45254L,45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,
8406845263L,45264L,45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,
8406945273L,45274L,45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,
8407045283L,45284L,45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,
8407145293L,45294L,45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,
8407245303L,45304L,45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,
8407345313L,45314L,45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,
8407445323L,45324L,45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,
8407545333L,45334L,45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,
8407645343L,45344L,45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,
8407745353L,45354L,45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,
8407845363L,45364L,45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,
8407945373L,45374L,45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,
8408045383L,45384L,45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,
8408145393L,45394L,45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,
8408245403L,45404L,45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,
8408345413L,45414L,45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,
8408445423L,45424L,45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,
8408545433L,45434L,45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,
8408645443L,45444L,45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,
8408745453L,45454L,45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,
8408845463L,45464L,45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,
8408945473L,45474L,45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,
8409045483L,45484L,45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,
8409145493L,45494L,45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,
8409245503L,45504L,45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,
8409345513L,45514L,45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,
8409445523L,45524L,45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,
8409545533L,45534L,45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,
8409645543L,45544L,45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,
8409745553L,45554L,45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,
8409845563L,45564L,45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,
8409945573L,45574L,45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,
8410045583L,45584L,45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,
8410145593L,45594L,45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,
8410245603L,45604L,45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,
8410345613L,45614L,45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,
8410445623L,45624L,45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,
8410545633L,45634L,45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,
8410645643L,45644L,45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,
8410745653L,45654L,45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,
8410845663L,45664L,45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,
8410945673L,45674L,45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,
8411045683L,45684L,45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,
8411145693L,45694L,45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,
8411245703L,45704L,45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,
8411345713L,45714L,45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,
8411445723L,45724L,45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,
8411545733L,45734L,45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,
8411645743L,45744L,45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,
8411745753L,45754L,45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,
8411845763L,45764L,45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,
8411945773L,45774L,45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,
8412045783L,45784L,45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,
8412145793L,45794L,45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,
8412245803L,45804L,45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,
8412345813L,45814L,45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,
8412445823L,45824L,45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,
8412545833L,45834L,45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,
8412645843L,45844L,45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,
8412745853L,45854L,45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,
8412845863L,45864L,45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,
8412945873L,45874L,45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,
8413045883L,45884L,45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,
8413145893L,45894L,45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,
8413245903L,45904L,45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,
8413345913L,45914L,45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,
8413445923L,45924L,45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,
8413545933L,45934L,45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,
8413645943L,45944L,45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,
8413745953L,45954L,45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,
8413845963L,45964L,45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,
8413945973L,45974L,45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,
8414045983L,45984L,45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,
8414145993L,45994L,45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,
8414246003L,46004L,46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,
8414346013L,46014L,46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,
8414446023L,46024L,46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,
8414546033L,46034L,46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,
8414646043L,46044L,46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,
8414746053L,46054L,46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,
8414846063L,46064L,46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,
8414946073L,46074L,46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,
8415046083L,46084L,46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,
8415146093L,46094L,46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,
8415246103L,46104L,46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,
8415346113L,46114L,46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,
8415446123L,46124L,46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,
8415546133L,46134L,46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,
8415646143L,46144L,46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,
8415746153L,46154L,46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,
8415846163L,46164L,46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,
8415946173L,46174L,46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,
8416046183L,46184L,46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,
8416146193L,46194L,46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,
8416246203L,46204L,46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,
8416346213L,46214L,46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,
8416446223L,46224L,46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,
8416546233L,46234L,46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,
8416646243L,46244L,46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,
8416746253L,46254L,46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,
8416846263L,46264L,46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,
8416946273L,46274L,46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,
8417046283L,46284L,46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,
8417146293L,46294L,46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,
8417246303L,46304L,46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,
8417346313L,46314L,46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,
8417446323L,46324L,46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,
8417546333L,46334L,46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,
8417646343L,46344L,46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,
8417746353L,46354L,46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,
8417846363L,46364L,46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,
8417946373L,46374L,46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,
8418046383L,46384L,46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,
8418146393L,46394L,46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,
8418246403L,46404L,46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,
8418346413L,46414L,46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,
8418446423L,46424L,46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,
8418546433L,46434L,46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,
8418646443L,46444L,46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,
8418746453L,46454L,46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,
8418846463L,46464L,46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,
8418946473L,46474L,46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,
8419046483L,46484L,46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,
8419146493L,46494L,46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,
8419246503L,46504L,46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,
8419346513L,46514L,46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,
8419446523L,46524L,46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,
8419546533L,46534L,46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,
8419646543L,46544L,46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,
8419746553L,46554L,46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,
8419846563L,46564L,46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,
8419946573L,46574L,46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,
8420046583L,46584L,46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,
8420146593L,46594L,46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,
8420246603L,46604L,46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,
8420346613L,46614L,46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,
8420446623L,46624L,46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,
8420546633L,46634L,46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,
8420646643L,46644L,46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,
8420746653L,46654L,46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,
8420846663L,46664L,46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,
8420946673L,46674L,46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,
8421046683L,46684L,46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,
8421146693L,46694L,46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,
8421246703L,46704L,46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,
8421346713L,46714L,46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,
8421446723L,46724L,46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,
8421546733L,46734L,46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,
8421646743L,46744L,46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,
8421746753L,46754L,46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,
8421846763L,46764L,46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,
8421946773L,46774L,46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,
8422046783L,46784L,46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,
8422146793L,46794L,46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,
8422246803L,46804L,46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,
8422346813L,46814L,46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,
8422446823L,46824L,46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,
8422546833L,46834L,46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,
8422646843L,46844L,46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,
8422746853L,46854L,46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,
8422846863L,46864L,46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,
8422946873L,46874L,46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,
8423046883L,46884L,46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,
8423146893L,46894L,46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,
8423246903L,46904L,46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,
8423346913L,46914L,46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,
8423446923L,46924L,46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,
8423546933L,46934L,46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,
8423646943L,46944L,46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,
8423746953L,46954L,46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,
8423846963L,46964L,46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,
8423946973L,46974L,46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,
8424046983L,46984L,46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,
8424146993L,46994L,46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,
8424247003L,47004L,47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,
8424347013L,47014L,47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,
8424447023L,47024L,47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,
8424547033L,47034L,47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,
8424647043L,47044L,47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,
8424747053L,47054L,47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,
8424847063L,47064L,47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,
8424947073L,47074L,47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,
8425047083L,47084L,47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,
8425147093L,47094L,47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,
8425247103L,47104L,47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,
8425347113L,47114L,47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,
8425447123L,47124L,47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,
8425547133L,47134L,47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,
8425647143L,47144L,47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,
8425747153L,47154L,47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,
8425847163L,47164L,47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,
8425947173L,47174L,47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,
8426047183L,47184L,47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,
8426147193L,47194L,47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,
8426247203L,47204L,47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,
8426347213L,47214L,47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,
8426447223L,47224L,47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,
8426547233L,47234L,47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,
8426647243L,47244L,47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,
8426747253L,47254L,47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,
8426847263L,47264L,47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,
8426947273L,47274L,47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,
8427047283L,47284L,47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,
8427147293L,47294L,47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,
8427247303L,47304L,47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,
8427347313L,47314L,47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,
8427447323L,47324L,47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,
8427547333L,47334L,47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,
8427647343L,47344L,47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,
8427747353L,47354L,47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,
8427847363L,47364L,47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,
8427947373L,47374L,47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,
8428047383L,47384L,47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,
8428147393L,47394L,47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,
8428247403L,47404L,47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,
8428347413L,47414L,47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,
8428447423L,47424L,47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,
8428547433L,47434L,47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,
8428647443L,47444L,47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,
8428747453L,47454L,47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,
8428847463L,47464L,47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,
8428947473L,47474L,47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,
8429047483L,47484L,47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,
8429147493L,47494L,47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,
8429247503L,47504L,47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,
8429347513L,47514L,47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,
8429447523L,47524L,47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,
8429547533L,47534L,47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,
8429647543L,47544L,47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,
8429747553L,47554L,47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,
8429847563L,47564L,47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,
8429947573L,47574L,47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,
8430047583L,47584L,47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,
8430147593L,47594L,47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,
8430247603L,47604L,47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,
8430347613L,47614L,47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,
8430447623L,47624L,47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,
8430547633L,47634L,47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,
8430647643L,47644L,47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,
8430747653L,47654L,47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,
8430847663L,47664L,47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,
8430947673L,47674L,47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,
8431047683L,47684L,47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,
8431147693L,47694L,47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,
8431247703L,47704L,47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,
8431347713L,47714L,47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,
8431447723L,47724L,47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,
8431547733L,47734L,47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,
8431647743L,47744L,47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,
8431747753L,47754L,47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,
8431847763L,47764L,47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,
8431947773L,47774L,47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,
8432047783L,47784L,47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,
8432147793L,47794L,47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,
8432247803L,47804L,47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,
8432347813L,47814L,47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,
8432447823L,47824L,47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,
8432547833L,47834L,47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,
8432647843L,47844L,47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,
8432747853L,47854L,47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,
8432847863L,47864L,47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,
8432947873L,47874L,47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,
8433047883L,47884L,47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,
8433147893L,47894L,47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,
8433247903L,47904L,47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,
8433347913L,47914L,47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,
8433447923L,47924L,47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,
8433547933L,47934L,47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,
8433647943L,47944L,47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,
8433747953L,47954L,47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,
8433847963L,47964L,47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,
8433947973L,47974L,47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,
8434047983L,47984L,47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,
8434147993L,47994L,47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,
8434248003L,48004L,48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,
8434348013L,48014L,48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,
8434448023L,48024L,48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,
8434548033L,48034L,48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,
8434648043L,48044L,48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,
8434748053L,48054L,48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,
8434848063L,48064L,48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,
8434948073L,48074L,48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,
8435048083L,48084L,48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,
8435148093L,48094L,48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,
8435248103L,48104L,48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,
8435348113L,48114L,48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,
8435448123L,48124L,48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,
8435548133L,48134L,48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,
8435648143L,48144L,48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,
8435748153L,48154L,48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,
8435848163L,48164L,48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,
8435948173L,48174L,48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,
8436048183L,48184L,48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,
8436148193L,48194L,48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,
8436248203L,48204L,48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,
8436348213L,48214L,48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,
8436448223L,48224L,48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,
8436548233L,48234L,48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,
8436648243L,48244L,48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,
8436748253L,48254L,48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,
8436848263L,48264L,48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,
8436948273L,48274L,48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,
8437048283L,48284L,48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,
8437148293L,48294L,48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,
8437248303L,48304L,48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,
8437348313L,48314L,48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,
8437448323L,48324L,48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,
8437548333L,48334L,48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,
8437648343L,48344L,48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,
8437748353L,48354L,48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,
8437848363L,48364L,48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,
8437948373L,48374L,48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,
8438048383L,48384L,48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,
8438148393L,48394L,48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,
8438248403L,48404L,48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,
8438348413L,48414L,48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,
8438448423L,48424L,48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,
8438548433L,48434L,48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,
8438648443L,48444L,48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,
8438748453L,48454L,48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,
8438848463L,48464L,48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,
8438948473L,48474L,48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,
8439048483L,48484L,48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,
8439148493L,48494L,48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,
8439248503L,48504L,48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,
8439348513L,48514L,48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,
8439448523L,48524L,48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,
8439548533L,48534L,48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,
8439648543L,48544L,48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,
8439748553L,48554L,48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,
8439848563L,48564L,48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,
8439948573L,48574L,48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,
8440048583L,48584L,48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,
8440148593L,48594L,48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,
8440248603L,48604L,48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,
8440348613L,48614L,48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,
8440448623L,48624L,48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,
8440548633L,48634L,48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,
8440648643L,48644L,48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,
8440748653L,48654L,48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,
8440848663L,48664L,48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,
8440948673L,48674L,48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,
8441048683L,48684L,48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,
8441148693L,48694L,48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,
8441248703L,48704L,48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,
8441348713L,48714L,48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,
8441448723L,48724L,48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,
8441548733L,48734L,48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,
8441648743L,48744L,48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,
8441748753L,48754L,48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,
8441848763L,48764L,48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,
8441948773L,48774L,48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,
8442048783L,48784L,48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,
8442148793L,48794L,48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,
8442248803L,48804L,48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,
8442348813L,48814L,48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,
8442448823L,48824L,48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,
8442548833L,48834L,48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,
8442648843L,48844L,48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,
8442748853L,48854L,48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,
8442848863L,48864L,48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,
8442948873L,48874L,48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,
8443048883L,48884L,48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,
8443148893L,48894L,48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,
8443248903L,48904L,48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,
8443348913L,48914L,48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,
8443448923L,48924L,48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,
8443548933L,48934L,48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,
8443648943L,48944L,48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,
8443748953L,48954L,48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,
8443848963L,48964L,48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,
8443948973L,48974L,48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,
8444048983L,48984L,48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,
8444148993L,48994L,48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,
8444249003L,49004L,49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,
8444349013L,49014L,49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,
8444449023L,49024L,49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,
8444549033L,49034L,49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,
8444649043L,49044L,49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,
8444749053L,49054L,49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,
8444849063L,49064L,49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,
8444949073L,49074L,49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,
8445049083L,49084L,49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,
8445149093L,49094L,49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,
8445249103L,49104L,49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,
8445349113L,49114L,49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,
8445449123L,49124L,49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,
8445549133L,49134L,49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,
8445649143L,49144L,49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,
8445749153L,49154L,49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,
8445849163L,49164L,49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,
8445949173L,49174L,49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,
8446049183L,49184L,49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,
8446149193L,49194L,49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,
8446249203L,49204L,49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,
8446349213L,49214L,49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,
8446449223L,49224L,49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,
8446549233L,49234L,49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,
8446649243L,49244L,49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,
8446749253L,49254L,49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,
8446849263L,49264L,49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,
8446949273L,49274L,49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,
8447049283L,49284L,49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,
8447149293L,49294L,49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,
8447249303L,49304L,49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,
8447349313L,49314L,49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,
8447449323L,49324L,49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,
8447549333L,49334L,49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,
8447649343L,49344L,49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,
8447749353L,49354L,49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,
8447849363L,49364L,49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,
8447949373L,49374L,49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,
8448049383L,49384L,49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,
8448149393L,49394L,49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,
8448249403L,49404L,49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,
8448349413L,49414L,49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,
8448449423L,49424L,49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,
8448549433L,49434L,49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,
8448649443L,49444L,49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,
8448749453L,49454L,49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,
8448849463L,49464L,49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,
8448949473L,49474L,49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,
8449049483L,49484L,49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,
8449149493L,49494L,49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,
8449249503L,49504L,49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,
8449349513L,49514L,49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,
8449449523L,49524L,49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,
8449549533L,49534L,49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,
8449649543L,49544L,49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,
8449749553L,49554L,49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,
8449849563L,49564L,49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,
8449949573L,49574L,49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,
8450049583L,49584L,49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,
8450149593L,49594L,49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,
8450249603L,49604L,49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,
8450349613L,49614L,49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,
8450449623L,49624L,49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,
8450549633L,49634L,49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,
8450649643L,49644L,49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,
8450749653L,49654L,49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,
8450849663L,49664L,49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,
8450949673L,49674L,49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,
8451049683L,49684L,49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,
8451149693L,49694L,49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,
8451249703L,49704L,49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,
8451349713L,49714L,49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,
8451449723L,49724L,49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,
8451549733L,49734L,49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,
8451649743L,49744L,49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,
8451749753L,49754L,49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,
8451849763L,49764L,49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,
8451949773L,49774L,49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,
8452049783L,49784L,49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,
8452149793L,49794L,49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,
8452249803L,49804L,49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,
8452349813L,49814L,49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,
8452449823L,49824L,49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,
8452549833L,49834L,49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,
8452649843L,49844L,49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,
8452749853L,49854L,49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,
8452849863L,49864L,49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,
8452949873L,49874L,49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,
8453049883L,49884L,49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,
8453149893L,49894L,49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,
8453249903L,49904L,49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,
8453349913L,49914L,49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,
8453449923L,49924L,49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,
8453549933L,49934L,49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,
8453649943L,49944L,49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,
8453749953L,49954L,49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,
8453849963L,49964L,49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,
8453949973L,49974L,49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,
8454049983L,49984L,49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,
8454149993L,49994L,49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,
8454250003L,50004L,50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,
8454350013L,50014L,50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,
8454450023L,50024L,50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,
8454550033L,50034L,50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,
8454650043L,50044L,50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,
8454750053L,50054L,50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,
8454850063L,50064L,50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,
8454950073L,50074L,50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,
8455050083L,50084L,50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,
8455150093L,50094L,50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,
8455250103L,50104L,50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,
8455350113L,50114L,50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,
8455450123L,50124L,50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,
8455550133L,50134L,50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,
8455650143L,50144L,50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,
8455750153L,50154L,50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,
8455850163L,50164L,50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,
8455950173L,50174L,50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,
8456050183L,50184L,50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,
8456150193L,50194L,50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,
8456250203L,50204L,50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,
8456350213L,50214L,50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,
8456450223L,50224L,50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,
8456550233L,50234L,50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,
8456650243L,50244L,50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,
8456750253L,50254L,50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,
8456850263L,50264L,50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,
8456950273L,50274L,50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,
8457050283L,50284L,50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,
8457150293L,50294L,50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,
8457250303L,50304L,50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,
8457350313L,50314L,50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,
8457450323L,50324L,50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,
8457550333L,50334L,50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,
8457650343L,50344L,50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,
8457750353L,50354L,50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,
8457850363L,50364L,50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,
8457950373L,50374L,50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,
8458050383L,50384L,50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,
8458150393L,50394L,50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,
8458250403L,50404L,50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,
8458350413L,50414L,50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,
8458450423L,50424L,50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,
8458550433L,50434L,50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,
8458650443L,50444L,50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,
8458750453L,50454L,50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,
8458850463L,50464L,50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,
8458950473L,50474L,50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,
8459050483L,50484L,50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,
8459150493L,50494L,50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,
8459250503L,50504L,50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,
8459350513L,50514L,50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,
8459450523L,50524L,50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,
8459550533L,50534L,50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,
8459650543L,50544L,50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,
8459750553L,50554L,50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,
8459850563L,50564L,50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,
8459950573L,50574L,50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,
8460050583L,50584L,50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,
8460150593L,50594L,50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,
8460250603L,50604L,50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,
8460350613L,50614L,50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,
8460450623L,50624L,50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,
8460550633L,50634L,50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,
8460650643L,50644L,50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,
8460750653L,50654L,50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,
8460850663L,50664L,50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,
8460950673L,50674L,50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,
8461050683L,50684L,50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,
8461150693L,50694L,50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,
8461250703L,50704L,50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,
8461350713L,50714L,50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,
8461450723L,50724L,50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,
8461550733L,50734L,50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,
8461650743L,50744L,50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,
8461750753L,50754L,50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,
8461850763L,50764L,50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,
8461950773L,50774L,50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,
8462050783L,50784L,50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,
8462150793L,50794L,50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,
8462250803L,50804L,50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,
8462350813L,50814L,50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,
8462450823L,50824L,50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,
8462550833L,50834L,50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,
8462650843L,50844L,50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,
8462750853L,50854L,50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,
8462850863L,50864L,50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,
8462950873L,50874L,50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,
8463050883L,50884L,50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,
8463150893L,50894L,50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,
8463250903L,50904L,50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,
8463350913L,50914L,50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,
8463450923L,50924L,50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,
8463550933L,50934L,50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,
8463650943L,50944L,50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,
8463750953L,50954L,50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,
8463850963L,50964L,50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,
8463950973L,50974L,50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,
8464050983L,50984L,50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,
8464150993L,50994L,50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,
8464251003L,51004L,51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,
8464351013L,51014L,51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,
8464451023L,51024L,51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,
8464551033L,51034L,51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,
8464651043L,51044L,51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,
8464751053L,51054L,51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,
8464851063L,51064L,51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,
8464951073L,51074L,51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,
8465051083L,51084L,51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,
8465151093L,51094L,51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,
8465251103L,51104L,51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,
8465351113L,51114L,51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,
8465451123L,51124L,51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,
8465551133L,51134L,51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,
8465651143L,51144L,51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,
8465751153L,51154L,51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,
8465851163L,51164L,51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,
8465951173L,51174L,51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,
8466051183L,51184L,51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,
8466151193L,51194L,51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,
8466251203L,51204L,51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,
8466351213L,51214L,51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,
8466451223L,51224L,51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,
8466551233L,51234L,51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,
8466651243L,51244L,51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,
8466751253L,51254L,51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,
8466851263L,51264L,51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,
8466951273L,51274L,51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,
8467051283L,51284L,51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,
8467151293L,51294L,51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,
8467251303L,51304L,51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,
8467351313L,51314L,51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,
8467451323L,51324L,51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,
8467551333L,51334L,51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,
8467651343L,51344L,51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,
8467751353L,51354L,51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,
8467851363L,51364L,51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,
8467951373L,51374L,51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,
8468051383L,51384L,51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,
8468151393L,51394L,51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,
8468251403L,51404L,51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,
8468351413L,51414L,51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,
8468451423L,51424L,51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,
8468551433L,51434L,51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,
8468651443L,51444L,51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,
8468751453L,51454L,51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,
8468851463L,51464L,51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,
8468951473L,51474L,51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,
8469051483L,51484L,51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,
8469151493L,51494L,51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,
8469251503L,51504L,51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,
8469351513L,51514L,51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,
8469451523L,51524L,51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,
8469551533L,51534L,51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,
8469651543L,51544L,51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,
8469751553L,51554L,51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,
8469851563L,51564L,51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,
8469951573L,51574L,51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,
8470051583L,51584L,51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,
8470151593L,51594L,51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,
8470251603L,51604L,51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,
8470351613L,51614L,51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,
8470451623L,51624L,51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,
8470551633L,51634L,51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,
8470651643L,51644L,51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,
8470751653L,51654L,51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,
8470851663L,51664L,51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,
8470951673L,51674L,51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,
8471051683L,51684L,51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,
8471151693L,51694L,51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,
8471251703L,51704L,51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,
8471351713L,51714L,51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,
8471451723L,51724L,51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,
8471551733L,51734L,51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,
8471651743L,51744L,51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,
8471751753L,51754L,51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,
8471851763L,51764L,51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,
8471951773L,51774L,51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,
8472051783L,51784L,51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,
8472151793L,51794L,51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,
8472251803L,51804L,51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,
8472351813L,51814L,51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,
8472451823L,51824L,51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,
8472551833L,51834L,51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,
8472651843L,51844L,51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,
8472751853L,51854L,51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,
8472851863L,51864L,51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,
8472951873L,51874L,51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,
8473051883L,51884L,51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,
8473151893L,51894L,51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,
8473251903L,51904L,51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,
8473351913L,51914L,51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,
8473451923L,51924L,51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,
8473551933L,51934L,51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,
8473651943L,51944L,51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,
8473751953L,51954L,51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,
8473851963L,51964L,51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,
8473951973L,51974L,51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,
8474051983L,51984L,51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,
8474151993L,51994L,51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,
8474252003L,52004L,52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,
8474352013L,52014L,52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,
8474452023L,52024L,52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,
8474552033L,52034L,52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,
8474652043L,52044L,52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,
8474752053L,52054L,52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,
8474852063L,52064L,52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,
8474952073L,52074L,52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,
8475052083L,52084L,52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,
8475152093L,52094L,52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,
8475252103L,52104L,52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,
8475352113L,52114L,52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,
8475452123L,52124L,52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,
8475552133L,52134L,52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,
8475652143L,52144L,52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,
8475752153L,52154L,52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,
8475852163L,52164L,52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,
8475952173L,52174L,52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,
8476052183L,52184L,52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,
8476152193L,52194L,52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,
8476252203L,52204L,52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,
8476352213L,52214L,52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,
8476452223L,52224L,52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,
8476552233L,52234L,52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,
8476652243L,52244L,52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,
8476752253L,52254L,52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,
8476852263L,52264L,52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,
8476952273L,52274L,52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,
8477052283L,52284L,52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,
8477152293L,52294L,52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,
8477252303L,52304L,52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,
8477352313L,52314L,52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,
8477452323L,52324L,52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,
8477552333L,52334L,52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,
8477652343L,52344L,52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,
8477752353L,52354L,52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,
8477852363L,52364L,52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,
8477952373L,52374L,52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,
8478052383L,52384L,52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,
8478152393L,52394L,52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,
8478252403L,52404L,52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,
8478352413L,52414L,52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,
8478452423L,52424L,52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,
8478552433L,52434L,52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,
8478652443L,52444L,52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,
8478752453L,52454L,52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,
8478852463L,52464L,52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,
8478952473L,52474L,52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,
8479052483L,52484L,52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,
8479152493L,52494L,52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,
8479252503L,52504L,52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,
8479352513L,52514L,52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,
8479452523L,52524L,52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,
8479552533L,52534L,52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,
8479652543L,52544L,52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,
8479752553L,52554L,52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,
8479852563L,52564L,52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,
8479952573L,52574L,52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,
8480052583L,52584L,52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,
8480152593L,52594L,52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,
8480252603L,52604L,52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,
8480352613L,52614L,52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,
8480452623L,52624L,52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,
8480552633L,52634L,52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,
8480652643L,52644L,52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,
8480752653L,52654L,52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,
8480852663L,52664L,52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,
8480952673L,52674L,52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,
8481052683L,52684L,52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,
8481152693L,52694L,52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,
8481252703L,52704L,52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,
8481352713L,52714L,52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,
8481452723L,52724L,52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,
8481552733L,52734L,52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,
8481652743L,52744L,52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,
8481752753L,52754L,52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,
8481852763L,52764L,52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,
8481952773L,52774L,52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,
8482052783L,52784L,52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,
8482152793L,52794L,52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,
8482252803L,52804L,52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,
8482352813L,52814L,52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,
8482452823L,52824L,52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,
8482552833L,52834L,52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,
8482652843L,52844L,52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,
8482752853L,52854L,52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,
8482852863L,52864L,52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,
8482952873L,52874L,52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,
8483052883L,52884L,52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,
8483152893L,52894L,52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,
8483252903L,52904L,52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,
8483352913L,52914L,52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,
8483452923L,52924L,52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,
8483552933L,52934L,52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,
8483652943L,52944L,52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,
8483752953L,52954L,52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,
8483852963L,52964L,52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,
8483952973L,52974L,52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,
8484052983L,52984L,52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,
8484152993L,52994L,52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,
8484253003L,53004L,53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,
8484353013L,53014L,53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,
8484453023L,53024L,53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,
8484553033L,53034L,53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,
8484653043L,53044L,53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,
8484753053L,53054L,53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,
8484853063L,53064L,53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,
8484953073L,53074L,53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,
8485053083L,53084L,53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,
8485153093L,53094L,53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,
8485253103L,53104L,53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,
8485353113L,53114L,53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,
8485453123L,53124L,53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,
8485553133L,53134L,53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,
8485653143L,53144L,53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,
8485753153L,53154L,53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,
8485853163L,53164L,53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,
8485953173L,53174L,53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,
8486053183L,53184L,53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,
8486153193L,53194L,53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,
8486253203L,53204L,53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,
8486353213L,53214L,53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,
8486453223L,53224L,53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,
8486553233L,53234L,53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,
8486653243L,53244L,53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,
8486753253L,53254L,53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,
8486853263L,53264L,53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,
8486953273L,53274L,53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,
8487053283L,53284L,53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,
8487153293L,53294L,53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,
8487253303L,53304L,53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,
8487353313L,53314L,53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,
8487453323L,53324L,53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,
8487553333L,53334L,53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,
8487653343L,53344L,53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,
8487753353L,53354L,53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,
8487853363L,53364L,53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,
8487953373L,53374L,53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,
8488053383L,53384L,53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,
8488153393L,53394L,53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,
8488253403L,53404L,53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,
8488353413L,53414L,53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,
8488453423L,53424L,53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,
8488553433L,53434L,53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,
8488653443L,53444L,53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,
8488753453L,53454L,53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,
8488853463L,53464L,53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,
8488953473L,53474L,53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,
8489053483L,53484L,53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,
8489153493L,53494L,53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,
8489253503L,53504L,53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,
8489353513L,53514L,53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,
8489453523L,53524L,53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,
8489553533L,53534L,53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,
8489653543L,53544L,53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,
8489753553L,53554L,53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,
8489853563L,53564L,53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,
8489953573L,53574L,53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,
8490053583L,53584L,53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,
8490153593L,53594L,53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,
8490253603L,53604L,53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,
8490353613L,53614L,53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,
8490453623L,53624L,53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,
8490553633L,53634L,53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,
8490653643L,53644L,53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,
8490753653L,53654L,53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,
8490853663L,53664L,53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,
8490953673L,53674L,53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,
8491053683L,53684L,53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,
8491153693L,53694L,53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,
8491253703L,53704L,53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,
8491353713L,53714L,53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,
8491453723L,53724L,53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,
8491553733L,53734L,53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,
8491653743L,53744L,53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,
8491753753L,53754L,53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,
8491853763L,53764L,53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,
8491953773L,53774L,53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,
8492053783L,53784L,53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,
8492153793L,53794L,53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,
8492253803L,53804L,53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,
8492353813L,53814L,53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,
8492453823L,53824L,53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,
8492553833L,53834L,53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,
8492653843L,53844L,53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,
8492753853L,53854L,53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,
8492853863L,53864L,53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,
8492953873L,53874L,53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,
8493053883L,53884L,53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,
8493153893L,53894L,53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,
8493253903L,53904L,53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,
8493353913L,53914L,53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,
8493453923L,53924L,53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,
8493553933L,53934L,53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,
8493653943L,53944L,53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,
8493753953L,53954L,53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,
8493853963L,53964L,53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,
8493953973L,53974L,53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,
8494053983L,53984L,53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,
8494153993L,53994L,53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,
8494254003L,54004L,54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,
8494354013L,54014L,54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,
8494454023L,54024L,54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,
8494554033L,54034L,54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,
8494654043L,54044L,54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,
8494754053L,54054L,54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,
8494854063L,54064L,54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,
8494954073L,54074L,54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,
8495054083L,54084L,54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,
8495154093L,54094L,54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,
8495254103L,54104L,54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,
8495354113L,54114L,54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,
8495454123L,54124L,54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,
8495554133L,54134L,54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,
8495654143L,54144L,54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,
8495754153L,54154L,54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,
8495854163L,54164L,54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,
8495954173L,54174L,54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,
8496054183L,54184L,54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,
8496154193L,54194L,54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,
8496254203L,54204L,54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,
8496354213L,54214L,54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,
8496454223L,54224L,54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,
8496554233L,54234L,54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,
8496654243L,54244L,54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,
8496754253L,54254L,54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,
8496854263L,54264L,54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,
8496954273L,54274L,54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,
8497054283L,54284L,54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,
8497154293L,54294L,54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,
8497254303L,54304L,54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,
8497354313L,54314L,54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,
8497454323L,54324L,54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,
8497554333L,54334L,54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,
8497654343L,54344L,54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,
8497754353L,54354L,54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,
8497854363L,54364L,54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,
8497954373L,54374L,54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,
8498054383L,54384L,54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,
8498154393L,54394L,54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,
8498254403L,54404L,54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,
8498354413L,54414L,54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,
8498454423L,54424L,54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,
8498554433L,54434L,54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,
8498654443L,54444L,54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,
8498754453L,54454L,54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,
8498854463L,54464L,54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,
8498954473L,54474L,54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,
8499054483L,54484L,54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,
8499154493L,54494L,54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,
8499254503L,54504L,54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,
8499354513L,54514L,54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,
8499454523L,54524L,54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,
8499554533L,54534L,54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,
8499654543L,54544L,54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,
8499754553L,54554L,54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,
8499854563L,54564L,54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,
8499954573L,54574L,54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,
8500054583L,54584L,54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,
8500154593L,54594L,54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,
8500254603L,54604L,54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,
8500354613L,54614L,54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,
8500454623L,54624L,54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,
8500554633L,54634L,54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,
8500654643L,54644L,54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,
8500754653L,54654L,54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,
8500854663L,54664L,54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,
8500954673L,54674L,54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,
8501054683L,54684L,54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,
8501154693L,54694L,54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,
8501254703L,54704L,54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,
8501354713L,54714L,54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,
8501454723L,54724L,54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,
8501554733L,54734L,54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,
8501654743L,54744L,54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,
8501754753L,54754L,54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,
8501854763L,54764L,54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,
8501954773L,54774L,54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,
8502054783L,54784L,54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,
8502154793L,54794L,54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,
8502254803L,54804L,54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,
8502354813L,54814L,54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,
8502454823L,54824L,54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,
8502554833L,54834L,54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,
8502654843L,54844L,54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,
8502754853L,54854L,54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,
8502854863L,54864L,54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,
8502954873L,54874L,54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,
8503054883L,54884L,54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,
8503154893L,54894L,54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,
8503254903L,54904L,54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,
8503354913L,54914L,54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,
8503454923L,54924L,54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,
8503554933L,54934L,54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,
8503654943L,54944L,54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,
8503754953L,54954L,54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,
8503854963L,54964L,54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,
8503954973L,54974L,54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,
8504054983L,54984L,54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,
8504154993L,54994L,54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,
8504255003L,55004L,55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,
8504355013L,55014L,55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,
8504455023L,55024L,55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,
8504555033L,55034L,55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,
8504655043L,55044L,55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,
8504755053L,55054L,55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,
8504855063L,55064L,55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,
8504955073L,55074L,55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,
8505055083L,55084L,55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,
8505155093L,55094L,55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,
8505255103L,55104L,55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,
8505355113L,55114L,55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,
8505455123L,55124L,55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,
8505555133L,55134L,55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,
8505655143L,55144L,55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,
8505755153L,55154L,55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,
8505855163L,55164L,55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,
8505955173L,55174L,55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,
8506055183L,55184L,55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,
8506155193L,55194L,55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,
8506255203L,55204L,55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,
8506355213L,55214L,55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,
8506455223L,55224L,55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,
8506555233L,55234L,55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,
8506655243L,55244L,55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,
8506755253L,55254L,55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,
8506855263L,55264L,55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,
8506955273L,55274L,55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,
8507055283L,55284L,55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,
8507155293L,55294L,55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,
8507255303L,55304L,55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,
8507355313L,55314L,55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,
8507455323L,55324L,55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,
8507555333L,55334L,55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,
8507655343L,55344L,55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,
8507755353L,55354L,55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,
8507855363L,55364L,55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,
8507955373L,55374L,55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,
8508055383L,55384L,55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,
8508155393L,55394L,55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,
8508255403L,55404L,55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,
8508355413L,55414L,55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,
8508455423L,55424L,55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,
8508555433L,55434L,55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,
8508655443L,55444L,55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,
8508755453L,55454L,55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,
8508855463L,55464L,55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,
8508955473L,55474L,55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,
8509055483L,55484L,55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,
8509155493L,55494L,55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,
8509255503L,55504L,55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,
8509355513L,55514L,55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,
8509455523L,55524L,55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,
8509555533L,55534L,55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,
8509655543L,55544L,55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,
8509755553L,55554L,55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,
8509855563L,55564L,55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,
8509955573L,55574L,55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,
8510055583L,55584L,55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,
8510155593L,55594L,55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,
8510255603L,55604L,55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,
8510355613L,55614L,55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,
8510455623L,55624L,55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,
8510555633L,55634L,55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,
8510655643L,55644L,55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,
8510755653L,55654L,55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,
8510855663L,55664L,55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,
8510955673L,55674L,55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,
8511055683L,55684L,55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,
8511155693L,55694L,55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,
8511255703L,55704L,55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,
8511355713L,55714L,55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,
8511455723L,55724L,55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,
8511555733L,55734L,55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,
8511655743L,55744L,55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,
8511755753L,55754L,55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,
8511855763L,55764L,55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,
8511955773L,55774L,55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,
8512055783L,55784L,55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,
8512155793L,55794L,55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,
8512255803L,55804L,55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,
8512355813L,55814L,55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,
8512455823L,55824L,55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,
8512555833L,55834L,55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,
8512655843L,55844L,55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,
8512755853L,55854L,55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,
8512855863L,55864L,55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,
8512955873L,55874L,55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,
8513055883L,55884L,55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,
8513155893L,55894L,55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,
8513255903L,55904L,55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,
8513355913L,55914L,55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,
8513455923L,55924L,55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,
8513555933L,55934L,55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,
8513655943L,55944L,55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,
8513755953L,55954L,55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,
8513855963L,55964L,55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,
8513955973L,55974L,55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,
8514055983L,55984L,55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,
8514155993L,55994L,55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,
8514256003L,56004L,56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,
8514356013L,56014L,56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,
8514456023L,56024L,56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,
8514556033L,56034L,56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,
8514656043L,56044L,56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,
8514756053L,56054L,56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,
8514856063L,56064L,56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,
8514956073L,56074L,56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,
8515056083L,56084L,56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,
8515156093L,56094L,56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,
8515256103L,56104L,56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,
8515356113L,56114L,56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,
8515456123L,56124L,56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,
8515556133L,56134L,56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,
8515656143L,56144L,56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,
8515756153L,56154L,56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,
8515856163L,56164L,56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,
8515956173L,56174L,56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,
8516056183L,56184L,56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,
8516156193L,56194L,56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,
8516256203L,56204L,56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,
8516356213L,56214L,56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,
8516456223L,56224L,56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,
8516556233L,56234L,56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,
8516656243L,56244L,56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,
8516756253L,56254L,56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,
8516856263L,56264L,56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,
8516956273L,56274L,56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,
8517056283L,56284L,56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,
8517156293L,56294L,56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,
8517256303L,56304L,56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,
8517356313L,56314L,56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,
8517456323L,56324L,56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,
8517556333L,56334L,56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,
8517656343L,56344L,56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,
8517756353L,56354L,56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,
8517856363L,56364L,56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,
8517956373L,56374L,56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,
8518056383L,56384L,56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,
8518156393L,56394L,56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,
8518256403L,56404L,56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,
8518356413L,56414L,56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,
8518456423L,56424L,56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,
8518556433L,56434L,56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,
8518656443L,56444L,56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,
8518756453L,56454L,56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,
8518856463L,56464L,56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,
8518956473L,56474L,56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,
8519056483L,56484L,56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,
8519156493L,56494L,56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,
8519256503L,56504L,56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,
8519356513L,56514L,56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,
8519456523L,56524L,56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,
8519556533L,56534L,56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,
8519656543L,56544L,56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,
8519756553L,56554L,56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,
8519856563L,56564L,56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,
8519956573L,56574L,56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,
8520056583L,56584L,56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,
8520156593L,56594L,56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,
8520256603L,56604L,56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,
8520356613L,56614L,56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,
8520456623L,56624L,56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,
8520556633L,56634L,56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,
8520656643L,56644L,56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,
8520756653L,56654L,56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,
8520856663L,56664L,56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,
8520956673L,56674L,56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,
8521056683L,56684L,56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,
8521156693L,56694L,56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,
8521256703L,56704L,56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,
8521356713L,56714L,56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,
8521456723L,56724L,56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,
8521556733L,56734L,56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,
8521656743L,56744L,56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,
8521756753L,56754L,56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,
8521856763L,56764L,56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,
8521956773L,56774L,56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,
8522056783L,56784L,56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,
8522156793L,56794L,56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,
8522256803L,56804L,56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,
8522356813L,56814L,56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,
8522456823L,56824L,56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,
8522556833L,56834L,56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,
8522656843L,56844L,56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,
8522756853L,56854L,56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,
8522856863L,56864L,56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,
8522956873L,56874L,56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,
8523056883L,56884L,56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,
8523156893L,56894L,56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,
8523256903L,56904L,56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,
8523356913L,56914L,56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,
8523456923L,56924L,56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,
8523556933L,56934L,56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,
8523656943L,56944L,56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,
8523756953L,56954L,56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,
8523856963L,56964L,56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,
8523956973L,56974L,56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,
8524056983L,56984L,56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,
8524156993L,56994L,56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,
8524257003L,57004L,57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,
8524357013L,57014L,57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,
8524457023L,57024L,57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,
8524557033L,57034L,57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,
8524657043L,57044L,57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,
8524757053L,57054L,57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,
8524857063L,57064L,57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,
8524957073L,57074L,57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,
8525057083L,57084L,57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,
8525157093L,57094L,57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,
8525257103L,57104L,57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,
8525357113L,57114L,57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,
8525457123L,57124L,57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,
8525557133L,57134L,57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,
8525657143L,57144L,57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,
8525757153L,57154L,57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,
8525857163L,57164L,57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,
8525957173L,57174L,57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,
8526057183L,57184L,57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,
8526157193L,57194L,57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,
8526257203L,57204L,57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,
8526357213L,57214L,57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,
8526457223L,57224L,57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,
8526557233L,57234L,57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,
8526657243L,57244L,57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,
8526757253L,57254L,57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,
8526857263L,57264L,57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,
8526957273L,57274L,57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,
8527057283L,57284L,57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,
8527157293L,57294L,57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,
8527257303L,57304L,57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,
8527357313L,57314L,57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,
8527457323L,57324L,57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,
8527557333L,57334L,57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,
8527657343L,57344L,57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,
8527757353L,57354L,57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,
8527857363L,57364L,57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,
8527957373L,57374L,57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,
8528057383L,57384L,57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,
8528157393L,57394L,57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,
8528257403L,57404L,57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,
8528357413L,57414L,57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,
8528457423L,57424L,57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,
8528557433L,57434L,57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,
8528657443L,57444L,57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,
8528757453L,57454L,57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,
8528857463L,57464L,57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,
8528957473L,57474L,57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,
8529057483L,57484L,57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,
8529157493L,57494L,57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,
8529257503L,57504L,57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,
8529357513L,57514L,57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,
8529457523L,57524L,57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,
8529557533L,57534L,57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,
8529657543L,57544L,57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,
8529757553L,57554L,57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,
8529857563L,57564L,57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,
8529957573L,57574L,57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,
8530057583L,57584L,57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,
8530157593L,57594L,57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,
8530257603L,57604L,57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,
8530357613L,57614L,57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,
8530457623L,57624L,57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,
8530557633L,57634L,57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,
8530657643L,57644L,57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,
8530757653L,57654L,57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,
8530857663L,57664L,57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,
8530957673L,57674L,57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,
8531057683L,57684L,57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,
8531157693L,57694L,57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,
8531257703L,57704L,57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,
8531357713L,57714L,57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,
8531457723L,57724L,57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,
8531557733L,57734L,57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,
8531657743L,57744L,57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,
8531757753L,57754L,57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,
8531857763L,57764L,57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,
8531957773L,57774L,57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,
8532057783L,57784L,57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,
8532157793L,57794L,57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,
8532257803L,57804L,57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,
8532357813L,57814L,57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,
8532457823L,57824L,57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,
8532557833L,57834L,57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,
8532657843L,57844L,57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,
8532757853L,57854L,57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,
8532857863L,57864L,57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,
8532957873L,57874L,57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,
8533057883L,57884L,57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,
8533157893L,57894L,57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,
8533257903L,57904L,57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,
8533357913L,57914L,57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,
8533457923L,57924L,57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,
8533557933L,57934L,57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,
8533657943L,57944L,57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,
8533757953L,57954L,57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,
8533857963L,57964L,57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,
8533957973L,57974L,57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,
8534057983L,57984L,57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,
8534157993L,57994L,57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,
8534258003L,58004L,58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,
8534358013L,58014L,58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,
8534458023L,58024L,58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,
8534558033L,58034L,58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,
8534658043L,58044L,58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,
8534758053L,58054L,58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,
8534858063L,58064L,58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,
8534958073L,58074L,58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,
8535058083L,58084L,58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,
8535158093L,58094L,58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,
8535258103L,58104L,58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,
8535358113L,58114L,58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,
8535458123L,58124L,58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,
8535558133L,58134L,58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,
8535658143L,58144L,58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,
8535758153L,58154L,58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,
8535858163L,58164L,58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,
8535958173L,58174L,58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,
8536058183L,58184L,58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,
8536158193L,58194L,58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,
8536258203L,58204L,58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,
8536358213L,58214L,58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,
8536458223L,58224L,58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,
8536558233L,58234L,58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,
8536658243L,58244L,58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,
8536758253L,58254L,58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,
8536858263L,58264L,58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,
8536958273L,58274L,58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,
8537058283L,58284L,58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,
8537158293L,58294L,58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,
8537258303L,58304L,58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,
8537358313L,58314L,58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,
8537458323L,58324L,58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,
8537558333L,58334L,58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,
8537658343L,58344L,58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,
8537758353L,58354L,58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,
8537858363L,58364L,58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,
8537958373L,58374L,58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,
8538058383L,58384L,58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,
8538158393L,58394L,58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,
8538258403L,58404L,58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,
8538358413L,58414L,58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,
8538458423L,58424L,58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,
8538558433L,58434L,58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,
8538658443L,58444L,58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,
8538758453L,58454L,58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,
8538858463L,58464L,58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,
8538958473L,58474L,58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,
8539058483L,58484L,58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,
8539158493L,58494L,58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,
8539258503L,58504L,58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,
8539358513L,58514L,58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,
8539458523L,58524L,58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,
8539558533L,58534L,58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,
8539658543L,58544L,58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,
8539758553L,58554L,58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,
8539858563L,58564L,58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,
8539958573L,58574L,58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,
8540058583L,58584L,58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,
8540158593L,58594L,58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,
8540258603L,58604L,58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,
8540358613L,58614L,58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,
8540458623L,58624L,58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,
8540558633L,58634L,58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,
8540658643L,58644L,58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,
8540758653L,58654L,58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,
8540858663L,58664L,58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,
8540958673L,58674L,58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,
8541058683L,58684L,58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,
8541158693L,58694L,58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,
8541258703L,58704L,58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,
8541358713L,58714L,58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,
8541458723L,58724L,58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,
8541558733L,58734L,58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,
8541658743L,58744L,58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,
8541758753L,58754L,58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,
8541858763L,58764L,58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,
8541958773L,58774L,58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,
8542058783L,58784L,58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,
8542158793L,58794L,58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,
8542258803L,58804L,58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,
8542358813L,58814L,58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,
8542458823L,58824L,58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,
8542558833L,58834L,58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,
8542658843L,58844L,58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,
8542758853L,58854L,58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,
8542858863L,58864L,58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,
8542958873L,58874L,58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,
8543058883L,58884L,58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,
8543158893L,58894L,58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,
8543258903L,58904L,58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,
8543358913L,58914L,58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,
8543458923L,58924L,58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,
8543558933L,58934L,58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,
8543658943L,58944L,58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,
8543758953L,58954L,58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,
8543858963L,58964L,58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,
8543958973L,58974L,58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,
8544058983L,58984L,58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,
8544158993L,58994L,58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,
8544259003L,59004L,59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,
8544359013L,59014L,59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,
8544459023L,59024L,59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,
8544559033L,59034L,59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,
8544659043L,59044L,59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,
8544759053L,59054L,59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,
8544859063L,59064L,59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,
8544959073L,59074L,59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,
8545059083L,59084L,59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,
8545159093L,59094L,59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,
8545259103L,59104L,59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,
8545359113L,59114L,59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,
8545459123L,59124L,59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,
8545559133L,59134L,59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,
8545659143L,59144L,59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,
8545759153L,59154L,59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,
8545859163L,59164L,59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,
8545959173L,59174L,59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,
8546059183L,59184L,59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,
8546159193L,59194L,59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,
8546259203L,59204L,59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,
8546359213L,59214L,59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,
8546459223L,59224L,59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,
8546559233L,59234L,59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,
8546659243L,59244L,59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,
8546759253L,59254L,59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,
8546859263L,59264L,59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,
8546959273L,59274L,59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,
8547059283L,59284L,59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,
8547159293L,59294L,59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,
8547259303L,59304L,59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,
8547359313L,59314L,59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,
8547459323L,59324L,59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,
8547559333L,59334L,59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,
8547659343L,59344L,59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,
8547759353L,59354L,59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,
8547859363L,59364L,59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,
8547959373L,59374L,59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,
8548059383L,59384L,59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,
8548159393L,59394L,59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,
8548259403L,59404L,59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,
8548359413L,59414L,59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,
8548459423L,59424L,59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,
8548559433L,59434L,59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,
8548659443L,59444L,59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,
8548759453L,59454L,59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,
8548859463L,59464L,59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,
8548959473L,59474L,59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,
8549059483L,59484L,59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,
8549159493L,59494L,59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,
8549259503L,59504L,59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,
8549359513L,59514L,59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,
8549459523L,59524L,59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,
8549559533L,59534L,59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,
8549659543L,59544L,59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,
8549759553L,59554L,59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,
8549859563L,59564L,59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,
8549959573L,59574L,59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,
8550059583L,59584L,59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,
8550159593L,59594L,59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,
8550259603L,59604L,59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,
8550359613L,59614L,59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,
8550459623L,59624L,59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,
8550559633L,59634L,59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,
8550659643L,59644L,59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,
8550759653L,59654L,59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,
8550859663L,59664L,59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,
8550959673L,59674L,59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,
8551059683L,59684L,59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,
8551159693L,59694L,59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,
8551259703L,59704L,59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,
8551359713L,59714L,59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,
8551459723L,59724L,59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,
8551559733L,59734L,59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,
8551659743L,59744L,59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,
8551759753L,59754L,59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,
8551859763L,59764L,59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,
8551959773L,59774L,59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,
8552059783L,59784L,59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,
8552159793L,59794L,59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,
8552259803L,59804L,59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,
8552359813L,59814L,59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,
8552459823L,59824L,59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,
8552559833L,59834L,59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,
8552659843L,59844L,59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,
8552759853L,59854L,59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,
8552859863L,59864L,59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,
8552959873L,59874L,59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,
8553059883L,59884L,59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,
8553159893L,59894L,59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,
8553259903L,59904L,59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,
8553359913L,59914L,59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,
8553459923L,59924L,59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,
8553559933L,59934L,59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,
8553659943L,59944L,59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,
8553759953L,59954L,59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,
8553859963L,59964L,59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,
8553959973L,59974L,59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,
8554059983L,59984L,59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,
8554159993L,59994L,59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,
8554260003L,60004L,60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,
8554360013L,60014L,60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,
8554460023L,60024L,60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,
8554560033L,60034L,60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,
8554660043L,60044L,60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,
8554760053L,60054L,60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,
8554860063L,60064L,60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,
8554960073L,60074L,60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,
8555060083L,60084L,60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,
8555160093L,60094L,60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,
8555260103L,60104L,60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,
8555360113L,60114L,60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,
8555460123L,60124L,60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,
8555560133L,60134L,60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,
8555660143L,60144L,60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,
8555760153L,60154L,60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,
8555860163L,60164L,60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,
8555960173L,60174L,60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,
8556060183L,60184L,60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,
8556160193L,60194L,60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,
8556260203L,60204L,60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,
8556360213L,60214L,60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,
8556460223L,60224L,60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,
8556560233L,60234L,60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,
8556660243L,60244L,60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,
8556760253L,60254L,60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,
8556860263L,60264L,60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,
8556960273L,60274L,60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,
8557060283L,60284L,60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,
8557160293L,60294L,60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,
8557260303L,60304L,60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,
8557360313L,60314L,60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,
8557460323L,60324L,60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,
8557560333L,60334L,60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,
8557660343L,60344L,60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,
8557760353L,60354L,60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,
8557860363L,60364L,60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,
8557960373L,60374L,60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,
8558060383L,60384L,60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,
8558160393L,60394L,60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,
8558260403L,60404L,60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,
8558360413L,60414L,60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,
8558460423L,60424L,60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,
8558560433L,60434L,60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,
8558660443L,60444L,60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,
8558760453L,60454L,60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,
8558860463L,60464L,60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,
8558960473L,60474L,60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,
8559060483L,60484L,60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,
8559160493L,60494L,60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,
8559260503L,60504L,60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,
8559360513L,60514L,60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,
8559460523L,60524L,60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,
8559560533L,60534L,60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,
8559660543L,60544L,60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,
8559760553L,60554L,60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,
8559860563L,60564L,60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,
8559960573L,60574L,60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,
8560060583L,60584L,60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,
8560160593L,60594L,60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,
8560260603L,60604L,60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,
8560360613L,60614L,60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,
8560460623L,60624L,60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,
8560560633L,60634L,60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,
8560660643L,60644L,60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,
8560760653L,60654L,60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,
8560860663L,60664L,60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,
8560960673L,60674L,60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,
8561060683L,60684L,60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,
8561160693L,60694L,60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,
8561260703L,60704L,60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,
8561360713L,60714L,60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,
8561460723L,60724L,60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,
8561560733L,60734L,60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,
8561660743L,60744L,60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,
8561760753L,60754L,60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,
8561860763L,60764L,60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,
8561960773L,60774L,60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,
8562060783L,60784L,60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,
8562160793L,60794L,60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,
8562260803L,60804L,60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,
8562360813L,60814L,60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,
8562460823L,60824L,60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,
8562560833L,60834L,60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,
8562660843L,60844L,60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,
8562760853L,60854L,60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,
8562860863L,60864L,60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,
8562960873L,60874L,60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,
8563060883L,60884L,60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,
8563160893L,60894L,60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,
8563260903L,60904L,60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,
8563360913L,60914L,60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,
8563460923L,60924L,60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,
8563560933L,60934L,60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,
8563660943L,60944L,60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,
8563760953L,60954L,60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,
8563860963L,60964L,60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,
8563960973L,60974L,60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,
8564060983L,60984L,60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,
8564160993L,60994L,60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,
8564261003L,61004L,61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,
8564361013L,61014L,61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,
8564461023L,61024L,61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,
8564561033L,61034L,61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,
8564661043L,61044L,61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,
8564761053L,61054L,61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,
8564861063L,61064L,61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,
8564961073L,61074L,61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,
8565061083L,61084L,61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,
8565161093L,61094L,61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,
8565261103L,61104L,61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,
8565361113L,61114L,61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,
8565461123L,61124L,61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,
8565561133L,61134L,61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,
8565661143L,61144L,61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,
8565761153L,61154L,61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,
8565861163L,61164L,61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,
8565961173L,61174L,61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,
8566061183L,61184L,61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,
8566161193L,61194L,61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,
8566261203L,61204L,61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,
8566361213L,61214L,61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,
8566461223L,61224L,61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,
8566561233L,61234L,61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,
8566661243L,61244L,61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,
8566761253L,61254L,61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,
8566861263L,61264L,61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,
8566961273L,61274L,61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,
8567061283L,61284L,61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,
8567161293L,61294L,61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,
8567261303L,61304L,61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,
8567361313L,61314L,61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,
8567461323L,61324L,61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,
8567561333L,61334L,61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,
8567661343L,61344L,61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,
8567761353L,61354L,61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,
8567861363L,61364L,61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,
8567961373L,61374L,61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,
8568061383L,61384L,61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,
8568161393L,61394L,61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,
8568261403L,61404L,61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,
8568361413L,61414L,61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,
8568461423L,61424L,61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,
8568561433L,61434L,61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,
8568661443L,61444L,61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,
8568761453L,61454L,61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,
8568861463L,61464L,61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,
8568961473L,61474L,61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,
8569061483L,61484L,61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,
8569161493L,61494L,61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,
8569261503L,61504L,61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,
8569361513L,61514L,61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,
8569461523L,61524L,61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,
8569561533L,61534L,61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,
8569661543L,61544L,61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,
8569761553L,61554L,61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,
8569861563L,61564L,61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,
8569961573L,61574L,61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,
8570061583L,61584L,61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,
8570161593L,61594L,61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,
8570261603L,61604L,61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,
8570361613L,61614L,61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,
8570461623L,61624L,61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,
8570561633L,61634L,61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,
8570661643L,61644L,61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,
8570761653L,61654L,61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,
8570861663L,61664L,61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,
8570961673L,61674L,61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,
8571061683L,61684L,61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,
8571161693L,61694L,61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,
8571261703L,61704L,61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,
8571361713L,61714L,61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,
8571461723L,61724L,61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,
8571561733L,61734L,61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,
8571661743L,61744L,61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,
8571761753L,61754L,61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,
8571861763L,61764L,61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,
8571961773L,61774L,61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,
8572061783L,61784L,61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,
8572161793L,61794L,61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,
8572261803L,61804L,61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,
8572361813L,61814L,61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,
8572461823L,61824L,61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,
8572561833L,61834L,61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,
8572661843L,61844L,61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,
8572761853L,61854L,61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,
8572861863L,61864L,61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,
8572961873L,61874L,61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,
8573061883L,61884L,61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,
8573161893L,61894L,61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,
8573261903L,61904L,61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,
8573361913L,61914L,61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,
8573461923L,61924L,61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,
8573561933L,61934L,61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,
8573661943L,61944L,61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,
8573761953L,61954L,61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,
8573861963L,61964L,61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,
8573961973L,61974L,61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,
8574061983L,61984L,61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,
8574161993L,61994L,61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,
8574262003L,62004L,62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,
8574362013L,62014L,62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,
8574462023L,62024L,62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,
8574562033L,62034L,62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,
8574662043L,62044L,62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,
8574762053L,62054L,62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,
8574862063L,62064L,62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,
8574962073L,62074L,62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,
8575062083L,62084L,62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,
8575162093L,62094L,62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,
8575262103L,62104L,62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,
8575362113L,62114L,62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,
8575462123L,62124L,62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,
8575562133L,62134L,62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,
8575662143L,62144L,62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,
8575762153L,62154L,62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,
8575862163L,62164L,62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,
8575962173L,62174L,62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,
8576062183L,62184L,62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,
8576162193L,62194L,62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,
8576262203L,62204L,62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,
8576362213L,62214L,62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,
8576462223L,62224L,62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,
8576562233L,62234L,62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,
8576662243L,62244L,62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,
8576762253L,62254L,62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,
8576862263L,62264L,62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,
8576962273L,62274L,62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,
8577062283L,62284L,62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,
8577162293L,62294L,62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,
8577262303L,62304L,62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,
8577362313L,62314L,62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,
8577462323L,62324L,62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,
8577562333L,62334L,62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,
8577662343L,62344L,62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,
8577762353L,62354L,62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,
8577862363L,62364L,62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,
8577962373L,62374L,62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,
8578062383L,62384L,62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,
8578162393L,62394L,62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,
8578262403L,62404L,62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,
8578362413L,62414L,62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,
8578462423L,62424L,62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,
8578562433L,62434L,62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,
8578662443L,62444L,62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,
8578762453L,62454L,62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,
8578862463L,62464L,62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,
8578962473L,62474L,62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,
8579062483L,62484L,62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,
8579162493L,62494L,62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,
8579262503L,62504L,62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,
8579362513L,62514L,62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,
8579462523L,62524L,62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,
8579562533L,62534L,62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,
8579662543L,62544L,62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,
8579762553L,62554L,62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,
8579862563L,62564L,62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,
8579962573L,62574L,62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,
8580062583L,62584L,62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,
8580162593L,62594L,62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,
8580262603L,62604L,62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,
8580362613L,62614L,62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,
8580462623L,62624L,62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,
8580562633L,62634L,62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,
8580662643L,62644L,62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,
8580762653L,62654L,62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,
8580862663L,62664L,62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,
8580962673L,62674L,62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,
8581062683L,62684L,62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,
8581162693L,62694L,62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,
8581262703L,62704L,62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,
8581362713L,62714L,62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,
8581462723L,62724L,62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,
8581562733L,62734L,62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,
8581662743L,62744L,62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,
8581762753L,62754L,62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,
8581862763L,62764L,62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,
8581962773L,62774L,62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,
8582062783L,62784L,62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,
8582162793L,62794L,62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,
8582262803L,62804L,62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,
8582362813L,62814L,62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,
8582462823L,62824L,62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,
8582562833L,62834L,62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,
8582662843L,62844L,62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,
8582762853L,62854L,62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,
8582862863L,62864L,62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,
8582962873L,62874L,62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,
8583062883L,62884L,62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,
8583162893L,62894L,62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,
8583262903L,62904L,62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,
8583362913L,62914L,62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,
8583462923L,62924L,62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,
8583562933L,62934L,62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,
8583662943L,62944L,62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,
8583762953L,62954L,62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,
8583862963L,62964L,62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,
8583962973L,62974L,62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,
8584062983L,62984L,62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,
8584162993L,62994L,62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,
8584263003L,63004L,63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,
8584363013L,63014L,63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,
8584463023L,63024L,63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,
8584563033L,63034L,63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,
8584663043L,63044L,63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,
8584763053L,63054L,63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,
8584863063L,63064L,63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,
8584963073L,63074L,63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,
8585063083L,63084L,63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,
8585163093L,63094L,63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,
8585263103L,63104L,63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,
8585363113L,63114L,63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,
8585463123L,63124L,63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,
8585563133L,63134L,63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,
8585663143L,63144L,63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,
8585763153L,63154L,63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,
8585863163L,63164L,63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,
8585963173L,63174L,63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,
8586063183L,63184L,63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,
8586163193L,63194L,63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,
8586263203L,63204L,63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,
8586363213L,63214L,63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,
8586463223L,63224L,63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,
8586563233L,63234L,63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,
8586663243L,63244L,63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,
8586763253L,63254L,63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,
8586863263L,63264L,63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,
8586963273L,63274L,63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,
8587063283L,63284L,63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,
8587163293L,63294L,63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,
8587263303L,63304L,63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,
8587363313L,63314L,63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,
8587463323L,63324L,63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,
8587563333L,63334L,63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,
8587663343L,63344L,63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,
8587763353L,63354L,63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,
8587863363L,63364L,63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,
8587963373L,63374L,63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,
8588063383L,63384L,63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,
8588163393L,63394L,63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,
8588263403L,63404L,63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,
8588363413L,63414L,63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,
8588463423L,63424L,63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,
8588563433L,63434L,63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,
8588663443L,63444L,63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,
8588763453L,63454L,63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,
8588863463L,63464L,63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,
8588963473L,63474L,63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,
8589063483L,63484L,63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,
8589163493L,63494L,63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,
8589263503L,63504L,63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,
8589363513L,63514L,63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,
8589463523L,63524L,63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,
8589563533L,63534L,63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,
8589663543L,63544L,63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,
8589763553L,63554L,63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,
8589863563L,63564L,63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,
8589963573L,63574L,63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,
8590063583L,63584L,63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,
8590163593L,63594L,63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,
8590263603L,63604L,63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,
8590363613L,63614L,63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,
8590463623L,63624L,63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,
8590563633L,63634L,63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,
8590663643L,63644L,63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,
8590763653L,63654L,63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,
8590863663L,63664L,63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,
8590963673L,63674L,63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,
8591063683L,63684L,63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,
8591163693L,63694L,63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,
8591263703L,63704L,63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,
8591363713L,63714L,63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,
8591463723L,63724L,63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,
8591563733L,63734L,63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,
8591663743L,63744L,63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,
8591763753L,63754L,63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,
8591863763L,63764L,63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,
8591963773L,63774L,63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,
8592063783L,63784L,63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,
8592163793L,63794L,63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,
8592263803L,63804L,63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,
8592363813L,63814L,63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,
8592463823L,63824L,63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,
8592563833L,63834L,63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,
8592663843L,63844L,63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,
8592763853L,63854L,63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,
8592863863L,63864L,63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,
8592963873L,63874L,63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,
8593063883L,63884L,63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,
8593163893L,63894L,63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,
8593263903L,63904L,63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,
8593363913L,63914L,63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,
8593463923L,63924L,63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,
8593563933L,63934L,63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,
8593663943L,63944L,63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,
8593763953L,63954L,63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,
8593863963L,63964L,63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,
8593963973L,63974L,63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,
8594063983L,63984L,63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,
8594163993L,63994L,63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,
8594264003L,64004L,64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,
8594364013L,64014L,64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,
8594464023L,64024L,64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,
8594564033L,64034L,64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,
8594664043L,64044L,64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,
8594764053L,64054L,64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,
8594864063L,64064L,64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,
8594964073L,64074L,64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,
8595064083L,64084L,64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,
8595164093L,64094L,64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,
8595264103L,64104L,64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,
8595364113L,64114L,64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,
8595464123L,64124L,64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,
8595564133L,64134L,64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,
8595664143L,64144L,64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,
8595764153L,64154L,64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,
8595864163L,64164L,64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,
8595964173L,64174L,64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,
8596064183L,64184L,64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,
8596164193L,64194L,64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,
8596264203L,64204L,64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,
8596364213L,64214L,64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,
8596464223L,64224L,64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,
8596564233L,64234L,64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,
8596664243L,64244L,64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,
8596764253L,64254L,64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,
8596864263L,64264L,64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,
8596964273L,64274L,64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,
8597064283L,64284L,64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,
8597164293L,64294L,64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,
8597264303L,64304L,64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,
8597364313L,64314L,64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,
8597464323L,64324L,64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,
8597564333L,64334L,64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,
8597664343L,64344L,64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,
8597764353L,64354L,64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,
8597864363L,64364L,64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,
8597964373L,64374L,64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,
8598064383L,64384L,64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,
8598164393L,64394L,64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,
8598264403L,64404L,64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,
8598364413L,64414L,64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,
8598464423L,64424L,64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,
8598564433L,64434L,64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,
8598664443L,64444L,64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,
8598764453L,64454L,64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,
8598864463L,64464L,64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,
8598964473L,64474L,64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,
8599064483L,64484L,64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,
8599164493L,64494L,64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,
8599264503L,64504L,64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,
8599364513L,64514L,64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,
8599464523L,64524L,64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,
8599564533L,64534L,64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,
8599664543L,64544L,64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,
8599764553L,64554L,64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,
8599864563L,64564L,64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,
8599964573L,64574L,64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,
8600064583L,64584L,64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,
8600164593L,64594L,64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,
8600264603L,64604L,64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,
8600364613L,64614L,64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,
8600464623L,64624L,64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,
8600564633L,64634L,64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,
8600664643L,64644L,64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,
8600764653L,64654L,64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,
8600864663L,64664L,64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,
8600964673L,64674L,64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,
8601064683L,64684L,64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,
8601164693L,64694L,64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,
8601264703L,64704L,64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,
8601364713L,64714L,64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,
8601464723L,64724L,64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,
8601564733L,64734L,64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,
8601664743L,64744L,64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,
8601764753L,64754L,64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,
8601864763L,64764L,64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,
8601964773L,64774L,64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,
8602064783L,64784L,64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,
8602164793L,64794L,64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,
8602264803L,64804L,64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,
8602364813L,64814L,64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,
8602464823L,64824L,64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,
8602564833L,64834L,64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,
8602664843L,64844L,64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,
8602764853L,64854L,64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,
8602864863L,64864L,64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,
8602964873L,64874L,64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,
8603064883L,64884L,64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,
8603164893L,64894L,64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,
8603264903L,64904L,64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,
8603364913L,64914L,64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,
8603464923L,64924L,64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,
8603564933L,64934L,64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,
8603664943L,64944L,64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,
8603764953L,64954L,64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,
8603864963L,64964L,64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,
8603964973L,64974L,64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,
8604064983L,64984L,64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,
8604164993L,64994L,64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,
8604265003L,65004L,65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,
8604365013L,65014L,65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,
8604465023L,65024L,65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,
8604565033L,65034L,65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,
8604665043L,65044L,65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,
8604765053L,65054L,65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,
8604865063L,65064L,65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,
8604965073L,65074L,65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,
8605065083L,65084L,65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,
8605165093L,65094L,65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,
8605265103L,65104L,65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,
8605365113L,65114L,65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,
8605465123L,65124L,65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,
8605565133L,65134L,65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,
8605665143L,65144L,65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,
8605765153L,65154L,65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,
8605865163L,65164L,65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,
8605965173L,65174L,65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,
8606065183L,65184L,65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,
8606165193L,65194L,65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,
8606265203L,65204L,65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,
8606365213L,65214L,65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,
8606465223L,65224L,65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,
8606565233L,65234L,65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,
8606665243L,65244L,65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,
8606765253L,65254L,65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,
8606865263L,65264L,65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,
8606965273L,65274L,65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,
8607065283L,65284L,65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,
8607165293L,65294L,65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,
8607265303L,65304L,65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,
8607365313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
8607465323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
8607565333L,65334L,65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,
8607665343L,65344L,65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,
8607765321L,65322L,65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,
8607865331L,65332L,65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,
8607965373L,65374L,65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,
8608065383L,65384L,65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,
8608165393L,65394L,65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,
8608265403L,65404L,65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,
8608365413L,65414L,65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,
8608465423L,65424L,65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,
8608565433L,65434L,65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,
8608665443L,65444L,65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,
8608765453L,65454L,65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,
8608865463L,65464L,65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,
8608965473L,65474L,65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,
8609065483L,65484L,65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,
8609165493L,65494L,65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,
8609265503L,65504L,65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,
8609365513L,65514L,65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,
8609465523L,65524L,65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,
8609565533L,65534L,65535L,
86096};
86097#endif
86098#line 1 "duk_util_bitdecoder.c"
86099/*
86100 * Bitstream decoder.
86101 */
86102
86103/* include removed: duk_internal.h */
86104
86105/* Decode 'bits' bits from the input stream (bits must be 1...24).
86106 * When reading past bitstream end, zeroes are shifted in. The result
86107 * is signed to match duk_bd_decode_flagged.
86108 */
86110 duk_small_int_t shift;
86111 duk_uint32_t mask;
86112 duk_uint32_t tmp;
86113
86114 /* Note: cannot read more than 24 bits without possibly shifting top bits out.
86115 * Fixable, but adds complexity.
86116 */
86117 DUK_ASSERT(bits >= 1 && bits <= 24);
86118
86119 while (ctx->currbits < bits) {
86120#if 0
86121 DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
86122 (long) bits, (long) ctx->currbits));
86123#endif
86124 ctx->currval <<= 8;
86125 if (ctx->offset < ctx->length) {
86126 /* If ctx->offset >= ctx->length, we "shift zeroes in"
86127 * instead of croaking.
86128 */
86129 ctx->currval |= ctx->data[ctx->offset++];
86130 }
86131 ctx->currbits += 8;
86132 }
86133#if 0
86134 DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
86135 (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
86136#endif
86138 /* Extract 'top' bits of currval; note that the extracted bits do not need
86139 * to be cleared, we just ignore them on next round.
86140 */
86141 shift = ctx->currbits - bits;
86142 mask = (1 << bits) - 1;
86143 tmp = (ctx->currval >> shift) & mask;
86144 ctx->currbits = shift; /* remaining */
86146#if 0
86147 DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
86148 (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
86149#endif
86150
86151 return tmp;
86152}
86153
86155 return (duk_small_int_t) duk_bd_decode(ctx, 1);
86156}
86157
86158/* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
86159 * default value. Return value is signed so that negative marker value can be
86160 * used by caller as a "not present" value.
86161 */
86162DUK_INTERNAL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
86163 if (duk_bd_decode_flag(ctx)) {
86164 return (duk_int32_t) duk_bd_decode(ctx, bits);
86165 } else {
86166 return def_value;
86167 }
86168}
86169#line 1 "duk_util_bitencoder.c"
86170/*
86171 * Bitstream encoder.
86172 */
86173
86174/* include removed: duk_internal.h */
86175
86176DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
86177 duk_uint8_t tmp;
86178
86179 DUK_ASSERT(ctx != NULL);
86180 DUK_ASSERT(ctx->currbits < 8);
86181
86182 /* This limitation would be fixable but adds unnecessary complexity. */
86183 DUK_ASSERT(bits >= 1 && bits <= 24);
86185 ctx->currval = (ctx->currval << bits) | data;
86186 ctx->currbits += bits;
86187
86188 while (ctx->currbits >= 8) {
86189 if (ctx->offset < ctx->length) {
86190 tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
86191 ctx->data[ctx->offset++] = tmp;
86192 } else {
86193 /* If buffer has been exhausted, truncate bitstream */
86194 ctx->truncated = 1;
86195 }
86196
86197 ctx->currbits -= 8;
86198 }
86199}
86200
86202 duk_small_int_t npad;
86203
86204 DUK_ASSERT(ctx != NULL);
86205 DUK_ASSERT(ctx->currbits < 8);
86206
86207 npad = (duk_small_int_t) (8 - ctx->currbits);
86208 if (npad > 0) {
86209 duk_be_encode(ctx, 0, npad);
86210 }
86211 DUK_ASSERT(ctx->currbits == 0);
86212}
86213#line 1 "duk_util_bufwriter.c"
86214/*
86215 * Fast buffer writer with spare management.
86216 */
86217
86218/* include removed: duk_internal.h */
86219
86220/*
86221 * Macro support functions (use only macros in calling code)
86222 */
86223
86224DUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t curr_offset, duk_size_t new_length) {
86225 duk_uint8_t *p;
86226
86227 DUK_ASSERT(thr != NULL);
86228 DUK_ASSERT(bw_ctx != NULL);
86229 DUK_UNREF(thr);
86230
86231 p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
86232 DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
86233 bw_ctx->p = p + curr_offset;
86234 bw_ctx->p_base = p;
86235 bw_ctx->p_limit = p + new_length;
86236}
86237
86239
86240 DUK_ASSERT(thr != NULL);
86241 DUK_ASSERT(bw_ctx != NULL);
86242 DUK_ASSERT(h_buf != NULL);
86243 DUK_UNREF(thr);
86244
86245 bw_ctx->buf = h_buf;
86246 duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
86248
86250 duk_context *ctx;
86251
86252 DUK_ASSERT(thr != NULL);
86253 DUK_ASSERT(bw_ctx != NULL);
86254 ctx = (duk_context *) thr;
86255
86256 (void) duk_push_dynamic_buffer(ctx, buf_size);
86257 bw_ctx->buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
86258 duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
86259}
86260
86261/* Resize target buffer for requested size. Called by the macro only when the
86262 * fast path test (= there is space) fails.
86263 */
86264DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
86265 duk_size_t curr_off;
86266 duk_size_t add_sz;
86267 duk_size_t new_sz;
86268
86269 DUK_ASSERT(thr != NULL);
86270 DUK_ASSERT(bw_ctx != NULL);
86271
86272 /* We could do this operation without caller updating bw_ctx->ptr,
86273 * but by writing it back here we can share code better.
86274 */
86275
86276 curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
86277 add_sz = (curr_off >> DUK_BW_SPARE_SHIFT) + DUK_BW_SPARE_ADD;
86278 new_sz = curr_off + sz + add_sz;
86279 if (new_sz < curr_off) {
86280 /* overflow */
86282 return NULL; /* not reachable */
86283 }
86284#if 0 /* for manual torture testing: tight allocation, useful with valgrind */
86285 new_sz = curr_off + sz;
86286#endif
86287
86288 /* This is important to ensure dynamic buffer data pointer is not
86289 * NULL (which is possible if buffer size is zero), which in turn
86290 * causes portability issues with e.g. memmove() and memcpy().
86291 */
86292 DUK_ASSERT(new_sz >= 1);
86293
86294 DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
86295
86296 duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
86297 duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
86298 return bw_ctx->p;
86299}
86300
86301/* Make buffer compact, matching current written size. */
86303 duk_size_t len;
86304
86305 DUK_ASSERT(thr != NULL);
86306 DUK_ASSERT(bw_ctx != NULL);
86307 DUK_UNREF(thr);
86308
86309 len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
86310 duk_hbuffer_resize(thr, bw_ctx->buf, len);
86311 duk__bw_update_ptrs(thr, bw_ctx, len, len);
86312}
86313
86315 duk_uint8_t *p_base;
86316
86317 DUK_ASSERT(thr != NULL);
86318 DUK_ASSERT(bw != NULL);
86319 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86320 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86321 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86322 DUK_UNREF(thr);
86323
86324 p_base = bw->p_base;
86325 DUK_MEMCPY((void *) bw->p,
86326 (const void *) (p_base + src_off),
86327 (size_t) len);
86328 bw->p += len;
86329}
86330
86332 DUK_ASSERT(thr != NULL);
86333 DUK_ASSERT(bw != NULL);
86334 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86335 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86336 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86337 DUK_UNREF(thr);
86338
86339 DUK_BW_ENSURE(thr, bw, len);
86340 duk_bw_write_raw_slice(thr, bw, src_off, len);
86341}
86342
86343DUK_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) {
86344 duk_uint8_t *p_base;
86345 duk_size_t buf_sz, move_sz;
86346
86347 DUK_ASSERT(thr != NULL);
86348 DUK_ASSERT(bw != NULL);
86349 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86351 DUK_UNREF(thr);
86352
86353 p_base = bw->p_base;
86354 buf_sz = bw->p - p_base;
86355 move_sz = buf_sz - dst_off;
86356
86357 DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
86358 DUK_MEMMOVE((void *) (p_base + dst_off + len),
86359 (const void *) (p_base + dst_off),
86360 (size_t) move_sz);
86361 DUK_MEMCPY((void *) (p_base + dst_off),
86362 (const void *) buf,
86363 (size_t) len);
86364 bw->p += len;
86365}
86366
86367DUK_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) {
86368 DUK_ASSERT(thr != NULL);
86369 DUK_ASSERT(bw != NULL);
86370 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86371 DUK_ASSERT(buf != NULL);
86372 DUK_UNREF(thr);
86373
86374 DUK_BW_ENSURE(thr, bw, len);
86375 duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
86376}
86377
86379 duk_uint8_t *p_base;
86380 duk_size_t buf_sz, move_sz;
86381
86382 DUK_ASSERT(thr != NULL);
86383 DUK_ASSERT(bw != NULL);
86384 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86385 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86386 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86387 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86388 DUK_UNREF(thr);
86389
86390 p_base = bw->p_base;
86391
86392 /* Don't support "straddled" source now. */
86393 DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
86394
86395 if (dst_off <= src_off) {
86396 /* Target is before source. Source offset is expressed as
86397 * a "before change" offset. Account for the memmove.
86399 src_off += len;
86400 }
86401
86402 buf_sz = bw->p - p_base;
86403 move_sz = buf_sz - dst_off;
86404
86405 DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
86406 DUK_MEMMOVE((void *) (p_base + dst_off + len),
86407 (const void *) (p_base + dst_off),
86408 (size_t) move_sz);
86409 DUK_MEMCPY((void *) (p_base + dst_off),
86410 (const void *) (p_base + src_off),
86411 (size_t) len);
86412 bw->p += len;
86413}
86416 DUK_ASSERT(thr != NULL);
86417 DUK_ASSERT(bw != NULL);
86418 DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86419 DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86420 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86421 DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86422 DUK_UNREF(thr);
86423
86424 /* Don't support "straddled" source now. */
86425 DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
86426
86427 DUK_BW_ENSURE(thr, bw, len);
86428 duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
86429}
86430
86432 duk_uint8_t *p_base, *p_dst, *p_src;
86433 duk_size_t buf_sz, move_sz;
86434
86435 DUK_ASSERT(thr != NULL);
86436 DUK_ASSERT(bw != NULL);
86437 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86438 DUK_UNREF(thr);
86439
86440 p_base = bw->p_base;
86441 buf_sz = bw->p - p_base;
86442 move_sz = buf_sz - off;
86443 p_dst = p_base + off + len;
86444 p_src = p_base + off;
86445 DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);
86446 return p_src; /* point to start of 'reserved area' */
86447}
86448
86450 DUK_ASSERT(thr != NULL);
86451 DUK_ASSERT(bw != NULL);
86452 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86453 DUK_UNREF(thr);
86454
86455 DUK_BW_ENSURE(thr, bw, len);
86456 return duk_bw_insert_raw_area(thr, bw, off, len);
86457}
86458
86460 duk_size_t move_sz;
86461
86462 duk_uint8_t *p_base;
86463 duk_uint8_t *p_src;
86464 duk_uint8_t *p_dst;
86465
86466 DUK_ASSERT(thr != NULL);
86467 DUK_ASSERT(bw != NULL);
86468 DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86469 DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86470 DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
86471 DUK_UNREF(thr);
86472
86473 p_base = bw->p_base;
86474 p_dst = p_base + off;
86475 p_src = p_dst + len;
86476 move_sz = (duk_size_t) (bw->p - p_src);
86477 DUK_MEMMOVE((void *) p_dst,
86478 (const void *) p_src,
86479 (size_t) move_sz);
86480 bw->p -= len;
86481}
86482
86483/*
86484 * Macro support functions for reading/writing raw data.
86485 *
86486 * These are done using mempcy to ensure they're valid even for unaligned
86487 * reads/writes on platforms where alignment counts. On x86 at least gcc
86488 * is able to compile these into a bswap+mov. "Always inline" is used to
86489 * ensure these macros compile to minimal code.
86490 *
86491 * Not really bufwriter related, but currently used together.
86492 */
86493
86494DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
86495 union {
86496 duk_uint8_t b[2];
86497 duk_uint16_t x;
86498 } u;
86499
86500 DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);
86501 u.x = DUK_NTOH16(u.x);
86502 *p += 2;
86503 return u.x;
86504}
86505
86506DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
86507 union {
86508 duk_uint8_t b[4];
86509 duk_uint32_t x;
86510 } u;
86511
86512 DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
86513 u.x = DUK_NTOH32(u.x);
86514 *p += 4;
86515 return u.x;
86516}
86517
86520 union {
86521 duk_uint8_t b[4];
86522 duk_uint32_t x;
86523 } u;
86524
86525 DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
86526 u.x = DUK_NTOH32(u.x);
86527 du.ui[DUK_DBL_IDX_UI0] = u.x;
86528 DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);
86529 u.x = DUK_NTOH32(u.x);
86530 du.ui[DUK_DBL_IDX_UI1] = u.x;
86531 *p += 8;
86532
86533 return du.d;
86534}
86535
86536DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
86537 union {
86538 duk_uint8_t b[2];
86539 duk_uint16_t x;
86540 } u;
86542 u.x = DUK_HTON16(val);
86543 DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);
86544 *p += 2;
86545}
86546
86547DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
86548 union {
86549 duk_uint8_t b[4];
86550 duk_uint32_t x;
86551 } u;
86552
86553 u.x = DUK_HTON32(val);
86554 DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
86555 *p += 4;
86556}
86557
86560 union {
86561 duk_uint8_t b[4];
86562 duk_uint32_t x;
86563 } u;
86564
86565 du.d = val;
86566 u.x = du.ui[DUK_DBL_IDX_UI0];
86567 u.x = DUK_HTON32(u.x);
86568 DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
86569 u.x = du.ui[DUK_DBL_IDX_UI1];
86570 u.x = DUK_HTON32(u.x);
86571 DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);
86572 *p += 8;
86573}
86574#line 1 "duk_util_hashbytes.c"
86575/*
86576 * Hash function duk_util_hashbytes().
86577 *
86578 * Currently, 32-bit MurmurHash2.
86579 *
86580 * Don't rely on specific hash values; hash function may be endianness
86581 * dependent, for instance.
86582 */
86583
86584/* include removed: duk_internal.h */
86585
86586#if defined(DUK_USE_STRHASH_DENSE)
86587/* 'magic' constants for Murmurhash2 */
86588#define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL)
86589#define DUK__MAGIC_R 24
86590
86591DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
86592 duk_uint32_t h = seed ^ ((duk_uint32_t) len);
86593
86594 while (len >= 4) {
86595 /* Portability workaround is required for platforms without
86596 * unaligned access. The replacement code emulates little
86597 * endian access even on big endian architectures, which is
86598 * OK as long as it is consistent for a build.
86599 */
86600#ifdef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
86601 duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
86602#else
86603 duk_uint32_t k = ((duk_uint32_t) data[0]) |
86604 (((duk_uint32_t) data[1]) << 8) |
86605 (((duk_uint32_t) data[2]) << 16) |
86606 (((duk_uint32_t) data[3]) << 24);
86607#endif
86608
86609 k *= DUK__MAGIC_M;
86610 k ^= k >> DUK__MAGIC_R;
86611 k *= DUK__MAGIC_M;
86612 h *= DUK__MAGIC_M;
86613 h ^= k;
86614 data += 4;
86615 len -= 4;
86616 }
86617
86618 switch (len) {
86619 case 3: h ^= data[2] << 16;
86620 case 2: h ^= data[1] << 8;
86621 case 1: h ^= data[0];
86622 h *= DUK__MAGIC_M;
86623 }
86624
86625 h ^= h >> 13;
86626 h *= DUK__MAGIC_M;
86627 h ^= h >> 15;
86628
86629 return h;
86630}
86631#endif /* DUK_USE_STRHASH_DENSE */
86632#line 1 "duk_util_tinyrandom.c"
86634 * A tiny random number generator.
86635 *
86636 * Currently used for Math.random().
86637 *
86638 * http://www.woodmann.com/forum/archive/index.php/t-3100.html
86639 */
86640
86641/* include removed: duk_internal.h */
86642
86643#define DUK__UPDATE_RND(rnd) do { \
86644 (rnd) += ((rnd) * (rnd)) | 0x05; \
86645 (rnd) = ((rnd) & 0xffffffffU); /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
86646 } while (0)
86647
86648#define DUK__RND_BIT(rnd) ((rnd) >> 31) /* only use the highest bit */
86649
86652 duk_uint32_t res = 0;
86653 duk_uint32_t rnd;
86654
86655 rnd = thr->heap->rnd_state;
86656
86657 for (i = 0; i < n; i++) {
86658 DUK__UPDATE_RND(rnd);
86659 res <<= 1;
86660 res += DUK__RND_BIT(rnd);
86661 }
86662
86663 thr->heap->rnd_state = rnd;
86664
86665 return res;
86666}
86667
86669 duk_double_t t;
86671 duk_uint32_t rnd;
86672
86673 /*
86674 * XXX: could make this a lot faster if we create the double memory
86675 * representation directly. Feasible easily (must be uniform random).
86676 */
86677
86678 rnd = thr->heap->rnd_state;
86679
86680 n = 53; /* enough to cover the whole mantissa */
86681 t = 0.0;
86682
86683 do {
86684 DUK__UPDATE_RND(rnd);
86685 t += DUK__RND_BIT(rnd);
86686 t /= 2.0;
86687 } while (--n);
86688
86689 thr->heap->rnd_state = rnd;
86690
86691 DUK_ASSERT(t >= (duk_double_t) 0.0);
86692 DUK_ASSERT(t < (duk_double_t) 1.0);
86693
86694 return t;
86695}
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
duk_int32_t duk_reg_t
duk_uint32_t duk_regconst_t
duk_uint32_t duk_instr_t
#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]
DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc)
#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_OP_POSTINCR
#define DUK__ISHEXDIGIT(x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index)
#define DUK_OP_LDINT
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
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__BI_MAX_PARTS
DUK_INTERNAL_DECL void * duk_default_alloc_function(void *udata, duk_size_t size)
#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, x)
#define DUK_ASC_LC_M
DUK_INTERNAL const char * duk_str_invalid_func_name
#define DUK_LJ_TYPE_THROW
#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 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 duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx)
DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val)
#define DUK_TVAL_DECREF(thr, tv)
#define DUK_ASC_SLASH
#define DUK_MS_FLAG_NO_OBJECT_COMPACTION
#define DUK_STRIDX_TO_LOCALE_STRING
#define DUK_TOK_DEFAULT
#define DUK_TOK_SUB
#define DUK__FUNCTION_BODY_REQUIRE_SLOTS
#define DUK__BP_ASSIGNMENT
#define DUK_ASC_LC_N
#define DUK_RETOK_DISJUNCTION
#define DUK_HSTRING_GET_ARRIDX_FAST(h)
#define DUK_TOK_ARSHIFT_EQ
#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, 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)
#define DUK__PM_SECOND
#define DUK_OP_TRYCATCH
DUK_EXTERNAL void * duk_to_pointer(duk_context *ctx, duk_idx_t index)
#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE
#define DUK_ASC_LC_U
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)
#define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap, h, v)
DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp)
DUK_INTERNAL_DECL duk_hobject * duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags)
#define DUK__BP_BAND
#define DUK_TVAL_SET_TVAL(v, x)
#define DUK_BIDX_UINT8ARRAY_PROTOTYPE
DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx)
#define DUK__LOCAL_TZOFFSET_MAXITER
DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags)
#define DUK_ACT_FLAG_PREVENT_YIELD
DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap)
#define DUK__SM_PERIOD
DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx)
#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)
#define DUK_STRIDX_INT_CALLEE
#define DUK_DEC_OP(x)
#define DUK_OP_JUMP
#define DUK_ERROR_RANGE(thr, msg)
#define DUK_EXTRAOP_INVLHS
#define DUK_HOBJECT_FLAG_NEWENV
#define DUK_DBG_IB_EOM
#define DUK_TOK_DO
#define DUK_HSTRING_HAS_ASCII(x)
DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc)
#define DUK_LJ_TYPE_CONTINUE
#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
#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)
#define DUK_STRIDX_INT_ARGS
struct duk_breakpoint duk_breakpoint
#define DUK__ISDIGIT(x)
DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx)
DUK_INTERNAL const char * duk_str_invalid_break_cont_label
#define DUK_COMPILER_MAX_BYTECODE_LENGTH
#define DUK_TOK_INCREMENT
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)
#define DUK_ASC_LPAREN
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_LJ_TYPE_YIELD
DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx)
#define DUK_ASC_DOUBLEQUOTE
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx)
DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx)
#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_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx)
#define DUK_HBUFFER_SET_EXTERNAL(x)
#define DUK_STR_NUMBER_OUTSIDE_RANGE
#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)
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_INT_THIS
#define DUK_DEC_B(x)
#define DUK_STRIDX_BYTE_OFFSET
#define DUK_DBG_IB_OBJECT
DUK_LOCAL double duk__asin(double 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)
DUK_INTERNAL_DECL const char * duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv)
#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_REOP_MATCH
#define DUK_BW_ADD_PTR(thr, bw_ctx, delta)
#define DUK_DBG_IB_NOTIFY
#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
#define DUK__PM_MINUTE
DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr)
#define DUK_STRIDX_LC_TRACE
DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx)
#define DUK__ADVANCEBYTES(lex_ctx, count)
#define DUK_ASC_PIPE
#define DUK_DBG_IB_NUMBER
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
#define DUK_TOK_RCURLY
#define DUK_OP_SNEQ
DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[]
#define DUK__PI_TZMINUTE
DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins)
#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)
#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)
#define DUK__NO_ARRAY_INDEX
DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year)
#define DUK_EXTRAOP_THROW
DUK_INTERNAL const char * duk_str_catchstack_limit
#define DUK_STRIDX_HAS
#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT
DUK_EXTERNAL const char * duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len)
#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_hbuffer * duk_get_hbuffer(duk_context *ctx, duk_idx_t index)
#define DUK_OP_STREG
DUK_INTERNAL const char * duk_str_prototype_chain_limit
#define DUK_TAG_POINTER
DUK_LOCAL void duk__sort_array_indices(duk_hthread *thr, duk_hobject *h_obj)
DUK_LOCAL_DECL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
#define DUK_REOP_RANGES
DUK_INTERNAL_DECL void * duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize)
#define DUK_HOBJECT_A_MIN_GROW_ADD
#define DUK_ASC_LC_Z
#define DUK_HSTRING_IS_ASCII(x)
#define DUK_HEAPHDR_SET_TEMPROOT(h)
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_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)
#define DUK_ASC_2
#define DUK_REOP_ASSERT_WORD_BOUNDARY
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 void duk__clear_refzero_list_flags(duk_heap *heap)
#define DUK_TVAL_SET_FASTINT_U32(tv, val)
#define DUK_OP_NONE
#define DUK_LABEL_FLAG_ALLOW_BREAK
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x)
DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val)
#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)
#define DUK_DECL_TYPE_VAR
DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z)
#define DUK__NARGS_VARARGS_MARKER
#define DUK_STR_NOT_CALLABLE
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_INT_REGBASE
#define DUK_STRIDX_BRACKETED_ELLIPSIS
#define DUK_STRIDX_ENUMERABLE
#define DUK_TOK_MUL
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_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)
#define DUK__SER_STRING
#define DUK_OP_PREDECP
#define DUK_S2N_FLAG_ALLOW_FRAC
#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY
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)
#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_LOCAL double duk__atan(double x)
#define DUK_TVAL_IS_NUMBER(tv)
DUK_INTERNAL_DECL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx)
DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256]
#define DUK_STR_NOT_COMPILEDFUNCTION
DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr)
#define DUK_IVAL_VAR
#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)
#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 void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h)
#define DUK_TOK_EQUALSIGN
DUK_INTERNAL const char * duk_str_invalid_label
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 duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx)
#define DUK_HOBJECT_HAS_BOUND(h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx)
#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap)
DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx)
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)
#define DUK_STR_NOT_WRITABLE
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)
#define DUK_CAT_LABEL_SHIFT
DUK_EXTERNAL void duk_push_this(duk_context *ctx)
DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr)
#define DUK_PC2LINE_MAX_DIFF_LENGTH
DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx)
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum)
#define DUK_BIDX_EVAL_ERROR_PROTOTYPE
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_STR_INVALID_LABEL
#define DUK_STR_DEFAULTVALUE_COERCE_FAILED
#define DUK_RETOK_ATOM_PERIOD
#define DUK_HOBJECT_POSTINC_ENEXT(h)
#define DUK_DBG_CMD_GETBYTECODE
#define DUK_STRIDX_LC_BUFFER
#define DUK_OP_DELPROP
#define DUK_DEC_A(x)
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)
#define DUK__FLD_FLOAT
#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_STR_FMT_PTR
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp)
#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)
#define DUK__ERRFMT_BUFSIZE
#define DUK__ITER_SOME
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__PROP_FLAGS_BITS
#define DUK_RAW_WRITE_U16_BE(ptr, val)
#define DUK_ALLOC(heap, size)
#define DUK_STRIDX_MOD_LOADED
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index)
#define DUK__EXPR_FLAG_REQUIRE_INIT
DUK_INTERNAL_DECL void * duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud)
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_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)
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_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx)
#define DUK_ASC_AMP
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)
#define DUK_ASC_NUL
#define DUK_TAG_NULL
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_RETOK_EOF
#define DUK_CALL_FLAG_CONSTRUCTOR_CALL
const duk_uint8_t duk_unicode_caseconv_uc[1288]
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)
#define DUK_DBG_IB_NULL
DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind)
DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_FLAG_NAMEBINDING
#define DUK_TOK_THIS
#define DUK_HOBJECT_CMASK_BOOLEAN
#define DUK_IVAL_ARITH_EXTRAOP
#define DUK__SETTEMP_CHECKMAX(comp_ctx, x)
#define DUK_ASC_EXCLAMATION
#define DUK_TOK_LNOT
DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n)
#define DUK__MAX_OUTPUT_DIGITS
#define DUK__CONSTP(x)
#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
#define DUK_STRIDX_ENUMERATE
DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2)
DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING
DUK_INTERNAL const duk_uint8_t duk_initjs_data[204]
#define DUK_STRIDX_RAW
#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_OP_SUB
#define DUK_STRIDX_TO_UTC_STRING
#define DUK_LFUNC_NARGS_MAX
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx)
#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__PM_TZHOUR
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx)
#define DUK_STR_NO_SOURCECODE
#define DUK__MAX_RE_QUANT_DIGITS
DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv)
#define DUK_STRIDX_ARRAY
#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_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx)
DUK_INTERNAL const char * duk_str_c_callstack_limit
#define DUK_STR_INVALID_TRY
#define DUK__PM_DAY
#define DUK__BP_SHIFT
#define DUK_STRTAB_MIN_USED_DIVISOR
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)
#define DUK_EXTRAOP_UNP
#define DUK_TOK_ADD
#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_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx)
DUK_EXTERNAL const char * duk_hex_encode(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx)
DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk_idx_t nargs)
#define DUK_BW_WRITE_RAW_U8_3(thr, bw_ctx, val1, val2, val3)
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_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)
DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr)
#define DUK_STRIDX_LC_ARGUMENTS
#define DUK_STRIDX_GLOBAL
#define DUK_STR_POP_TOO_MANY
DUK_INTERNAL const char * duk_str_property_is_virtual
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx)
DUK_LOCAL const duk_uint8_t duk__token_lbp[]
DUK_LOCAL double duk__sin(double x)
DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p)
DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y)
DUK_INTERNAL_DECL void * duk_heap_mem_alloc(duk_heap *heap, duk_size_t size)
#define DUK_HSTRING_NO_ARRAY_INDEX
DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index)
#define DUK_ASC_UC_T
#define DUK_GETDESC_FLAG_PUSH_VALUE
#define DUK_COMPARE_FLAG_NEGATE
#define DUK_TOK_IDENTIFIER
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_HOBJECT_E_SLOT_IS_ENUMERABLE(heap, h, i)
#define DUK__ADVTOK(advbytes, tok)
#define DUK_OP_MPUTOBJ
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 void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget)
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx)
#define DUK_TOK_BXOR
#define DUK_HTHREAD_STRING_BASE64(thr)
DUK_EXTERNAL void * duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx)
#define DUK_TOK_GT
#define DUK_DELPROP_FLAG_THROW
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 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)
#define DUK_TOK_IF
duk_int32_t duk_reg_t
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx)
#define DUK_ASC_8
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp)
DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t magic)
DUK_INTERNAL_DECL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf)
DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_size_t cat_idx, duk_small_uint_t lj_type)
#define DUK_ASC_5
#define DUK__ITER_MAP
#define DUK_OP_MOD
DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags)
DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type)
#define DUK_BC_EXTRAOP_MAX
#define DUK_STRIDX_UC_BOOLEAN
#define DUK__FLD_DOUBLE
#define DUK_TVAL_SET_OBJECT(tv, hptr)
DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx)
#define DUK__MAX_OBJECT_INIT_PAIRS
#define DUK_STRIDX_LC_WARN
#define DUK_STRDATA_MAX_STRLEN
#define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap)
#define DUK_STR_INVALID_SWITCH
#define DUK__CF_ACCEPT_NUL
#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)
#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x, v)
#define DUK__MAX_ARRAY_INIT_VALUES
#define DUK_UNICODE_CP_ZWNJ
#define DUK__JSON_DECSTR_CHUNKSIZE
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value)
DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx)
DUK_INTERNAL const char * duk_str_invalid_call_args
#define DUK_OP_POSTINCP
#define DUK__MAX_FORMATTED_LENGTH
#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)
const duk_uint8_t duk_unicode_idp_m_ids_noa[397]
#define DUK__BP_BXOR
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 void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs)
#define DUK_GET_HOBJECT_NEGIDX(ctx, idx)
#define DUK_BW_SET_SIZE(thr, bw_ctx, sz)
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_EXTERNAL const char * duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len)
#define DUK__PI_HOUR
DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z)
#define DUK_HOBJECT_GET_PROPS(heap, h)
#define DUK__SER_VERSION
#define DUK_STR_INVALID_VAR_DECLARATION
DUK_INTERNAL_DECL void duk_hthread_catchstack_grow(duk_hthread *thr)
#define DUK_STRIDX_JSON_EXT_UNDEFINED
#define DUK_STRIDX_FMT
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(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_hthread * duk_require_hthread(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_E_GET_KEY_BASE(heap, h)
DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size)
#define DUK_TOK_BNOT
#define DUK__SER_MARKER
#define DUK_STRIDX_INT_HANDLER
DUK_EXTERNAL void duk_push_boolean(duk_context *ctx, duk_bool_t val)
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_error_prototype_filename_setter(duk_context *ctx)
DUK_INTERNAL_DECL void duk_push_hstring(duk_context *ctx, duk_hstring *h)
#define DUK_HEAP_NUM_STRINGS
#define DUK_STRIDX_TRUE
DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr)
#define DUK_DBG_ERR_UNKNOWN
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx)
#define duk_xdef_prop_stridx_wec(ctx, obj_index, stridx)
#define DUK_STR_DECODE_FAILED
DUK_INTERNAL_DECL duk_hcompiledfunction * duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index)
DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size)
#define DUK_DDD(x)
#define DUK__STRPTIME_BUF_SIZE
#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_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_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)
#define DUK__SETTEMP(comp_ctx, x)
#define DUK_RETOK_ATOM_START_CHARCLASS
#define DUK_ASC_RANGLE
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx)
#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)
#define DUK_STRIDX_SOURCE
#define DUK__L3()
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_ASC_9
#define DUK_STR_SETTER_UNDEFINED
DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK_OP_LDREG
#define DUK_STRTAB_MIN_FREE_DIVISOR
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)
#define DUK_STRIDX_MATH
#define DUK_ASC_LC_X
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx)
DUK_INTERNAL const duk_uint8_t duk_strings_data[1049]
#define DUK_OP_PUTVAR
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
#define DUK_STEP_TYPE_INTO
DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv)
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_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx)
#define DUK_COMPILER_TOKEN_LIMIT
#define DUK_STRIDX_INT_NEXT
#define DUK_STR_NOT_NATIVEFUNCTION
DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key)
#define DUK_HOBJECT_A_GET_BASE(heap, h)
DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act)
#define DUK_CAT_CLEAR_CATCH_ENABLED(c)
#define DUK_EXTRAOP_ENDTRY
#define DUK_HOBJECT_A_ABANDON_LIMIT
#define DUK__OBJ_LIT_KEY_PLAIN
#define DUK_STRIDX_TYPE
#define DUK_DBG_PROPFLAG_INTERNAL
#define DUK_STRIDX_FLOAT32_ARRAY
#define DUK_ASC_6
#define DUK_BIDX_TYPE_ERROR_PROTOTYPE
#define DUK_TOK_LT
#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 int duk_repl_isinf(double x)
#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
#define DUK_REOP_ASSERT_END
DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap)
DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h)
#define DUK__ENUM_START_INDEX
#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__STILL_PROLOGUE
#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)
#define DUK_TOK_BAND
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_SPACE
#define DUK_STRIDX_BYTE_LENGTH
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap, h)
#define DUK_OP_IF
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year)
#define DUK_TVAL_IS_BUFFER(tv)
#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC
#define DUK_STRIDX_UC_NUMBER
#define DUK_HEAPHDR_GET_PREV(heap, h)
DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx)
#define DUK__MK_LBP(bp)
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx)
#define DUK_OP_BOR
#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)
#define DUK_ASC_7
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx)
#define DUK__NUMCONV_CTX_BIGINTS_SIZE
static const duk_uint8_t duk__buffer_class_from_elemtype[9]
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_STRIDX_START_RESERVED
#define DUK_OP_PREDECR
#define DUK__MAX_TEMPS
DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str)
#define DUK_BIDX_DOUBLE_ERROR
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)
DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx)
#define DUK__ISOCTDIGIT(x)
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val)
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 duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx)
#define DUK_TOK_FINALLY
#define DUK_OP_PREINCP
#define DUK_LFUNC_LENGTH_MAX
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx)
#define DUK_TVAL_SET_UNUSED_UPDREF
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_STR_VALSTACK_LIMIT
#define DUK__JSON_DECSTR_BUFSIZE
#define DUK_BW_COMPACT(thr, bw_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx)
DUK_INTERNAL_DECL duk_hstring * duk_to_hstring(duk_context *ctx, duk_idx_t index)
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)
DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg)
#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
#define DUK_DECL_TYPE_FUNC
DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z)
#define DUK_DBG_CMD_PRINT
#define DUK_STRIDX_MESSAGE
#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM
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_EXTRAOP_SETALEN
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
#define DUK_STRIDX_FILE_NAME
DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj)
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)
#define DUK_TVAL_IS_UNDEFINED(tv)
#define DUK__EXPR_FLAG_REJECT_IN
#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
#define DUK_STRIDX_SET
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)
#define DUK__FLD_16BIT
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
#define DUK_BC_REGLIMIT
DUK_INTERNAL_DECL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h)
DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK_TOK_DIV_EQ
#define DUK_ASC_LC_C
DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx)
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)
#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)
#define DUK__MKBITS(a, b, c, d, e, f, g, h)
#define DUK_TOK_EQ
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
DUK_INTERNAL_DECL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top)
#define DUK_EXTRAOP_NEXTENUM
#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)
DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x)
#define DUK_STRIDX_COMMA
DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_SET_BUFFER(tv, hptr)
DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top)
#define DUK_ASC_1
#define DUK__HASH_SIZE_RATIO
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx)
#define DUK_TVAL_IS_OBJECT(tv)
#define DUK_HOBJECT_IS_OBJENV(h)
#define DUK_TOK_NUMBER
#define DUK_HOBJECT_CLASS_INT16ARRAY
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx)
DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index)
#define DUK_ASC_RBRACKET
DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx)
#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS
#define DUK_HEAPHDR_FLAG_TEMPROOT
#define DUK_JSON_FLAG_AVOID_KEY_QUOTES
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx)
#define DUK_TOK_MAXVAL
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags)
#define DUK_HOBJECT_SET_CREATEARGS(h)
DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_DBG_IB_UNUSED
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 const char * duk_str_bound_chain_limit
DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[]
DUK_INTERNAL_DECL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h)
DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp)
#define DUK_ERROR_SYNTAX(thr, msg)
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx)
#define DUK_HTHREAD_STRING_BYTE_LENGTH(thr)
#define DUK_BIDX_FUNCTION_PROTOTYPE
#define DUK__L0()
#define DUK_DBG_CMD_ALERT
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx)
#define DUK_PROPDESC_FLAGS_NONE
DUK_INTERNAL_DECL duk_hcompiledfunction * duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags)
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_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value)
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 duk_ret_t duk_bi_date_constructor(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx)
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_INTERNAL_DECL void * duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize)
double(* duk__two_arg_func)(double, double)
DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc)
DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p)
DUK_EXTERNAL void * duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst)
DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase)
DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx)
#define DUK_BI_DATE_ISO8601_BUFSIZE
#define DUK_TVAL_SET_TVAL_UPDREF_FAST
#define DUK_STR_BUFFER_TOO_LONG
#define DUK__BP_RELATIONAL
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)
#define DUK__BP_BOR
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject(duk_context *ctx, duk_idx_t index)
#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 void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx)
#define DUK_ASC_UC_C
#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)
#define DUK__HAS_TERM
#define DUK_STRIDX_DEC_ENV
DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx)
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]
DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
#define DUK__DELETED_MARKER(heap)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx)
DUK_INTERNAL const char * duk_str_unterminated_stmt
DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n)
DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap)
#define DUK_HTHREAD_STRING___PROTO__(thr)
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)
#define DUK_STRIDX_LC_FUNCTION
DUK_INTERNAL_DECL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr)
DUK_INTERNAL_DECL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h)
#define DUK_HBUFFEROBJECT_VALID_SLICE(h)
DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act)
#define DUK_HOBJECT_CLASS_FUNCTION
DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x)
#define DUK_ASC_LC_B
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)
#define DUK_ASC_BACKSLASH
DUK_EXTERNAL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2)
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx)
#define DUK_ENC_OP_A_B_C(op, a, b, c)
#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)
#define DUK__SM_PLUS
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_INTERNAL_DECL const char * duk_push_string_readable(duk_context *ctx, duk_idx_t index)
DUK_LOCAL void duk__vm_bitwise_not(duk_hthread *thr, duk_tval *tv_x, duk_uint_fast_t idx_z)
#define DUK_TOK_WITH
#define DUK_STRDATA_DATA_LENGTH
struct duk_compiler_instr duk_compiler_instr
#define DUK_STRIDX_OWN_KEYS
#define DUK_HEAP_DBG_RATELIMIT_OPCODES
DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
#define DUK__BP_COMMA
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)
#define DUK__STRIDX_BITS
DUK_INTERNAL_DECL duk_tval * duk_get_borrowed_this_tval(duk_context *ctx)
DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256]
#define DUK_EXTRAOP_ENDFIN
#define DUK_OP_BXOR
DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16]
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)
#define DUK_STRIDX_INDEX
#define duk_js_samevalue(tv_x, tv_y)
#define DUK_HTHREAD_STRING_INT_TARGET(thr)
#define DUK_DBG_CMD_STATUS
#define DUK__GETCONST_MAX_CONSTS_CHECK
#define DUK_STR_ARRAY_LENGTH_NOT_WRITABLE
#define DUK_STRIDX_INT_FINALIZER
DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem)
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv)
#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)
#define DUK_HOBJECT_CLASS_DATE
#define DUK__LENGTH_PROP_BITS
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)
DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val)
DUK_EXTERNAL void * duk_get_pointer(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_INCREF(thr, tv)
#define DUK_TOK_GE
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag)
DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2)
#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)
#define DUK__SM_NUL
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx)
DUK_INTERNAL const duk_uint8_t duk_lc_digits[36]
DUK_INTERNAL const char * duk_str_array_length_over_2g
DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags)
#define DUK_REALLOC_INDIRECT(heap, cb, ud, newsize)
#define DUK_PROPDESC_FLAG_ACCESSOR
#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx)
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)
#define DUK_EXTRAOP_LDNULL
DUK_LOCAL void duk__free_stringtable(duk_heap *heap)
#define DUK_REOP_INVRANGES
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, h)
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)
#define DUK__PROP_TYPE_ACCESSOR
#define DUK_BW_RESET_SIZE(thr, bw_ctx)
#define DUK_HCOMPILEDFUNCTION_SET_DATA(heap, h, v)
#define DUK_ASC_LC_L
DUK_LOCAL duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key)
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx)
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_HOBJECT_E_GET_KEY(heap, h, i)
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_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)
#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)
DUK_INTERNAL_DECL void duk_hthread_callstack_grow(duk_hthread *thr)
#define DUK_ERROR_INTERNAL_DEFMSG(thr)
#define DUK_DPRINT
#define DUK_STR_CANNOT_DELETE_IDENTIFIER
#define DUK_PROPDESC_FLAGS_E
#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__IDX_UNDEFINED
#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS
DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL const char * duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len)
#define DUK_PROPDESC_FLAGS_WE
#define DUK_TOK_ALSHIFT_EQ
#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)
#define DUK_VSRESIZE_FLAG_SHRINK
#define DUK_ASSERT(x)
DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256]
#define DUK__EXPR_RBP_MASK
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_STR_NOT_NULL
#define DUK__ASSERT_LEFT(n)
DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h)
DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx)
DUK_EXTERNAL void * duk_alloc(duk_context *ctx, duk_size_t size)
#define duk_push_idx(ctx, val)
#define DUK_DBG_CMD_RESUME
#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_TOK_MUL_EQ
#define DUK__BP_CALL
#define DUK_STRIDX_REG_EXP
#define DUK_STRIDX_UC_STRING
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_STR_EMPTY_EXPR_NOT_ALLOWED
DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h)
DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags)
#define DUK_ASC_MINUS
#define DUK_BIDX_STRING_PROTOTYPE
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year)
#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
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx)
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_TVAL_IS_POINTER(tv)
#define DUK_STRIDX_LC_UNDEFINED
#define DUK_TOK_TRUE
#define DUK_HOBJECT_GET_ASIZE(h)
#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)
#define DUK_DBG_CMD_THROW
DUK_INTERNAL_DECL void duk_to_object_class_string_top(duk_context *ctx)
#define DUK_HTHREAD_STRING_INT_REGBASE(thr)
DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap)
DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index)
#define DUK_REOP_SAVE
DUK_INTERNAL const char * duk_str_setter_undefined
#define DUK_STR_JSONENC_RECLIMIT
#define DUK_TVAL_IS_UNUSED(tv)
#define DUK_ACT_FLAG_STRICT
#define DUK_HSTRING_GET_HASH(x)
#define DUK_TOK_LE
#define DUK_FREE(heap, ptr)
#define DUK_HOBJECT_FLAG_BUFFEROBJECT
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_HTHREAD_STRING_INT_THREAD(thr)
#define DUK_HEAPHDR_HAS_TEMPROOT(h)
#define DUK_ASC_UC_B
#define DUK__OBJ_LIT_KEY_GET
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx)
#define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(heap, h)
DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr)
#define DUK_LJ_TYPE_RETURN
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum)
DUK_INTERNAL const char * duk_str_invalid_getset_name
#define DUK_TOK_LAND
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(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]
#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap, h, i)
#define DUK_HOBJECT_GET_CLASS_STRING(heap, h)
#define DUK_HEAPHDR_HTYPE_VALID(h)
const duk_uint8_t duk_unicode_ids_noa[791]
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx)
#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE
#define DUK_PROPDESC_FLAGS_C
#define DUK_TOK_BXOR_EQ
DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs)
#define DUK_EXTRAOP_UNM
DUK_LOCAL duk_bool_t duk__resize_strtab_probe(duk_heap *heap)
#define DUK_OP_CSREGI
#define DUK_HTHREAD_STRING_INT_VARENV(thr)
DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze)
#define DUK_BIDX_INT32ARRAY_PROTOTYPE
#define DUK_MS_FLAG_NO_FINALIZERS
#define DUK_EXTRAOP_TYPEOFID
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx)
#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST
DUK_INTERNAL_DECL duk_hnativefunction * duk_get_hnativefunction(duk_context *ctx, duk_idx_t index)
#define DUK__OUTPUT_TYPE_LINENUMBER
#define DUK__ITER_FOREACH
#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__REGP(x)
#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)
#define DUK_OP_PUTPROP
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]
DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf)
#define DUK_BIDX_LOGGER_CONSTRUCTOR
DUK_INTERNAL const char * duk_str_const_limit
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx)
DUK_EXTERNAL const char * duk_api_global_filename
#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen)
DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap)
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx)
DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_EXTERNAL void duk_push_null(duk_context *ctx)
#define DUK_STR_NOT_OBJECT
#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)
DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth)
#define DUK_HOBJECT_IS_CALLABLE(h)
#define DUK_HOBJECT_SET_NOTAIL(h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx)
DUK_INTERNAL_DECL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length)
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
DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv)
#define DUK_STRIDX_ERR_THROW
DUK_INTERNAL_DECL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h)
#define DUK_STRIDX_DEFINE_PROPERTY
#define DUK_ERROR_API(thr, msg)
#define DUK_TOK_VAR
#define DUK_EXTRAOP_LNOT
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx)
DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect)
#define DUK_STR_REG_LIMIT
#define DUK_HTHREAD_STRING_INT_LEXENV(thr)
DUK_EXTERNAL void duk_pop_3(duk_context *ctx)
DUK_EXTERNAL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc)
DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt)
#define DUK_OP_LT
#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE
DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h)
#define DUK_HOBJECT_CLASS_AS_FLAGS(v)
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_CALL_FLAG_IS_TAILCALL
#define DUK_ASC_LCURLY
DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[]
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx)
#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)
DUK_INTERNAL_DECL duk_hstring * duk_js_typeof(duk_hthread *thr, duk_tval *tv_x)
#define DUK_OP_BASL
#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)
#define DUK__JSON_ENCSTR_CHUNKSIZE
#define DUK_DBG_CMD_ADDBREAK
#define DUK_EXTRAOP_ENDLABEL
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_STRIDX_VALUE
#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC
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_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_DEC_C(x)
#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_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__PROP_TYPE_BUILTIN
#define DUK__FUN()
DUK_INTERNAL const duk_c_function duk_bi_native_functions[149]
duk_uint32_t duk_regconst_t
#define DUK_ACT_FLAG_DIRECT_EVAL
DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata)
#define DUK_IVAL_PLAIN
DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t check_object_coercible)
DUK_EXTERNAL void duk_dup_top(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_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_bool_t duk_is_number(duk_context *ctx, duk_idx_t index)
#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_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos)
#define DUK_BIDX_GLOBAL_ENV
#define DUK_HOBJECT_IS_ENV(h)
DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx)
#define DUK__YEAR(x)
#define DUK_HEAPHDR_HAS_REACHABLE(h)
#define DUK__PI_MONTH
DUK_INTERNAL const char * duk_str_defaultvalue_coerce_failed
#define DUK_STRIDX_INT32_ARRAY
#define DUK_DBG_CMD_PAUSE
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, x, v)
#define DUK_TOK_NEW
DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect)
DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder)
DUK_INTERNAL_DECL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h)
#define DUK_HOBJECT_SET_STRICT(h)
#define DUK_ASC_COLON
#define DUK_CAT_FLAG_LEXENV_ACTIVE
#define DUK_EXTRAOP_NEWOBJ
#define DUK_TOK_COLON
#define DUK_ASC_LC_J
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD
#define DUK_STR_NOT_THREAD
#define DUK_N2S_FLAG_FORCE_EXP
DUK_INTERNAL_DECL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length)
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
#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)
#define DUK__DIGITCHAR(x)
#define DUK_HTHREAD_STRING_INT_VARMAP(thr)
#define DUK_OP_CALL
#define DUK_LFUNC_NARGS_VARARGS
#define DUK_HEAPHDR_GET_REFCOUNT(h)
#define DUK_TOK_REGEXP
#define DUK_ASC_LC_Y
#define DUK_ASC_LC_P
#define DUK_BC_OP_MAX
#define DUK_TVAL_SET_DOUBLE(tv, d)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx)
DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx)
#define DUK_ASC_SEMICOLON
#define DUK__ALLOCTEMP(comp_ctx)
#define DUK_LEXER_INITCTX(ctx)
#define DUK__BYTECODE_INITIAL_ALLOC
#define DUK_HOBJECT_IS_THREAD(h)
DUK_INTERNAL_DECL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type)
#define DUK_TVAL_GET_STRING(tv)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx)
#define DUK_OP_CLOSURE
DUK_LOCAL void duk__push_stridx(duk_context *ctx, duk_bitdecoder_ctx *bd)
#define DUK__BITPACK_FF
#define DUK_TOK_ELSE
DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL const char * duk_str_invalid_object_literal
#define DUK__IDX_EXPORTS
#define DUK_OP_SEQ
#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT
#define DUK_DBG_CMD_GETVAR
DUK_LOCAL void duk__vm_logical_not(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_z)
#define DUK_RE_COMPILE_TOKEN_LIMIT
#define DUK_STRIDX_NAME
static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6]
#define DUK__PM_YEAR
#define DUK_ASC_LF
DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index)
#define DUK_STR_INTERNAL_ERROR
#define DUK__BITPACK_UNDERSCORE
#define DUK_ASC_UC_D
DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index)
#define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr)
#define DUK_TOK_NULL
#define DUK__SM_SPACE
#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED
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)
#define DUK_HOBJECT_CMASK_NUMBER
#define DUK__IDX_REQUIRE_ID
#define DUK_BC_DECLVAR_FLAG_UNDEF_VALUE
#define DUK__PM_MONTH
#define DUK_LEXER_SETPOINT(ctx, pt)
#define DUK_STR_UNEXPECTED_END_OF_PATTERN
DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next)
#define DUK_STRIDX_FALSE
#define DUK_TOK_SEMICOLON
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)
#define DUK_EXTRAOP_BREAK
DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst)
#define DUK_LJ_TYPE_UNKNOWN
#define DUK__ITER_EVERY
#define DUK_TVAL_SET_FASTINT(tv, val)
#define DUK_BW_SPARE_SHIFT
DUK_INTERNAL const char * duk_str_compiler_recursion_limit
#define DUK__MAX_FUNCS
#define DUK_TAG_STRING
#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)
DUK_INTERNAL const char * duk_str_func_stmt_not_allowed
#define DUK_BC_BC_MAX
#define DUK_TOK_CASE
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)
#define DUK_DD(x)
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
#define DUK_OP_CSVAR
DUK_LOCAL int duk__protected_compact_object(duk_context *ctx)
DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx)
#define DUK_STRTAB_HIGHEST_32BIT_PRIME
#define DUK_STR_NOT_EXTENSIBLE
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_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr, duk_size_t act_idx)
DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr)
#define DUK_STR_EXPECTED_IDENTIFIER
#define DUK_HOBJECT_HAS_ARRAY_PART(h)
#define DUK_ASC_PLUS
#define DUK_HSTRING_DECREF(thr, h)
#define DUK_HEAPHDR_FLAG_FINALIZED
#define DUK__NO_BIDX_MARKER
DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx)
#define DUK_REOP_PERIOD
DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags)
DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64]
#define DUK_BIDX_ARRAY_PROTOTYPE
#define DUK_ASC_SPACE
#define DUK_TVAL_SET_NUMBER_CHKFAST(tv, d)
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)
#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
#define DUK_TOK_BOR_EQ
#define DUK__SM_COLON
DUK_INTERNAL const char * duk_str_callstack_limit
#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH
DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx)
DUK_EXTERNAL void duk_require_stack_top(duk_context *ctx, duk_idx_t top)
#define DUK_BC_JUMP_BIAS
#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)
DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_TOK_SNEQ
#define DUK_STR_COMPILER_RECURSION_LIMIT
DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx)
DUK_INTERNAL const char * duk_str_quantifier_too_many_copies
#define DUK_HTHREAD_STATE_RESUMED
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)
#define DUK_ERROR_UNSUPPORTED(thr, msg)
#define DUK_REOP_SQGREEDY
DUK_EXTERNAL void * duk_require_pointer(duk_context *ctx, duk_idx_t index)
#define DUK_TVAL_SET_TVAL_UPDREF
#define DUK_TOK_ALSHIFT
#define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap)
#define DUK_HOBJECT_IS_NATIVEFUNCTION(h)
const duk_uint8_t duk_unicode_caseconv_lc[616]
#define DUK_OP_LDINTX
#define DUK_BC_ABC_MIN
#define DUK_STR_ARRAY_LENGTH_OVER_2G
DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz)
#define DUK_ASC_UC_L
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(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
#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 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)
#define DUK_STR_NOT_FUNCTION
#define DUK_STR_FMT_INVALID_JSON
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x)
#define DUK_OP_POSTDECP
#define DUK_STRIDX_EXPORTS
#define DUK_DBG_CMD_APPNOTIFY
#define DUK_OP_RETURN
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_INTERNAL_DECL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx)
DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size)
#define DUK_HTHREAD_INCREF(thr, h)
#define DUK_RE_FLAG_GLOBAL
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)
#define DUK_TOK_DEBUGGER
#define DUK_DBG_IB_INT4
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_S2N_FLAG_ALLOW_AUTO_HEX_INT
#define DUK_RETOK_ATOM_DIGIT
#define DUK_ACT_FLAG_CONSTRUCT
#define DUK_TOK_FOR
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx)
#define DUK_TOK_DECREMENT
#define DUK_ASC_UC_W
#define DUK_BIDX_ERROR_PROTOTYPE
#define DUK_EXTRAOP_INITENUM
#define DUK_COMPILER_PEEPHOLE_MAXITER
#define DUK__PI_TZHOUR
#define DUK_OP_MPUTOBJI
#define DUK__IVAL_FLAG_REQUIRE_SHORT
DUK_LOCAL double duk__floor(double x)
#define DUK__LONGJMP_RETHROW
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)
DUK_INTERNAL_DECL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n)
#define DUK_OP_DIV
#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
#define DUK_BIDX_GLOBAL
#define DUK_BW_INSERT_ENSURE_BYTES(thr, bw, dst_off, buf, len)
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__pcall_prop_raw(duk_context *ctx)
#define DUK_DBG_IB_HEAPPTR
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx)
#define DUK_TVAL_IS_STRING(tv)
#define DUK_STRIDX_INT_LEXENV
DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr)
#define DUK_STR_NOT_CONSTRUCTABLE
DUK_INTERNAL_DECL duk_hobject * duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code)
#define DUK__CF_ACCEPT
#define DUK_ASC_LC_K
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, h)
DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx)
#define DUK_PROPDESC_FLAG_NO_OVERWRITE
#define DUK_STRIDX_DATA
#define DUK_LFUNC_FLAGS_PACK(magic, length, nargs)
#define DUK_ASC_LANGLE
#define DUK_HOBJECT_DECREF(thr, h)
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len)
#define DUK__FLD_32BIT
#define DUK_OP_DECLVAR
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx)
#define DUK_ALLOC_RAW(heap, size)
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 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_codepoint_t cp, duk_bitdecoder_ctx *bd_ctx)
#define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap, h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx)
#define DUK_ASC_LC_D
#define DUK_HOBJECT_CLASS_ERROR
DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc)
#define DUK_STR_INVALID_FOR
#define DUK_LEXER_TEMP_BUF_LIMIT
#define DUK_STRIDX_LC_INFO
#define DUK_STR_PARSE_ERROR
DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index)
#define DUK_CAT_FLAG_CATCH_ENABLED
#define DUK_TOK_FALSE
#define DUK_STR_INVALID_ARRAY_LITERAL
#define DUK_VSRESIZE_FLAG_COMPACT
DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues)
#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE
#define DUK_STRIDX_JOIN
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)
#define DUK__TAG_NUMBER
DUK_INTERNAL_DECL duk_hstring * duk_get_hstring(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)
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_ASC_UC_O
#define DUK_DBG_IB_BUF2
#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_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 void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t)
#define DUK_REOP_SPLIT2
DUK_INTERNAL_DECL void * duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud)
#define DUK_CATCHSTACK_DEFAULT_MAX
#define DUK_HOBJECT_FLAG_BOUND
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 void * duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize)
#define DUK_UNICODE_CP_ZWJ
#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)
DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index)
#define DUK_TOK_LPAREN
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp)
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
DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h)
#define DUK_TVAL_SET_POINTER(tv, hptr)
#define DUK_TOK_SWITCH
#define DUK_RAW_READ_U8(ptr)
DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap)
#define DUK_EXTRAOP_INSTOF
DUK_INTERNAL const char * duk_str_invalid_expression
#define DUK_REOP_LOOKPOS
#define DUK_HEAP_STRING_INT_VALUE(heap)
#define DUK__BP_LOR
DUK_INTERNAL const char * duk_str_bytecode_limit
#define DUK_HEAPHDR_HAS_READONLY(h)
DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch)
#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 void duk_hthread_sync_currpc(duk_hthread *thr)
#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_INTERNAL_DECL void duk_hthread_callstack_shrink_check(duk_hthread *thr)
DUK_EXTERNAL void * duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index)
#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_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx)
#define DUK_ASC_SINGLEQUOTE
#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
#define DUK_DBG_IB_LIGHTFUNC
#define DUK_DBG_CMD_STEPOUT
#define DUK_HEAPHDR_GET_FLAGS(h)
#define DUK_HOBJECT_CLASS_UINT8ARRAY
#define DUK_BIDX_NUMBER_PROTOTYPE
DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr)
#define DUK_TOK_MOD
DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[]
#define DUK__NUM_ISO8601_PARSER_PARTS
DUK_EXTERNAL duk_idx_t duk_push_object(duk_context *ctx)
#define DUK_STRIDX_LC_NULL
#define DUK_STRIDX_EMPTY_STRING
#define DUK__FLD_VARINT
#define DUK_DBG_CMD_GETLOCALS
#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE
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)
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)
#define DUK_STRTAB_GROW_ST_SIZE(n)
#define DUK_HTHREAD_STATE_RUNNING
#define DUK_OP_POSTDECR
DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx)
#define DUK_BIDX_UINT32ARRAY_PROTOTYPE
#define DUK_STRIDX_LC_DEBUG
DUK_INTERNAL_DECL duk_uint8_t * duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz)
#define DUK_ASC_UC_I
#define DUK_HOBJECT_CLASS_GLOBAL
#define DUK_REOP_LOOKNEG
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx)
#define DUK_STRIDX_INT_VARMAP
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)
#define DUK_STRIDX_UC_OBJECT
DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof)
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__dec_plain_string(duk_json_dec_ctx *js_ctx)
#define DUK_DBG_IB_STR4
#define DUK_STRIDX_LENGTH
#define DUK__BP_CONDITIONAL
#define DUK__BITPACK_SWITCH
#define DUK_RETOK_ASSERT_WORD_BOUNDARY
DUK_INTERNAL const char * duk_str_proxy_rejected
DUK_INTERNAL_DECL duk_hstring * duk_push_this_coercible_to_string(duk_context *ctx)
DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)
DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index)
#define DUK__BP_ADDITIVE
DUK_INTERNAL const char * duk_str_not_extensible
DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx)
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_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_OP_PREINCR
DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index)
#define DUK_PC2LINE_SKIP
#define DUK_JSON_FLAG_EXT_CUSTOM
#define DUK_OP_BAND
#define DUK_BIDX_REGEXP_CONSTRUCTOR
#define DUK_TVAL_CHKFAST_INPLACE(v)
DUK_INTERNAL_DECL duk_hobject * duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t idx_bottom)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx)
DUK_EXTERNAL const char * duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap)
#define DUK_DBG_IB_ERROR
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
#define DUK_STEP_TYPE_OVER
#define DUK_OP_MPUTARRI
DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index)
#define DUK_HSTRING_SET_CHARLEN(x, v)
#define DUK_STR_PROTOTYPE_CHAIN_LIMIT
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx)
DUK_EXTERNAL void * duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
#define DUK_HBUFFEROBJECT_ELEM_FLOAT64
#define DUK__VALSTACK_PROXY_LOOKUP
#define DUK_DBG_CMD_LISTBREAK
#define DUK_TVAL_SET_BOOLEAN_TRUE(v)
DUK_INTERNAL_DECL duk_hstring * duk_require_hstring(duk_context *ctx, duk_idx_t index)
#define DUK_HTHREAD_STRING_SET(thr)
DUK_LOCAL double duk__exp(double x)
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx)
#define DUK_DBG_CMD_STEPOVER
#define DUK_STRIDX_INT_VALUE
#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx)
#define DUK_REALLOC_RAW(heap, ptr, newsize)
DUK_INTERNAL const char * duk_str_alloc_failed
#define DUK_ENC_OP_A(op, a)
#define DUK_ASC_LC_H
#define DUK_BW_INIT_WITHBUF(thr, bw_ctx, buf)
#define DUK_HSTRING_FLAG_EXTDATA
DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val)
#define duk_push_hthread(ctx, h)
#define DUK_STRIDX_NAN
#define DUK_HBUFFEROBJECT_ELEM_UINT32
DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags)
DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x)
#define DUK_OP_ADD
#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_DBG_CMD_STEPINTO
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx)
#define DUK_HTHREAD_STRING_JX(thr)
#define DUK__BP_FOR_EXPR
#define DUK_HOBJECT_H_GET_INDEX(heap, h, i)
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_TOK_QUESTION
DUK_INTERNAL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber)
#define DUK_EXTRAOP_INVALID
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp)
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 const char * duk_str_invalid_array_literal
#define DUK__PI_YEAR
#define DUK__CHECK_SPACE()
DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name)
#define DUK__CLASS_BITS
#define DUK_TOK_CATCH
#define DUK__ALLOW_AUTO_SEMI_ALWAYS
#define DUK_STR_CYCLIC_INPUT
#define DUK_STRIDX_PC
DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_context *ctx)
#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_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx)
DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx)
DUK_INTERNAL const char * duk_str_not_buffer
#define DUK_ASC_LC_G
#define DUK_TOK_STRING
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_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx)
DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
#define DUK_TOK_RBRACKET
#define DUK__BC_INITIAL_INSTS
#define DUK_EXTRAOP_INITSET
#define DUK_TVAL_IS_DOUBLE(v)
#define DUK_EXTRAOP_LDFALSE
DUK_INTERNAL const char * duk_str_invalid_return
#define DUK_CAT_FLAG_FINALLY_ENABLED
#define DUK__IDX_REQUESTED_ID
#define DUK_STR_UNTERMINATED_STMT
DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)
#define DUK__BIDX_BITS
#define DUK_HTHREAD_STRING_INT_THIS(thr)
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_OP_EXTRA
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx)
DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index)
#define DUK_STRIDX_ARRAY_BUFFER
#define DUK_HOBJECT_CLASS_UINT32ARRAY
#define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)
#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap, 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_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_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)
#define DUK_ASC_PERCENT
DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y)
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)
#define DUK__STRING_CHAR_BITS
#define DUK__BP_POSTFIX
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)
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx)
#define DUK_HEAPHDR_SET_FLAGS(h, val)
#define DUK_RETOK_ATOM_START_CAPTURE_GROUP
#define DUK_JS_COMPILE_FLAG_FUNCEXPR
#define DUK_STRTAB_INITIAL_SIZE
#define DUK__HAS_VAL
DUK_LOCAL_DECL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num)
#define DUK_HOBJECT_CLASS_THREAD
#define DUK_DBG_CMD_DETACHING
DUK_LOCAL double duk__round_fixed(double x)
#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, expectname, lowmemstr)
#define DUK_OP_DELVAR
#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_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx)
#define DUK__FLD_8BIT
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out)
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
#define DUK_HSTRING_MAX_BYTELEN
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_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
#define DUK__BP_LAND
DUK_INTERNAL const char * duk_str_unimplemented
#define DUK_EXTRAOP_ENDCATCH
#define DUK_ASC_UC_R
#define DUK_STRIDX_TO_STRING
DUK_LOCAL void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx)
duk_uint32_t duk_instr_t
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp)
#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_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx)
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_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp)
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)
DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr)
#define DUK__NO_EXP
DUK_INTERNAL_DECL duk_hstring * duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj)
#define DUK__STRFTIME_BUF_SIZE
#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)
#define DUK_TOK_BREAK
#define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE
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)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset)
DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h)
#define DUK_OP_PREDECV
DUK_INTERNAL const char * duk_str_encode_failed
DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key)
DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x)
#define DUK_STRIDX_UINT16_ARRAY
#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_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv)
DUK_LOCAL_DECL duk_heaphdr * duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag)
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_TOK_RSHIFT_EQ
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx)
#define DUK_IVAL_ARITH
#define DUK__SYNC_AND_NULL_CURR_PC()
DUK_INTERNAL_DECL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj)
DUK_EXTERNAL const char * duk_json_encode(duk_context *ctx, duk_idx_t index)
#define DUK_TOK_COMMA
#define DUK_EXTRAOP_LDTHIS
#define DUK__ISTEMP(comp_ctx, x)
#define DUK_STR_TEMP_LIMIT
DUK_INTERNAL const char * duk_str_invalid_for
DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx)
DUK_INTERNAL_DECL duk_hthread * duk_get_hthread(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_require(duk_context *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)
#define DUK__PI_SECOND
#define DUK_REOP_JUMP
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
DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k)
#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_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_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_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx)
#define DUK_OP_BASR
DUK_INTERNAL const char * duk_str_unexpected_type
DUK_LOCAL_DECL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx)
struct duk_hbuffer_fixed duk_hbuffer_fixed
#define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap, h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx)
#define DUK_HOBJECT_IS_FUNCTION(h)
#define DUK__IS_TERMINAL
#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
#define DUK__IDX_DUKTAPE
struct duk_tval_struct duk_tval
#define DUK_STRIDX_LC_N
DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx)
#define DUK_DBG_IB_UNDEFINED
#define DUK_STRIDX_REQUIRE
#define DUK__L2()
#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)
#define DUK__HASH_UNUSED
#define DUK_ASC_STAR
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_array_prototype_reduce_shared(duk_context *ctx)
#define DUK_ASC_UC_G
#define DUK__STRICT()
#define DUK_STRIDX_EVAL
#define DUK_HOBJECT_SET_ENEXT(h, v)
#define DUK_STRIDX_LC_STRING
#define DUK_ASC_LC_I
#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap, x)
#define DUK_LFUNC_LENGTH_MIN
#define DUK__LONGJMP_RESTART
#define DUK_STR_INVALID_BASE
DUK_LOCAL const duk_uint8_t * duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n)
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_HSTRING_SET_HASH(x, v)
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)
DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags)
#define DUK_ASC_LBRACKET
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx)
DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16]
#define DUK_HOBJECT_CLASS_MAX
#define DUK__SM_T
DUK_EXTERNAL void * duk_get_heapptr(duk_context *ctx, duk_idx_t index)
#define DUK_DBG_IB_STR2
#define DUK_OP_BLSR
#define DUK_STR_WRONG_BUFFER_TYPE
#define DUK_D(x)
#define DUK_ASC_RCURLY
DUK_EXTERNAL void duk_push_undefined(duk_context *ctx)
#define DUK__L1()
#define DUK_DBG_ERR_UNSUPPORTED
#define DUK_BC_B_MIN
#define DUK_OP_LE
#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_LOCAL void duk__push_stridx_or_string(duk_context *ctx, duk_bitdecoder_ctx *bd)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx)
DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx)
#define DUK_STRIDX_INT_TARGET
#define DUK_STR_WITH_IN_STRICT_MODE
#define DUK_OP_MUL
#define DUK_BW_GET_PTR(thr, bw_ctx)
#define DUK_HOBJECT_FLAG_THREAD
#define DUK__ISDIGIT03(x)
#define DUK_STR_NOT_CONFIGURABLE
DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res)
DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256]
#define DUK_HSTRING_SET_ARRIDX(x)
#define DUK_HTHREAD_STRING_TO_JSON(thr)
#define DUK_EXTRAOP_DEBUGGER
#define DUK_STR_C_CALLSTACK_LIMIT
#define DUK__WEEKDAY_MOD_ADDER
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)
#define DUK_TOK_WHILE
DUK_INTERNAL_DECL duk_hthread * duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx)
DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx)
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)
#define DUK_OP_CSVARI
#define DUK_HTHREAD_STRING_REQUIRE(thr)
#define DUK_STRIDX_INT_TRACEDATA
#define DUK_ASC_HT
#define DUK__ALLOCTEMPS(comp_ctx, count)
#define DUK_ISPEC_REGCONST
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx)
DUK_EXTERNAL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index)
#define DUK__CF_NEG
#define DUK_HOBJECT_E_SET_FLAGS(heap, h, i, f)
#define DUK_TOK_CONTINUE
#define DUK__PROP_TYPE_BITS
#define DUK_S2N_MAX_EXPONENT
#define DUK__BI_PRINT(name, x)
DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token)
DUK_EXTERNAL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs)
#define DUK__RETHAND_FINISHED
#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]
DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len)
#define DUK_TAG_UNDEFINED
#define DUK_S2N_FLAG_ALLOW_PLUS
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx)
DUK_LOCAL void duk__mark_finalizable(duk_heap *heap)
#define DUK_HEAPHDR_HAS_FINALIZED(h)
#define DUK_DEC_BC(x)
DUK_INTERNAL const char * duk_str_with_in_strict_mode
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx)
DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index)
#define DUK_STR_INVALID_CONTEXT
#define DUK_HTHREAD_STRING_NAME(thr)
#define DUK_TOK_THROW
#define DUK_PROPDESC_FLAGS_WC
#define DUK__CONST_MARKER
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_INTERNAL_DECL void * duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud)
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_STR_UNSUPPORTED
#define DUK_HOBJECT_IS_DECENV(h)
#define DUK_STR_NOT_STRING
#define DUK_PROPDESC_FLAG_WRITABLE
#define DUK_HSTRING_SET_RESERVED_WORD(x)
#define DUK_DDPRINT
#define DUK_TOK_LOR
#define DUK_HEAP_GET_STRING(heap, idx)
DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index)
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_DDDPRINT
#define DUK_OP_GETPROP
#define DUK_HOBJECT_SET_ENVRECCLOSED(h)
DUK_EXTERNAL void duk_set_global_object(duk_context *ctx)
#define DUK__HASH_DELETED
#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT
DUK_EXTERNAL const char * duk_push_sprintf(duk_context *ctx, const char *fmt,...)
#define DUK_BC_LDINTX_SHIFT
#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING
#define DUK_CAT_TYPE_TCF
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx)
DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx)
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_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
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx)
#define DUK_REOP_BACKREFERENCE
DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx)
#define DUK_ASC_LC_R
#define DUK_STR_PUSH_BEYOND_ALLOC_STACK
#define DUK_STR_CALLSTACK_LIMIT
#define DUK__ISDIGIT47(x)
#define DUK__ARRAY_MID_JOIN_LIMIT
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx)
#define DUK__RECURSION_INCREASE(comp_ctx, thr)
#define DUK_ASC_ATSIGN
#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_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx)
#define DUK_OP_NEQ
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
#define DUK_RETOK_QUANTIFIER
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)
DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(duk_context *ctx)
#define DUK_HNATIVEFUNCTION_NARGS_VARARGS
#define DUK_STR_FUNC_LIMIT
#define DUK_STRIDX_LC_NUMBER
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)
DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv)
DUK_INTERNAL const char * duk_str_not_constructable
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx)
DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr)
#define DUK_TOK_DELETE
#define DUK_HSTRING_SET_ASCII(x)
#define DUK_ASC_QUESTION
#define DUK_STRIDX_DATE
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_INTERNAL_DECL duk_hobject * duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_hstring * duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val)
#define DUK_REOP_WIPERANGE
DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx)
DUK_EXTERNAL void duk_push_number(duk_context *ctx, duk_double_t val)
#define DUK__PROP_TYPE_STRIDX
#define DUK_TOK_ADD_EQ
DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top)
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)
#define DUK__PI_MINUTE
#define DUK_TOK_LBRACKET
DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count)
#define DUK_EXTRAOP_IN
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx)
DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx)
#define DUK_STRIDX_INFINITY
#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)
#define DUK_DBG_ERR_TOOMANY
#define DUK_TAG_OBJECT
DUK_INTERNAL_DECL duk_hnativefunction * duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_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)
#define DUK_DBG_IB_BUF4
#define DUK_HTHREAD_STRING_INT_CALLEE(thr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx)
#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ
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_TOK_CONST
#define DUK_OP_CSPROP
#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_TAG_BOOLEAN
#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)
#define DUK_HEAP_STRCACHE_SIZE
#define DUK_DBG_IB_TRUE
DUK_EXTERNAL void duk_require_function(duk_context *ctx, duk_idx_t index)
#define DUK_STRIDX_JSON
DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap)
#define DUK_ASC_UC_Z
#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)
#define DUK_HTHREAD_STRING_BYTE_OFFSET(thr)
#define DUK_GET_TVAL_NEGIDX(ctx, idx)
#define DUK_STRIDX_OBJ_ENV
DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16]
DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len)
#define DUK_ASSERT_TOP(ctx, n)
DUK_EXTERNAL void duk_push_false(duk_context *ctx)
#define DUK__PARSE_STATEMENTS_SLOTS
#define DUK_LJ_TYPE_RESUME
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
#define DUK_STRIDX_IGNORE_CASE
DUK_INTERNAL_DECL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj)
#define DUK__BITPACK_SEVENBIT
#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE
#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
#define DUK_OP_CALLI
DUK_LOCAL duk_uint8_t * duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p)
#define DUK_TOK_EOF
#define DUK_JS_COMPILE_FLAG_STRICT
DUK_EXTERNAL void duk_push_global_stash(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx)
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8]
DUK_INTERNAL_DECL duk_tval * duk_require_tval(duk_context *ctx, duk_idx_t index)
#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,...)
#define DUK_ASC_EQUALS
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_HTYPE_OBJECT
#define DUK_TOK_MINVAL
DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr)
#define DUK_STR_PROPERTY_IS_VIRTUAL
#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY
#define DUK_HOBJECT_FLAG_EXTENSIBLE
#define DUK_REOP_ASSERT_START
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx)
#define DUK__BP_MULTIPLICATIVE
#define DUK_STR_INVALID_REGEXP_FLAGS
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
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
#define DUK_RE_QUANTIFIER_INFINITE
#define DUK_DBG_IB_FALSE
#define duk_push_uarridx(ctx, val)
#define DUK_ASC_0
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)
#define DUK_N2S_FLAG_NO_ZERO_PAD
#define DUK_PROPDESC_IS_ENUMERABLE(p)
#define DUK_EXTRAOP_NEWARR
#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD
#define DUK_HOBJECT_SET_ASIZE(h, v)
#define DUK_ENC_OP_ABC(op, abc)
DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx)
#define DUK_DBG_CMD_PUTVAR
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx)
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)
#define DUK_TOK_RSHIFT
#define DUK__PROP_TYPE_STRING
#define DUK_PROPDESC_FLAGS_WEC
#define DUK_STRIDX_TO_TOK(x)
#define DUK_TOK_DIV
DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto)
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)
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__CHECK_BITMASK(table, cp)
DUK_LOCAL duk_hbufferobject * duk__get_bufobj_this(duk_context *ctx)
#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP
DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
#define DUK_STR_NOT_BOOLEAN
DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size)
#define DUK_ASC_LC_O
#define DUK_STRIDX_TO_LOG_STRING
DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_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)
#define DUK_TOK_BAND_EQ
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx)
#define DUK_DBG_IB_REPLY
#define DUK_STRIDX_INT_VARENV
#define DUK_TVAL_GET_LIGHTFUNC(tv, out_fp, out_flags)
#define DUK_HEAPHDR_INCREF(thr, h)
#define DUK_STRIDX_JSON_EXT_NAN
#define DUK_DBG_CMD_DELBREAK
const duk_uint8_t duk_unicode_ids_m_let_noa[42]
#define DUK__IDX_FRESH_REQUIRE
#define DUK_ALLOC_ZEROED(heap, size)
#define DUK_STR_CONST_LIMIT
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_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst)
#define DUK__MAGIC_BITS
#define DUK_STRIDX_FLOAT64_ARRAY
#define duk_js_strict_equals(tv_x, tv_y)
#define DUK_STRIDX_INPUT
#define DUK_BIDX_REGEXP_PROTOTYPE
DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index)
#define DUK__MAX_CONSTS
#define DUK_RETOK_ATOM_WHITE
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx)
DUK_INTERNAL const char * duk_str_jsonenc_reclimit
#define DUK_BIDX_OBJECT_CONSTRUCTOR
DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_DBG_CMD_LOG
DUK_INTERNAL_DECL duk_hbuffer * duk_require_hbuffer(duk_context *ctx, duk_idx_t index)
#define DUK_BC_EXTRAOP_MIN
#define DUK_HOBJECT_CLASS_UINT16ARRAY
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx)
#define DUK__BITPACK_LETTER_LIMIT
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__IDX_LASTCOMP
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_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_INTERNAL_DECL duk_hcompiledfunction * duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index)
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__dec_array(duk_json_dec_ctx *js_ctx)
#define DUK_STRIDX_MINUS_ZERO
#define DUK_EXTRAOP_INITSETI
#define DUK_OP_GT
#define DUK_CATCHSTACK_SHRINK_THRESHOLD
DUK_LOCAL_DECL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h)
#define DUK__VOLUNTARY_PERIODIC_GC(heap)
#define DUK_STRIDX_STACK
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
DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
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_TVAL_SET_BOOLEAN_FALSE(v)
DUK_INTERNAL const char * duk_str_concat_result_too_long
#define DUK__IDX_MODLOADED
#define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx)
DUK_EXTERNAL void duk_push_global_object(duk_context *ctx)
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)
#define DUK_DBG_CMD_DUMPHEAP
DUK_INTERNAL int duk_repl_isfinite(double x)
DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t index)
#define DUK_TOK_INSTANCEOF
#define DUK_LJ_TYPE_BREAK
#define DUK_LFUNC_NARGS_MIN
DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx)
DUK_LOCAL const duk_uint16_t duk__bufferobject_virtual_props[]
void *(* duk_mem_getptr)(duk_heap *heap, void *ud)
#define DUK_PROPDESC_FLAG_ENUMERABLE
DUK_INTERNAL_DECL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx)
DUK_INTERNAL duk_uint8_t duk_util_probe_steps[32]
#define DUK_HBUFFEROBJECT_ELEM_FLOAT32
#define DUK_ISPEC_VALUE
#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)
#define DUK_TVAL_SET_FASTINT_I32(tv, val)
#define DUK_STR_FUNC_STMT_NOT_ALLOWED
#define DUK_STRIDX_INT8_ARRAY
#define DUK_HEAPHDR_CLEAR_REACHABLE(h)
DUK_INTERNAL int duk_repl_fpclassify(double x)
#define DUK_EXTRAOP_LDTRUE
#define DUK__SM_MINUS
#define DUK_HSTRING_SET_INTERNAL(x)
#define DUK_PROPDESC_IS_ACCESSOR(p)
DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site)
#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT
#define DUK_TVAL_GET_BOOLEAN(tv)
DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst)
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 void duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags)
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)
DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx)
#define DUK_ASC_LC_E
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)
#define DUK_STRIDX_LC_ERROR
#define DUK_TOK_SUB_EQ
static duk_uint16_t duk__buffer_elemtype_copy_compatible[9]
#define DUK_STRIDX_UC_POINTER
#define DUK_VALSTACK_DEFAULT_MAX
#define DUK__PARSE_EXPR_SLOTS
#define DUK_OP_CSREG
#define DUK_HOBJECT_E_USE_HASH_LIMIT
DUK_EXTERNAL const char * duk_to_string(duk_context *ctx, duk_idx_t index)
#define DUK_DBG_ERR_NOTFOUND
DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h)
DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv)
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx)
DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx)
DUK_INTERNAL_DECL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h)
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_BC_DECLVAR_FLAG_FUNC_DECL
#define DUK_STEP_TYPE_OUT
#define DUK_RE_FLAG_IGNORE_CASE
#define DUK_STRIDX_TO_ISO_STRING
#define DUK_BW_WRITE_ENSURE_U8_2(thr, bw_ctx, val1, val2)
#define DUK__ITER_FILTER
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x)
#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_EXTRAOP_BNOT
#define DUK_GET_TVAL_POSIDX(ctx, idx)
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_LOCAL_DECL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj)
#define DUK_HBUFFER_GET_DATA_PTR(heap, x)
#define DUK_HOBJECT_INCREF(thr, h)
#define DUK_TOK_TYPEOF
DUK_INTERNAL_DECL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags)
#define DUK_ASC_GRAVE
#define DUK_BW_WRITE_ENSURE_BYTES(thr, bw_ctx, valptr, valsz)
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 const char * duk_str_not_callable
#define DUK_OP_CSPROPI
#define DUK_STR_INVALID_THROW
#define DUK_STR_INVALID_LVALUE
#define DUK_ACT_GET_FUNC(act)
#define DUK_EXTRAOP_LABEL
#define DUK__INTERNAL_ERROR(msg)
DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val)
#define DUK_OP_MPUTARR
#define DUK__EMIT_FLAG_A_IS_SOURCE
#define DUK_HSTRING_SET_BYTELEN(x, v)
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)
#define DUK__BP_MEMBER
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)
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)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key)
#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_hobject * duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj)
#define DUK__PM_TZMINUTE
#define DUK_TOK_BOR
DUK_INTERNAL_DECL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top)
#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_INTERNAL_DECL duk_hbuffer * duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx)
#define DUK_TOK_NEQ
#define DUK_TOK_ARSHIFT
#define DUK_NUM_BUILTINS
DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase)
#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)
DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst)
DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra)
#define DUK_TOK_PERIOD
DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to)
#define DUK__BP_EOF
#define DUK_STR_INVALID_DESCRIPTOR
#define DUK_TVAL_SET_UNDEFINED_UPDREF
#define DUK_STRIDX_INT_MAP
#define DUK_ASC_TILDE
#define DUK_HTHREAD_STRING_EMPTY_STRING(thr)
#define DUK_HEAPHDR_FLAG_FINALIZABLE
#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT
#define DUK_STR_NOT_NUMBER
DUK_LOCAL double duk__tan(double x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx)
DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr)
#define DUK_HOBJECT_SET_HSIZE(h, v)
#define DUK_STRIDX_CALLEE
DUK_INTERNAL const char * duk_str_decode_failed
#define DUK_CAT_HAS_CATCH_ENABLED(c)
#define DUK_HTHREAD_STATE_YIELDED
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx)
#define DUK_HOBJECT_HASHIDX_DELETED
#define DUK_BC_B_MAX
#define DUK_HOBJECT_HAS_ENVRECCLOSED(h)
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv)
DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256]
DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf)
DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx)
#define DUK__EMIT_FLAG_B_IS_TARGET
#define DUK_STRIDX_FILENAME
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)
#define DUK_DBG_IB_POINTER
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)
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_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr)
#define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h)
#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc)
#define DUK_ASC_UC_N
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_LJ_TYPE_NORMAL
#define DUK__MAX_RE_DECESC_DIGITS
DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx)
DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg)
#define DUK_ASC_4
#define DUK_FREE_RAW(heap, ptr)
#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)
static duk_uint16_t duk__date_magics[]
#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT
#define DUK_ASC_UC_F
DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size)
DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx)
DUK_INTERNAL const char * duk_str_invalid_quantifier_no_atom
#define DUK_TOK_MOD_EQ
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_ret_t duk_bi_duktape_object_act(duk_context *ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx)
DUK_INTERNAL_DECL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags)
#define DUK_TOK_RETURN
DUK_LOCAL_DECL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx)
DUK_EXTERNAL void duk_push_nan(duk_context *ctx)
#define DUK_CALL_FLAG_DIRECT_EVAL
#define DUK_TVAL_GET_HEAPHDR(tv)
#define DUK_STRIDX_ENV
#define DUK_HTHREAD_STRING_HEX(thr)
#define DUK_STRIDX_VALUE_OF
DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size)
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_DECL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx)
DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap)
#define DUK__READABLE_STRING_MAXCHARS
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)
#define DUK_STRIDX_LC_OBJECT
DUK_INTERNAL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message)
#define DUK_OP_LDCONST
#define DUK__NATIDX_BITS
DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj)
#define DUK_ASC_UNDERSCORE
#define DUK_DBG_CMD_GETHEAPOBJINFO
DUK_EXTERNAL void duk_dump_function(duk_context *ctx)
#define DUK_HOBJECT_E_GET_FLAGS(heap, h, i)
DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val)
#define DUK_LFUNC_MAGIC_MAX
DUK_LOCAL_DECL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap)
#define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED
#define DUK_RETOK_ASSERT_END
DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx)
#define DUK_STRIDX_TO_JSON
#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY
#define DUK_RAW_READ_U16_BE(ptr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx)
#define DUK__PI_DAY
#define DUK_STR_SPRINTF_TOO_LONG
#define DUK_RETOK_ATOM_BACKREFERENCE
DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv)
DUK_INTERNAL const char * duk_str_parse_error
DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr)
DUK_INTERNAL const char * duk_str_redefine_virt_prop
#define DUK_OP_REGEXP
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_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_ASC_RPAREN
#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)
#define DUK_STRIDX_PROTOTYPE
#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h, i)
#define DUK_STRIDX_ID
#define DUK_ASC_LC_F
#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)
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_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index)
#define DUK_CALLSTACK_GROW_STEP
DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv)
DUK_LOCAL duk_codepoint_t duk__decode_hexesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset)
#define DUK_JSON_FLAG_EXT_COMPATIBLE
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)
#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)
#define DUK_BW_SPARE_ADD
#define DUK_BC_BC_MIN
DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)
#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap, h)
#define DUK_ERROR(thr, err, msg)
#define DUK_STRIDX_CLOG
DUK_EXTERNAL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index)
DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx)
#define DUK__IDX_RESOLVED_ID
DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top)
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__RETHAND_RESTART
#define DUK_BIDX_RANGE_ERROR_PROTOTYPE
#define DUK_TOK_LCURLY
#define DUK_STRTAB_U32_MAX_STRLEN
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_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)
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_LOCAL_DECL duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival)
#define DUK_BW_PUSH_AS_STRING(thr, bw_ctx)
#define DUK_CAT_TYPE_LABEL
#define DUK_OP_PREINCV
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)
#define DUK_STR_NOT_BUFFER
#define DUK_STR_ENCODE_FAILED
DUK_INTERNAL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber)
DUK_INTERNAL_DECL void duk_hthread_catchstack_shrink_check(duk_hthread *thr)
#define DUK_STRIDX_COMPILE
#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_hnativefunction * duk_require_hnativefunction(duk_context *ctx, duk_idx_t index)
#define DUK__PROP_TYPE_DOUBLE
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)
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)
#define duk_hobject_get_internal_value_tval_ptr(heap, obj)
DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index)
#define DUK_ASC_LC_Q
#define DUK_EXTRAOP_CONTINUE
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx)
#define DUK_HEAP_SWITCH_THREAD(heap, newthr)
DUK_INTERNAL_DECL duk_idx_t duk_push_compiledfunction(duk_context *ctx)
#define DUK_STR_BOUND_CHAIN_LIMIT
DUK_INTERNAL const char * duk_str_push_beyond_alloc_stack
DUK_INTERNAL const char * duk_str_unexpected_regexp_token
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out)
DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr)
DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr)
#define DUK_TOK_IN
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx)
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)
#define DUK_ASC_COMMA
DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags)
#define DUK_BC_A_MIN
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)
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_HOBJECT_GET_ESIZE(h)
DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx)
#define DUK_HBUFFER_SET_SIZE(x, v)
#define DUK_IVAL_PROP
#define DUK_HEAPHDR_HAS_FINALIZABLE(h)
#define DUK_TVAL_SET_UNDEFINED(tv)
#define DUK_OP_POSTDECV
#define DUK_STR_NOT_UNDEFINED
#define DUK_TOK_TRY
#define DUK_STRIDX_UC_ERROR
DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv)
DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t index, duk_small_int_t func_stridx)
#define DUK_STR_UNEXPECTED_TYPE
#define DUK_ASC_LC_W
DUK_INTERNAL_DECL duk_idx_t duk_push_object_internal(duk_context *ctx)
#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_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__compact_objects(duk_heap *heap)
#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD
#define DUK_ASC_UC_A
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
DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr)
#define DUK_ASC_DOLLAR
#define DUK_HSTRING_FLAG_ARRIDX
DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep)
#define DUK__BITPACK_SWITCH1
#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)
#define DUK_BC_C_MIN
DUK_INTERNAL_DECL duk_tval * duk_get_tval(duk_context *ctx, duk_idx_t index)
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_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)
DUK_INTERNAL_DECL void duk_heap_force_strtab_resize(duk_heap *heap)
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_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 const char * duk_str_unexpected_closing_paren
#define DUK_STRIDX_MULTILINE
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)
DUK_LOCAL_DECL void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc)
#define DUK_ERROR_INTERNAL(thr, msg)
#define DUK_HOBJECT_H_GET_BASE(heap, h)
#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_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx)
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size)
#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_string_prototype_to_string(duk_context *ctx)
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)
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)
#define DUK_HTYPE_STRING
DUK_LOCAL duk_hthread * duk__get_temp_hthread(duk_heap *heap)
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx)
DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs)
#define DUK_REOP_SPLIT1
#define DUK_REOP_CHAR
DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap)
#define DUK_ASC_CARET
#define DUK_HNATIVEFUNCTION_NARGS_MAX
#define DUK_TAG_BUFFER
DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32]
DUK_INTERNAL_DECL void * duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud)
#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
#define DUK_BIDX_DUKTAPE
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx)
#define DUK_ASC_UC_U
DUK_LOCAL_DECL duk_compiler_instr * duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc)
#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_STRIDX_LC_FATAL
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx)
DUK_INTERNAL_DECL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len)
#define DUK__UNEMIT_1(js_ctx)
#define DUK_STR_NOT_POINTER
#define DUK__UPDATE_RND(rnd)
DUK_INTERNAL_DECL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits)
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)
#define DUK_OP_POSTINCV
#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_ASC_PERIOD
#define DUK_HTHREAD_STRING_INFINITY(thr)
#define DUK__RE_INITIAL_BUFSIZE
#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject(duk_context *ctx, duk_idx_t index)
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)
DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg)
#define DUK__IDX_MODULE
#define DUK_STR_INVALID_RETURN
double(* duk__one_arg_func)(double)
#define DUK_S2N_FLAG_ALLOW_EXP
#define DUK_HOBJECT_A_FAST_RESIZE_LIMIT
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx)
#define DUK_DBG_CMD_DETACH
#define DUK_HOBJECT_CMASK_ARRAY
#define DUK_BW_ENSURE_GETPTR(thr, bw_ctx, sz)
#define DUK_BC_LDINT_BIAS
DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
DUK_EXTERNAL void duk_debugger_pause(duk_context *ctx)
DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx)
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_STRIDX_LC_L
#define DUK_HOBJECT_CLASS_DATAVIEW
#define DUK_STRIDX_INT_SOURCE
#define DUK_EXTRAOP_INITGET
#define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap, h)
#define DUK_OP_NEW
#define DUK__OBJ_LIT_KEY_SET
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx)
#define DUK_HOBJECT_P_ALLOC_SIZE(h)
DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx)
#define DUK_BC_C_MAX
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap, x)
struct duk_lexer_codepoint duk_lexer_codepoint
#define DUK_STR_DUPLICATE_LABEL
#define DUK_ASC_LC_S
#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)
#define DUK_DBG_IB_REQUEST
DUK_EXTERNAL void * duk_realloc(duk_context *ctx, void *ptr, duk_size_t size)
#define DUK__BP_INVALID
#define DUK_HTYPE_BUFFER
#define DUK_STR_INVALID_OBJECT_LITERAL
DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length)
#define DUK_STR_UNEXPECTED_CLOSING_PAREN
#define DUK_HOBJECT_HAS_NOTAIL(h)
#define DUK_EXTRAOP_NOP
DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap)
DUK_LOCAL double duk__atan2(double x, double y)
#define DUK_HOBJECT_SET_NEWENV(h)
#define DUK__SER_NUMBER
#define DUK_HOBJECT_SET_CLASS_NUMBER(h, v)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx)
#define DUK_STR_PROXY_REVOKED
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_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]
#define DUK_RAW_READ_U32_BE(ptr)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx)
#define DUK_HEAP_DBG_RATELIMIT_MILLISECS
#define DUK_EXTRAOP_TYPEOF
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
#define DUK_JSON_FLAG_ASCII_ONLY
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)
#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)
#define DUK_REOP_SQMINIMAL
#define DUK_STRIDX_NEWLINE_4SPACE
#define DUK__MKESC(nybbles, esc1, esc2)
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 void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top)
#define DUK_CATCHSTACK_SHRINK_SPARE
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key)
#define DUK_ASC_LC_A
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
#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_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx)
DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb)
DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_constructor(duk_context *ctx)
DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits)
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)
#define DUK_HOBJECT_INCREF_ALLOWNULL(thr, h)
#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
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_OP_EQ
#define DUK_BC_A_MAX
#define duk_push_u32(ctx, val)
#define DUK_HTHREAD_STRING_CALLER(thr)
#define DUK_HTHREAD_STRING_JC(thr)
#define DUK__PM_HOUR
#define DUK_ASC_LC_V
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)
#define DUK_OP_GETVAR
#define DUK__VALSTACK_SPACE
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(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_regexp_prototype_test(duk_context *ctx)
#define DUK_EXTRAOP_INITGETI
#define DUK__NARGS_BITS
#define DUK__RND_BIT(rnd)
#define DUK__PM_MILLISECOND
#define DUK_ASC_LC_T
#define DUK_BIDX_INT16ARRAY_PROTOTYPE
DUK_INTERNAL const char * duk_str_func_limit
#define DUK_DEC_ABC(x)
#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY
#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap, h, i)
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_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size)
#define DUK_IVAL_NONE
DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x)
#define DUK__STRING_LENGTH_BITS
#define DUK_TVAL_SET_STRING(tv, hptr)
#define DUK_PROPDESC_FLAGS_W
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx)
DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx)
DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h)
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
#define DUK_STRIDX_CALLER
DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx)
#define DUK_BC_ABC_MAX
#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)
DUK_INTERNAL_DECL duk_tval * duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key)
#define DUK_ERROR_FMT1(thr, err, fmt, arg1)
DUK_LOCAL double duk__sqrt(double x)
#define DUK_TOK_FUNCTION
#define DUK__RE_BUFLEN(re_ctx)
#define DUK_OP_GE
DUK_INTERNAL const char * duk_str_invalid_backrefs
#define DUK_STR_UNIMPLEMENTED
DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr)
DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b)
DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx)
static duk_uint8_t * duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p)
#define DUK__BP_EQUALITY
DUK_INTERNAL_DECL void duk_push_hobject(duk_context *ctx, duk_hobject *h)
#define DUK_UNICODE_MAX_XUTF8_LENGTH
#define DUK_TOK_SEQ
DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size)
#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES
DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p)
DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx)
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_string_prototype_caseconv_shared(duk_context *ctx)
#define DUK__EMIT_FLAG_NO_SHUFFLE_C
DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen)
#define DUK__PI_MILLISECOND
#define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)
#define DUK_STR_INVALID_BACKREFS
#define DUK__ISCONST(comp_ctx, x)
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx)
#define DUK_TVAL_IS_BOOLEAN(tv)
#define DUK_STRIDX_GET
#define DUK_BIDX_UINT16ARRAY_PROTOTYPE
DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t index)
#define DUK_HSTRING_FLAG_INTERNAL
#define DUK_EXTRAOP_LDUNDEF
#define DUK__APPENDBUFFER(lex_ctx, x)
#define DUK__RECURSION_DECREASE(comp_ctx, thr)
#define DUK_TVAL_SET_NUMBER(tv, val)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv)
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(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_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata)
#define DUK_HBUFFER_GET_SIZE(x)
DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr)
#define DUK__BP_CLOSING
#define DUK_ASC_UC_E
#define DUK_TOK_RPAREN
#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)
DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx)
DUK_INTERNAL_DECL duk_hobject * duk_push_this_coercible_to_object(duk_context *ctx)
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_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx)
#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)
#define DUK_ASC_3
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(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)
DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len)
#define DUK_TVAL_SET_FASTINT_I32_UPDREF
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen)
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_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res)
#define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap, h)
#define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap, h)
DUK_LOCAL_DECL void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_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)
DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id)
#define DUK__SM_Z
#define DUK_HBUFFEROBJECT_ELEM_UINT8
DUK_INTERNAL_DECL duk_activation * duk_hthread_get_current_activation(duk_hthread *thr)
#define DUK_HOBJECT_CLASS_FLOAT64ARRAY
#define DUK_TOK_VOID
#define DUK_VALSTACK_INTERNAL_EXTRA
#define DUK_ASC_HASH
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx)
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 duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p)
#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_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_BC_OP_MIN
#define DUK_CALL_FLAG_IGNORE_RECLIMIT
DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx)
#define DUK_DBG_CMD_EVAL
#define DUK_TAG_UNUSED
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)
DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv)
DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags)
#define DUK_HOBJECT_HAS_NAMEBINDING(h)
#define DUK__OUTPUT_TYPE_FILENAME
DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg)
#define DUK_TAG_LIGHTFUNC
DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags)
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx)
#define DUK_RETOK_ATOM_CHAR
DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx)
DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags)
DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx)
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)
#define DUK_BC_CALL_FLAG_TAILCALL
#define DUK_NUM_ALL_BUILTINS
#define DUK_STRIDX_JSON_EXT_POSINF
DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_context *ctx)
DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h)
DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx)
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)
DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t idx_key)
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx)
DUK_INTERNAL const char * duk_str_buffer_too_long
#define DUK_STRIDX_JSON_EXT_FUNCTION1
DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc)
#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_logger_prototype_raw(duk_context *ctx)
#define DUK_OP_NEWI
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx)
#define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS
DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx)
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_nodejs_buffer_tojson(duk_context *ctx)
#define DUK_LEXER_BUFFER_SIZE
#define DUK_HEAP_NUM_STRINGS
#define DUK_LEXER_WINDOW_SIZE
#define DUK_HEAP_MAX_BREAKPOINTS
#define DUK_STRTAB_CHAIN_SIZE
#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